/// <summary> Pop the next operation off the stack and build a non-terminal node
        /// around it, poping the next two items from the expression stack
        /// as its children
        /// </summary>
        private void  popOperation()
        {
            Operator op = (Operator)m_opStack.Pop();

            /* dispose of stack place holder ops (e.g.. OPEN_PAREN and OPEN_BRACKET) */
            if (op.precedence < 0)
            {
                return;
            }

            if (IndirectionOperatorAllowed)
            {
                /*
                 * Special case to support trailing dot syntax (e.g. a.b. )
                 * If DotOp and nothing on stack then we convert to
                 * an indirection op
                 */
                if (op == Operator.DIRECT_SELECT && m_expStack.Count < 2)
                {
                    op = Operator.INDIRECTION;
                }
            }

            // create operation and set its nodes
            NonTerminalExp node = op.createExpNode();

            node.RightChild = (ValueExp)m_expStack.Pop();

            if (!(node is SingleArgumentExp))
            {
                node.LeftChild = (ValueExp)m_expStack.Pop();
            }

            m_expStack.Push(node);
        }
        public static Operator SUBSCRIPT     = new Operator(17, "Operator.SUBSCRIPT", null, Type.GetType("Flash.Tools.Debugger.Expression.SubscriptExp"));   // a[k]; see ASTBuilder.addOp() //$NON-NLS-1$

        /// <summary> We create an empty non-terminal node of the given type based on the
        /// operator.
        /// </summary>
        public NonTerminalExp createExpNode()     // throws UnknownOperationException
        {
            NonTerminalExp node = null;

            if (expressionNodeClass == null)
            {
                throw new UnknownOperationException(this);
            }
            else
            {
                try
                {
                    node = (NonTerminalExp)expressionNodeClass.GetConstructor(Type.EmptyTypes).Invoke(null);
                }
                catch (OutOfMemoryException e)
                {
                    // should never happen
                    if (Trace.error)
                    {
                        Trace.trace(e.Message);
                    }
                }
                catch (AccessViolationException e)
                {
                    // should never happen
                    if (Trace.error)
                    {
                        Trace.trace(e.Message);
                    }
                }
            }

            return(node);
        }