/*
 *
 * 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 com.tradery.collections.NaryTree;

import java.util.Stack;

public class DirectNotationFE extends AbstractExpression
{
  private class XTree extends NaryTree
  {
    private NaryTree.Node crtNode = null;
    private char crtOp = 0;

    // this is normally used for symbols
    void addMakeCrt( NaryTree.Node node )
    {
      if( crtNode == null )
        crtNode = setRoot( node );
      else
        crtNode = crtNode.addSiblingToBack( node );
    }

    // this is normally used for and/or operators
    void add( NaryTree.Node node ) { if( crtOp == 0 ) { insertParentToBack( crtNode, node ); crtOp = 1; } }
    void add1( NaryTree.Node node ) { insertParentToBack( crtNode, node ); crtNode = node; }

    void addSubtree( NaryTree tree )
    {
      NaryTree.Node node = tree.getRoot();
      if( isRoot( crtNode ) )
        addChildTreeToBack( crtNode, tree );
      else
        this.addSiblingTreeToBack( crtNode, tree );
      crtNode = node;
    }
  }

  private Stack stack = new Stack();
  private XTree crtTree = new XTree();

  public DirectNotationFE( String name ) { super( name ); }
  public DirectNotationFE( String name, String expression )
    throws BadLimitsException, AmbiguousContentModelException
  {
    super( name );

    parse( expression );
    compile();
  }

  void addUnaryOp( SyntaxTree.ModelNode op ) { crtTree.add1( op ); }
  void addNaryOp( SyntaxTree.ModelNode op ) { crtTree.add( op ); }

  public void star( String name ) { addUnaryOp( makeStarNode( name ) ); }
  public void plus( String name ) { addUnaryOp( makePlusNode( name ) ); }
  public void opt( String name ) { addUnaryOp( makeOptNode( name ) ); }
  protected void realRange( String name, int min, int max ) throws BadLimitsException
  {
    addUnaryOp( makeRangeNode( name, min, max ) );
  }

  public void neutral( String name ) { addUnaryOp( makeNeutralNode( name ) ); }

  public void and( String name ) { addNaryOp( makeAndNode( name ) ); }
  public void or( String name ) { addNaryOp( makeOrNode( name ) ); }
  public void all( String name ) { addNaryOp( makeAllNode( name ) ); }

  public void symbol( String w ) { crtTree.addMakeCrt( makeSymbolNode( w ) ); }

  public void pop()
  {
    XTree tree = (XTree)stack.pop();
    tree.addSubtree( crtTree );
    crtTree = tree;
  }

  public void push()
  {
    stack.push( crtTree );
    crtTree = new XTree();
  }

  public void parse( String str  )
    throws BadLimitsException
  {
    super.parse( str );
    Node root = crtTree.getRoot();
    if( root != null )
      setRoot( crtTree.getRoot() );
  }



}