/*
 *
 * Copyright (c) 2007
 * Adrian Michel
 * http://www.tradery.com
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Adrian Michel makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
*/

package  com.tradery.contentmodel;

import java.util.Stack;
import java.util.Vector;
import com.tradery.contract.Contract;

  /**
   * these methods populate the syntax tree using the reverse Polish notation
   * so (a,b)*|(c,d) will be expressed as:
   * pushOr
   * pushStar
   * pushAnd
   * addOperand( "a" )
   * addOperand( "b" )
   * pop(2) (2 because of the And and Star -brings us back to the root (OR) level)
   * pushAnd
   * addOperand( "c" )
   * addOperand( "d" )
   * Note: addOperand doesn't change TOS, so there is no need to pop after a addOperand
   */


public class ReversePolishNotationFE extends AbstractExpression
{
  // these two are used when constructing the syntax tree with push/pop operations
  private ModelNode crtNode = null;
  private Stack binaryExpressionStack = new Stack();

  public ReversePolishNotationFE( String name ) { super( name ); }

  public void star( String name ) { pushOperator( makeStarNode( name ) ); }
  public void plus( String name ) { pushOperator( makePlusNode( name ) ); }
  public void opt( String name ) { pushOperator( makeOptNode( name ) ); }
  public void neutral( String name ) { pushOperator( makeNeutralNode( name ) ); }
  public void or( String name ) { pushOperator( makeOrNode( name ) ); }
  public void and( String name ) { pushOperator( makeAndNode( name ) ); }
  public void all( String name ) { pushOperator( makeAllNode( name ) ); }
  protected void realRange( String name, int min, int max )
    throws BadLimitsException
  {
    pushOperator( makeRangeNode( name, min, max ) );
  }

  private void pushOperator( OperatorNode node )
  {
    if( Contract.REQUIRE )
      Contract.require( node != null );
    binaryExpressionStack.push( crtNode = addNode( crtNode, node ) );
  }

  public void symbols( Vector operands )
  {
    if( Contract.REQUIRE )
      Contract.require( operands != null );

    for( int n = 0; n < operands.size(); n++ )
      // create the word node for the string n
      symbol( (String)operands.elementAt( n ) );
  }


  public void symbol( String operand ) { addNode( crtNode, makeSymbolNode( operand ) ); }

  public void pop()
  {
    binaryExpressionStack.pop();
    if( !binaryExpressionStack.empty() )
      crtNode = (ModelNode)binaryExpressionStack.peek();
  }

  //
  public void push() {}
}