Esempio n. 1
0
        internal DataExpression(DataTable?table, string?expression, Type?type)
        {
            ExpressionParser parser = new ExpressionParser(table);

            parser.LoadExpression(expression);

            _originalExpression = expression;
            _expr = null;

            // Note: nobody seems to pass a null expression in the codebase
            if (expression != null)
            {
                _storageType = DataStorage.GetStorageType(type);
                if (_storageType == StorageType.BigInteger)
                {
                    throw ExprException.UnsupportedDataType(type !);
                }

                _dataType = type;
                _expr     = parser.Parse();
                _parsed   = true;
                if (_expr != null && table != null)
                {
                    Bind(table);
                }
                else
                {
                    _bound = false;
                }
            }
        }
Esempio n. 2
0
        internal VariableDeclarationStatementNode(IdentifierNode identifier,
                                                  TypeSpecNode?type,
                                                  ExpressionNode?value,
                                                  bool isReadOnly,
                                                  int lineNumber,
                                                  int index) : base(lineNumber, index)
        {
            VariableIdentifierNode            = identifier;
            VariableIdentifierNode.ParentNode = this;

            TypeSpecNode = type;
            if (TypeSpecNode != null)
            {
                TypeSpecNode.ParentNode = this;
            }

            AssignedExpressionNode = value;
            if (AssignedExpressionNode != null)
            {
                AssignedExpressionNode.ParentNode = this;
            }


            IsReadOnly = isReadOnly;
        }
Esempio n. 3
0
        public ExpressionNode?ParseNextExpression(ref int index)
        {
            Debug.Assert(Lexemes.Count > index & index >= 0);
            ExpressionNode?expression = ParseNextExpressionInternal(ref index);

            index++;
            return(expression);
        }
 public IEnumerable <string> Transform(ExtendsNode item)
 {
     if (ShouldRender == false)
     {
         throw new NotImplementedException();
     }
     _NextTemplate = item.Template;
     yield break;
 }
Esempio n. 5
0
 public Select(DataTable table, string?filterExpression, string?sort, DataViewRowState recordStates)
 {
     _table       = table;
     _indexFields = table.ParseSortString(sort);
     if (filterExpression != null && filterExpression.Length > 0)
     {
         _rowFilter  = new DataExpression(_table, filterExpression);
         _expression = _rowFilter.ExpressionNode;
     }
     _recordStates = recordStates;
 }
Esempio n. 6
0
        internal static bool TryParseFor(JinjaEnvironment environment, Lexer lexer, ILookaroundEnumerator <ParsingNode> enumerator, [NotNullWhen(true)] out ASTNode?parsedNode)
        {
            ContainerNode? elseBlock  = null;
            ExpressionNode?filterNode = null;

            parsedNode = default;

            if (ForParser.StartBlock.TryParse(enumerator.Current, out var outsideStart, out var primaryInsideStart) == false)
            {
                return(false);
            }
            var primaryStartParsingNode = enumerator.Current;

            if (ForParser.StartBlock.TryGetAccumulations(ForParser.ForState.VariableNames, out var variableNames) == false || variableNames.Length == 0)
            {
                throw new NotImplementedException();
            }
            if (ForParser.StartBlock.TryGetAccumulation(ForParser.ForState.Expression, 0, out var expression) == false)
            {
                throw new NotImplementedException();
            }
            if (ForParser.StartBlock.TryGetAccumulation(ForParser.ForState.Filter, 0, out string?filter))
            {
                filterNode = ExpressionNode.FromString(environment, filter);
            }
            ForParser.StartBlock.TryGetVariable <bool>("recursive", out var recursive);
            enumerator.MoveNext();
            var primaryBlockChildren = ASTGenerator.ParseUntilFailure(environment, lexer, enumerator).ToArray();

            ContainerNode primaryBlock;

            if (ForParser.ElseBlock.TryParse(enumerator.Current, out var primaryInsideEnd, out var elseInsideStart))
            {
                var elseStartParsingNode = enumerator.Current;
                enumerator.MoveNext();
                var elseBlockChildren = ASTGenerator.ParseUntilFailure(environment, lexer, enumerator).ToArray();
                if (ForParser.EndBlock.TryParse(enumerator.Current, out var elseInsideEnd, out var outsideEnd) == false)
                {
                    throw new NotImplementedException();
                }

                primaryBlock = new ContainerNode(primaryStartParsingNode, primaryBlockChildren, null,
                                                 new WhiteSpaceControlSet(primaryInsideStart, primaryInsideEnd));
                elseBlock = new ContainerNode(elseStartParsingNode, elseBlockChildren, null,
                                              new WhiteSpaceControlSet(elseInsideStart, elseInsideEnd));
                parsedNode = new ForNode(primaryBlock, elseBlock, variableNames, ExpressionNode.FromString(environment, expression),
                                         filterNode, recursive, enumerator.Current, new WhiteSpaceControlSet(outsideStart, outsideEnd));
                return(true);
            }
        private StatementNode?ParseExpressionStatement(ref int index)
        {
            ExpressionNode?expression = expressionParser.ParseNextExpression(ref index);

            if (expression == null)
            {
                return(null);
            }

            return(expression switch
            {
                FunctionCallExpressionNode functionCall => ParseFunctionCallStatement(functionCall, ref index),
                IdentifierExpressionNode identifierExpression => ParseVariableAssignmentStatement(ref index, identifierExpression.IdentifierNode, expression),
                _ => Error(),
            });
Esempio n. 8
0
 internal ForNode(ContainerNode primaryBlock, ContainerNode?elseBlock,
                  string[] variableNames, object?expression, ExpressionNode?filter, bool recursive, ParsingNode?endParsingNode, WhiteSpaceControlSet?whiteSpace = null)
     : base(
         startParsingNode: null,
         children: primaryBlock.YieldOne().Concat(elseBlock?.YieldOne() ?? Enumerable.Empty <ContainerNode>()),
         endParsingNode: endParsingNode
         )
 {
     PrimaryBlock           = primaryBlock;
     ElseBlock              = elseBlock;
     VariableNames          = variableNames;
     Filter                 = filter;
     WhiteSpaceControl      = whiteSpace ?? new WhiteSpaceControlSet();
     Recursive              = recursive;
     AlreadyEvaluatedObject = expression;
 }
Esempio n. 9
0
        private ExpressionNode?ParseNextExpressionInternal(ref int index,
                                                           bool includeOperations = true)
        {
            ExpressionNode?expression = ParseSubExpression(ref index);

            if (expression == null)
            {
                return(null);
            }

            ParseAfterSubExpression(ref expression, ref index, includeOperations);

            if (expression is BinaryOperationChain chain)
            {
                expression = chain.Resolve();
            }

            return(expression);
        }
Esempio n. 10
0
        private void ParseAfterSubExpression(ref ExpressionNode?expression,
                                             ref int index,
                                             bool includeOperations = true)
        {
            while (true)
            {
                switch (Lexemes.TryGet(index + 1))
                {
                case IOperatorLexeme operatorLexeme when includeOperations:
                    index++;
                    ParseOperationChain(operatorLexeme, ref expression, ref index);
                    return;

                case SyntaxCharacterLexeme {
                        SyntaxCharacter: SyntaxCharacter.ParenthesisOpening
                } :
                    index++;
                    ParseFunctionCall(ref expression, ref index);
                    continue;
Esempio n. 11
0
        internal void Bind(DataTable?table)
        {
            _table = table;

            if (table == null)
            {
                return;
            }

            if (_expr != null)
            {
                Debug.Assert(_parsed, "Invalid calling order: Bind() before Parse()");
                List <DataColumn> list = new List <DataColumn>();
                _expr.Bind(table, list);
                _expr       = _expr.Optimize();
                _table      = table;
                _bound      = true;
                _dependency = list.ToArray();
            }
        }
        private ForStatementNode?ParseForStatement(ref int index)
        {
            int lineNumber = lexemes[index].LineNumber;
            int nodeIndex  = lexemes[index].Index;

            index++;

            if (!ParseForVariableSpecification(ref index,
                                               out IdentifierNode? identifier,
                                               out ExpressionNode? initialValue,
                                               out bool declaresNew))
            {
                return(null);
            }

            ExpressionNode?condition = null;

            if (lexemes.TryGet(index) is KeywordLexeme {
                Keyword: ReservedKeyword.While
            })
        public IEnumerable <string> Transform(TemplateNode item)
        {
            var toRender = item;

            while (true)
            {
                foreach (var output in TransformAll(toRender.Children))
                {
                    yield return(output);
                }


                if (_NextTemplate == null)
                {
                    break;
                }

                var nextTemplateObj = Environment.Evaluation.EvaluateDynamic(_NextTemplate.ExpressionParserNode, ExpressionParserTransformer);
                _NextTemplate = null;
                switch (nextTemplateObj)
                {
                case DynamicTemplate d:
                    toRender = d.TemplateNode;
                    break;

                case string templateName:
                    var temp = Environment.GetDynamicTemplate(templateName);
                    if (!(temp is DynamicTemplate dt))
                    {
                        throw new NotImplementedException();
                    }
                    toRender = dt.TemplateNode;
                    break;

                default:
                    throw new NotImplementedException();
                }
            }
        }
Esempio n. 14
0
        internal ForStatementNode(IdentifierNode identifier,
                                  bool declaresNew,
                                  ExpressionNode?initialValue,
                                  ExpressionNode?condition,
                                  ExpressionNode?withValue,
                                  StatementCollectionNode statements,
                                  int lineNumber,
                                  int index) : base(lineNumber, index)
        {
            Debug.Assert((condition != null) | (withValue != null));

            VariableIdentifierNode = identifier;
            identifier.ParentNode  = this;

            DeclaresNew = declaresNew;

            InitialValueNode = initialValue;
            if (initialValue != null)
            {
                initialValue.ParentNode = this;
            }

            ConditionNode = condition;
            if (condition != null)
            {
                condition.ParentNode = this;
            }

            WithExpressionNode = withValue;
            if (withValue != null)
            {
                withValue.ParentNode = this;
            }

            StatementNodes            = statements;
            StatementNodes.ParentNode = this;
        }
Esempio n. 15
0
        internal void LoadExpression(string?data)
        {
            int length;

            if (data == null)
            {
                length = 0;
                _text  = new char[length + 1];
            }
            else
            {
                length = data.Length;
                _text  = new char[length + 1];
                data.CopyTo(0, _text, 0, length);
            }

            _text[length] = '\0';

            if (_expression != null)
            {
                // free all nodes
                _expression = null;
            }
        }
Esempio n. 16
0
        public (ExpressionNode?Node, SourceMode Mode) Parse(ref CharacterReader r)
        {
            ExpressionNode?rootNode = null;
            ExpressionNode?node     = null;

            var(astNodes, mode) = BindingExpressionGrammar.Parse(ref r);

            foreach (var astNode in astNodes)
            {
                ExpressionNode?nextNode = null;
                switch (astNode)
                {
                case BindingExpressionGrammar.EmptyExpressionNode _:
                    nextNode = new EmptyExpressionNode();
                    break;

                case BindingExpressionGrammar.NotNode _:
                    nextNode = new LogicalNotNode();
                    break;

                case BindingExpressionGrammar.StreamNode _:
                    nextNode = new StreamNode();
                    break;

                case BindingExpressionGrammar.PropertyNameNode propName:
                    nextNode = new PropertyAccessorNode(propName.PropertyName, _enableValidation);
                    break;

                case BindingExpressionGrammar.IndexerNode indexer:
                    nextNode = new StringIndexerNode(indexer.Arguments);
                    break;

                case BindingExpressionGrammar.AttachedPropertyNameNode attachedProp:
                    nextNode = ParseAttachedProperty(attachedProp);
                    break;

                case BindingExpressionGrammar.SelfNode _:
                    nextNode = new SelfNode();
                    break;

                case BindingExpressionGrammar.AncestorNode ancestor:
                    nextNode = ParseFindAncestor(ancestor);
                    break;

                case BindingExpressionGrammar.NameNode elementName:
                    nextNode = new ElementNameNode(_nameScope ?? throw new NotSupportedException("Invalid element name binding with null name scope!"), elementName.Name);
                    break;

                case BindingExpressionGrammar.TypeCastNode typeCast:
                    nextNode = ParseTypeCastNode(typeCast);
                    break;
                }
                if (node is null)
                {
                    rootNode = node = nextNode;
                }
                else
                {
                    node.Next = nextNode;
                    node      = nextNode;
                }
            }

            return(rootNode, mode);
        }
Esempio n. 17
0
        // Gathers all linear expressions in to this.linearExpression and all binary expressions in to their respective candidate columns expressions
        private void AnalyzeExpression(BinaryNode expr)
        {
            Debug.Assert(_candidateColumns != null);

            if (_linearExpression == _expression)
            {
                return;
            }

            if (expr._op == Operators.Or)
            {
                _linearExpression = _expression;
                return;
            }
            else
            if (expr._op == Operators.And)
            {
                bool isLeft = false, isRight = false;
                if (expr._left is BinaryNode)
                {
                    AnalyzeExpression((BinaryNode)expr._left);
                    if (_linearExpression == _expression)
                    {
                        return;
                    }
                    isLeft = true;
                }
                else
                {
                    UnaryNode?unaryNode = expr._left as UnaryNode;
                    if (unaryNode != null)
                    {
                        while (unaryNode._op == Operators.Noop && unaryNode._right is UnaryNode && ((UnaryNode)unaryNode._right)._op == Operators.Noop)
                        {
                            unaryNode = (UnaryNode)unaryNode._right;
                        }
                        if (unaryNode._op == Operators.Noop && unaryNode._right is BinaryNode)
                        {
                            AnalyzeExpression((BinaryNode)(unaryNode._right));
                            if (_linearExpression == _expression)
                            {
                                return;
                            }
                            isLeft = true;
                        }
                    }
                }

                if (expr._right is BinaryNode)
                {
                    AnalyzeExpression((BinaryNode)expr._right);
                    if (_linearExpression == _expression)
                    {
                        return;
                    }
                    isRight = true;
                }
                else
                {
                    UnaryNode?unaryNode = expr._right as UnaryNode;
                    if (unaryNode != null)
                    {
                        while (unaryNode._op == Operators.Noop && unaryNode._right is UnaryNode && ((UnaryNode)unaryNode._right)._op == Operators.Noop)
                        {
                            unaryNode = (UnaryNode)unaryNode._right;
                        }
                        if (unaryNode._op == Operators.Noop && unaryNode._right is BinaryNode)
                        {
                            AnalyzeExpression((BinaryNode)(unaryNode._right));
                            if (_linearExpression == _expression)
                            {
                                return;
                            }

                            isRight = true;
                        }
                    }
                }

                if (isLeft && isRight)
                {
                    return;
                }

                ExpressionNode e = isLeft ? expr._right : expr._left;
                _linearExpression = (_linearExpression == null ? e : new BinaryNode(_table, Operators.And, e, _linearExpression));
                return;
            }
            else
            if (IsSupportedOperator(expr._op))
            {
                if (expr._left is NameNode && expr._right is ConstNode)
                {
                    ColumnInfo canColumn = _candidateColumns[((NameNode)(expr._left))._column !.Ordinal];
Esempio n. 18
0
 public ReturnNode(ExpressionNode inner)
 {
     Inner = inner;
 }
Esempio n. 19
0
        /// <summary>
        ///     Builds expression tree for higher-precedence operator to be used as left
        ///     operand of current operator. May cause errors - always do ErrorCheck() upin return.
        /// </summary>

        private void BuildExpression(int pri)
        {
            ExpressionNode?expr = null;

            Debug.Assert(pri > Operators.priStart && pri <= Operators.priMax, "Invalid priority value");

            /* For all operators of higher or same precedence (we are always
             * left-associative) */
            while (true)
            {
                Debug.Assert(_topOperator > 0, "Empty operator stack!!");
                OperatorInfo opInfo = _ops[_topOperator - 1];

                if (opInfo._priority < pri)
                {
                    goto end_loop;
                }

                Debug.Assert(opInfo._priority >= pri, "Invalid prioriry value");
                _topOperator--;

                ExpressionNode?nodeLeft;
                ExpressionNode nodeRight;
                switch (opInfo._type)
                {
                case Nodes.Binop:
                {
                    // get right, left operands. Bind them.

                    nodeRight = NodePop();
                    nodeLeft  = NodePop();

                    /* This is the place to do type and other checks */

                    switch (opInfo._op)
                    {
                    case Operators.Between:
                    case Operators.BetweenAnd:
                    case Operators.BitwiseAnd:
                    case Operators.BitwiseOr:
                    case Operators.BitwiseXor:
                    case Operators.BitwiseNot:
                        throw ExprException.UnsupportedOperator(opInfo._op);

                    case Operators.Is:
                    case Operators.Or:
                    case Operators.And:
                    case Operators.EqualTo:
                    case Operators.NotEqual:
                    case Operators.Like:
                    case Operators.LessThen:
                    case Operators.LessOrEqual:
                    case Operators.GreaterThen:
                    case Operators.GreaterOrEqual:
                    case Operators.In:
                        break;

                    default:
                        Debug.Assert(opInfo._op == Operators.Plus ||
                                     opInfo._op == Operators.Minus ||
                                     opInfo._op == Operators.Multiply ||
                                     opInfo._op == Operators.Divide ||
                                     opInfo._op == Operators.Modulo,
                                     "Invalud Binary operation");

                        break;
                    }
                    Debug.Assert(nodeLeft != null, "Invalid left operand");
                    Debug.Assert(nodeRight != null, "Invalid right operand");

                    if (opInfo._op == Operators.Like)
                    {
                        expr = new LikeNode(_table, opInfo._op, nodeLeft, nodeRight);
                    }
                    else
                    {
                        expr = new BinaryNode(_table, opInfo._op, nodeLeft, nodeRight);
                    }

                    break;
                }

                case Nodes.Unop:
                    /* Unary operator: Pop and bind right op. */
                    nodeLeft  = null;
                    nodeRight = NodePop();

                    /* Check for special cases */
                    switch (opInfo._op)
                    {
                    case Operators.Not:
                        break;

                    case Operators.BitwiseNot:
                        throw ExprException.UnsupportedOperator(opInfo._op);

                    case Operators.Negative:
                        break;
                    }

                    Debug.Assert(nodeLeft == null, "Invalid left operand");
                    Debug.Assert(nodeRight != null, "Invalid right operand");

                    expr = new UnaryNode(_table, opInfo._op, nodeRight);
                    break;

                case Nodes.Zop:
                    /* Intrinsic constant: just create node. */
                    expr = new ZeroOpNode(opInfo._op);
                    break;

                default:
                    Debug.Fail("Unhandled operator type");
                    goto end_loop;
                }
                Debug.Assert(expr != null, "Failed to create expression");

                NodePush(expr);
                // countinue while loop;
            }
end_loop:
            ;
        }
Esempio n. 20
0
        // CONSIDER: configure the scanner : local info

        internal ExpressionNode Parse()
        {
            // free all nodes
            _expression = null;

            StartScan();

            int          cParens = 0;
            OperatorInfo opInfo;

            while (_token != Tokens.EOS)
            {
loop:
                Scan();

                switch (_token)
                {
                case Tokens.EOS:
                    // End of string: must be operand; force out expression;
                    // check for bomb; check nothing left on stack.

                    if (_prevOperand == Empty)
                    {
                        if (_topNode == 0)
                        {
                            // we have an empty expression
                            break;
                        }
                        // set error missing operator
                        // read the last operator info
                        opInfo = _ops[_topOperator - 1];

                        throw ExprException.MissingOperand(opInfo);
                    }
                    // collect all nodes
                    BuildExpression(Operators.priLow);
                    if (_topOperator != 1)
                    {
                        throw ExprException.MissingRightParen();
                    }
                    break;

                case Tokens.Name:
                case Tokens.Parent:
                case Tokens.Numeric:
                case Tokens.Decimal:
                case Tokens.Float:
                case Tokens.StringConst:
                case Tokens.Date:
                    ExpressionNode?node = null;
                    string?        str  = null;

                    /* Constants and identifiers: create leaf node */

                    if (_prevOperand != Empty)
                    {
                        // set error missing operator
                        throw ExprException.MissingOperator(new string(_text, _start, _pos - _start));
                    }

                    if (_topOperator > 0)
                    {
                        // special check for IN without parentheses

                        opInfo = _ops[_topOperator - 1];

                        if (opInfo._type == Nodes.Binop && opInfo._op == Operators.In && _token != Tokens.Parent)
                        {
                            throw ExprException.InWithoutParentheses();
                        }
                    }

                    _prevOperand = Scalar;

                    switch (_token)
                    {
                    case Tokens.Parent:
                        string?relname;
                        string colname;

                        // parsing Parent[(relation_name)].column_name)
                        try
                        {
                            // expecting an '(' or '.'
                            Scan();
                            if (_token == Tokens.LeftParen)
                            {
                                //read the relation name
                                ScanToken(Tokens.Name);
                                relname = NameNode.ParseName(_text, _start, _pos);
                                ScanToken(Tokens.RightParen);
                                ScanToken(Tokens.Dot);
                            }
                            else
                            {
                                relname = null;
                                CheckToken(Tokens.Dot);
                            }
                        }
                        catch (Exception e) when(Common.ADP.IsCatchableExceptionType(e))
                        {
                            throw ExprException.LookupArgument();
                        }

                        ScanToken(Tokens.Name);
                        colname = NameNode.ParseName(_text, _start, _pos);

                        opInfo = _ops[_topOperator - 1];
                        node   = new LookupNode(_table, colname, relname);

                        break;

                    case Tokens.Name:
                        /* Qualify name now for nice error checking */

                        opInfo = _ops[_topOperator - 1];

                        /* Create tree element -                */
                        // CONSIDER: Check for reserved proc names here
                        node = new NameNode(_table, _text, _start, _pos);

                        break;

                    case Tokens.Numeric:
                        str  = new string(_text, _start, _pos - _start);
                        node = new ConstNode(_table, ValueType.Numeric, str);
                        break;

                    case Tokens.Decimal:
                        str  = new string(_text, _start, _pos - _start);
                        node = new ConstNode(_table, ValueType.Decimal, str);
                        break;

                    case Tokens.Float:
                        str  = new string(_text, _start, _pos - _start);
                        node = new ConstNode(_table, ValueType.Float, str);
                        break;

                    case Tokens.StringConst:
                        Debug.Assert(_text[_start] == '\'' && _text[_pos - 1] == '\'', "The expression contains an invalid string constant");
                        Debug.Assert(_pos - _start > 1, "The expression contains an invalid string constant");
                        // Store string without quotes..
                        str  = new string(_text, _start + 1, _pos - _start - 2);
                        node = new ConstNode(_table, ValueType.Str, str);
                        break;

                    case Tokens.Date:
                        Debug.Assert(_text[_start] == '#' && _text[_pos - 1] == '#', "The expression contains invalid date constant.");
                        Debug.Assert(_pos - _start > 2, "The expression contains invalid date constant '{0}'.");
                        // Store date without delimiters(#s)..
                        str  = new string(_text, _start + 1, _pos - _start - 2);
                        node = new ConstNode(_table, ValueType.Date, str);
                        break;

                    default:
                        Debug.Fail("unhandled token");
                        break;
                    }

                    NodePush(node);
                    goto loop;

                case Tokens.LeftParen:
                    cParens++;
                    if (_prevOperand == Empty)
                    {
                        // Check for ( following IN/IFF. if not, we have a normal (.
                        // Peek: take a look at the operators stack

                        Debug.Assert(_topOperator > 0, "Empty operator stack!!");
                        opInfo = _ops[_topOperator - 1];

                        if (opInfo._type == Nodes.Binop && opInfo._op == Operators.In)
                        {
                            /* IN - handle as procedure call */

                            node = new FunctionNode(_table, "In");
                            NodePush(node);
                            /* Push operator decriptor */
                            _ops[_topOperator++] = new OperatorInfo(Nodes.Call, Operators.Noop, Operators.priParen);
                        }
                        else
                        {      /* Normal ( */
                            /* Push operator decriptor */
                            _ops[_topOperator++] = new OperatorInfo(Nodes.Paren, Operators.Noop, Operators.priParen);
                        }
                    }
                    else
                    {
                        // This is a procedure call or () qualification
                        // Force out any dot qualifiers; check for bomb

                        BuildExpression(Operators.priProc);
                        _prevOperand = Empty;
                        ExpressionNode?nodebefore = NodePeek();

                        if (nodebefore == null || nodebefore.GetType() != typeof(NameNode))
                        {
                            // this is more like an assert, so we not care about "nice" exception text..
                            throw ExprException.SyntaxError();
                        }

                        /* Get the proc name */
                        NameNode name = (NameNode)NodePop();

                        // Make sure that we can bind the name as a Function
                        // then get the argument count and types, and parse arguments..

                        node = new FunctionNode(_table, name._name);

                        // check to see if this is an aggregate function
                        Aggregate agg = (Aggregate)(int)((FunctionNode)node).Aggregate;
                        if (agg != Aggregate.None)
                        {
                            node = ParseAggregateArgument((FunctionId)(int)agg);
                            NodePush(node);
                            _prevOperand = Expr;
                            goto loop;
                        }

                        NodePush(node);
                        _ops[_topOperator++] = new OperatorInfo(Nodes.Call, Operators.Noop, Operators.priParen);
                    }
                    goto loop;

                case Tokens.RightParen:
                {
                    /* Right parentheses: Build expression if we have an operand. */
                    if (_prevOperand != Empty)
                    {
                        BuildExpression(Operators.priLow);
                    }

                    /* We must have Tokens.LeftParen on stack. If no operand, must be procedure call. */
                    if (_topOperator <= 1)
                    {
                        // set error, syntax: too many right parens..
                        throw ExprException.TooManyRightParentheses();
                    }

                    Debug.Assert(_topOperator > 1, "melformed operator stack.");
                    _topOperator--;
                    opInfo = _ops[_topOperator];

                    if (_prevOperand == Empty && opInfo._type != Nodes.Call)
                    {
                        // set error, syntax: missing operand.
                        throw ExprException.MissingOperand(opInfo);
                    }

                    Debug.Assert(opInfo._priority == Operators.priParen, "melformed operator stack.");

                    if (opInfo._type == Nodes.Call)
                    {
                        /* add argument to the function call. */

                        if (_prevOperand != Empty)
                        {
                            // read last function argument
                            ExpressionNode argument = NodePop();

                            /* Get the procedure name and append argument */
                            Debug.Assert(_topNode > 0 && NodePeek() !.GetType() == typeof(FunctionNode), "The function node should be created on '('");

                            FunctionNode func = (FunctionNode)NodePop();
                            func.AddArgument(argument);
                            func.Check();
                            NodePush(func);
                        }
                    }
                    else
                    {
                        /* Normal parentheses: create tree node */
                        // Construct & Put the Nodes.Paren node on node stack
                        node = NodePop();
                        node = new UnaryNode(_table, Operators.Noop, node);
                        NodePush(node);
                    }

                    _prevOperand = Expr;
                    cParens--;
                    goto loop;
                }

                case Tokens.ListSeparator:
                {
                    /* Comma encountered: Must be operand; force out subexpression */

                    if (_prevOperand == Empty)
                    {
                        throw ExprException.MissingOperandBefore(",");
                    }

                    /* We are be in a procedure call */

                    /* build next argument */
                    BuildExpression(Operators.priLow);

                    opInfo = _ops[_topOperator - 1];

                    if (opInfo._type != Nodes.Call)
                    {
                        throw ExprException.SyntaxError();
                    }

                    ExpressionNode argument2 = NodePop();

                    /* Get the procedure name */

                    FunctionNode func = (FunctionNode)NodePop();

                    func.AddArgument(argument2);

                    NodePush(func);

                    _prevOperand = Empty;

                    goto loop;
                }

                case Tokens.BinaryOp:
                    if (_prevOperand == Empty)
                    {
                        /* Check for unary plus/minus */
                        if (_op == Operators.Plus)
                        {
                            _op = Operators.UnaryPlus;
                            // fall through to UnaryOperator;
                        }
                        else if (_op == Operators.Minus)
                        {
                            /* Unary minus */
                            _op = Operators.Negative;
                            // fall through to UnaryOperator;
                        }
                        else
                        {
                            // Error missing operand:
                            throw ExprException.MissingOperandBefore(Operators.ToString(_op));
                        }
                    }
                    else
                    {
                        _prevOperand = Empty;

                        /* CNSIDER: If we are going to support BETWEEN Translate AND to special BetweenAnd if it is. */

                        /* Force out to appropriate precedence; push operator. */

                        BuildExpression(Operators.Priority(_op));

                        // PushOperator descriptor
                        _ops[_topOperator++] = new OperatorInfo(Nodes.Binop, _op, Operators.Priority(_op));
                        goto loop;
                    }

                    goto
                case Tokens.UnaryOp;     // fall through to UnaryOperator;

                case Tokens.UnaryOp:
                    /* Must be no operand. Push it. */
                    _ops[_topOperator++] = new OperatorInfo(Nodes.Unop, _op, Operators.Priority(_op));
                    goto loop;

                case Tokens.ZeroOp:
                    // check the we have operator on the stack
                    if (_prevOperand != Empty)
                    {
                        // set error missing operator
                        throw ExprException.MissingOperator(new string(_text, _start, _pos - _start));
                    }

                    // PushOperator descriptor
                    _ops[_topOperator++] = new OperatorInfo(Nodes.Zop, _op, Operators.priMax);
                    _prevOperand         = Expr;
                    goto loop;

                case Tokens.Dot:
                    //if there is a name on the stack append it.
                    ExpressionNode?before = NodePeek();

                    if (before != null && before.GetType() == typeof(NameNode))
                    {
                        Scan();

                        if (_token == Tokens.Name)
                        {
                            NameNode nameBefore = (NameNode)NodePop();
                            string   newName    = nameBefore._name + "." + NameNode.ParseName(_text, _start, _pos);
                            NodePush(new NameNode(_table, newName));
                            goto loop;
                        }
                    }
                    // fall through to default
                    goto default;

                default:
                    throw ExprException.UnknownToken(new string(_text, _start, _pos - _start), _start + 1);
                }
            }
            goto end_loop;
end_loop:
            Debug.Assert(_topNode == 1 || _topNode == 0, "Invalid Node Stack");
            _expression = _nodeStack[0];

            return(_expression);
        }