Inheritance: ExpressionNode
        /// <devdoc>
        ///     Builds expression tree for higher-precedence operator to be used as left
        ///     operand of current operator. May cause errors - always do ErrorCheck() upin return.
        /// </devdoc>

        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.Assert(false, "Unhandled operator type");
                        goto end_loop;
                }
                Debug.Assert(expr != null, "Failed to create expression");

                NodePush(expr);
                // countinue while loop;
            }
            end_loop:
            ;
        }
示例#2
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)
        {
            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];
                    canColumn.expr = (canColumn.expr == null ? expr : new BinaryNode(_table, Operators.And, expr, canColumn.expr));
                    if (expr._op == Operators.EqualTo)
                    {
                        canColumn.equalsOperator = true;
                    }
                    _candidatesForBinarySearch = true;
                    return;
                }
                else
                if (expr._right is NameNode && expr._left is ConstNode)
                {
                    ExpressionNode temp = expr._left;
                    expr._left  = expr._right;
                    expr._right = temp;
                    switch (expr._op)
                    {
                    case Operators.GreaterThen: expr._op = Operators.LessThen; break;

                    case Operators.LessThen: expr._op = Operators.GreaterThen; break;

                    case Operators.GreaterOrEqual: expr._op = Operators.LessOrEqual; break;

                    case Operators.LessOrEqual: expr._op = Operators.GreaterOrEqual; break;

                    default: break;
                    }
                    ColumnInfo canColumn = _candidateColumns[((NameNode)(expr._left))._column.Ordinal];
                    canColumn.expr = (canColumn.expr == null ? expr : new BinaryNode(_table, Operators.And, expr, canColumn.expr));
                    if (expr._op == Operators.EqualTo)
                    {
                        canColumn.equalsOperator = true;
                    }
                    _candidatesForBinarySearch = true;
                    return;
                }
            }

            _linearExpression = (_linearExpression == null ? expr : new BinaryNode(_table, Operators.And, expr, _linearExpression));
            return;
        }
        // 

        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){
                                    // 
                                    if (!Common.ADP.IsCatchableExceptionType(e)) {
                                        throw;
                                    }
                                    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 -                */
                                // 
                                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.Assert(false, "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();
                                //Debug.WriteLine("Before name '" + nameBefore.name + "'");
                                string newName = nameBefore.name + "." + NameNode.ParseName(text, start, pos);
                                //Debug.WriteLine("Create new NameNode " + newName);
                                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;
        }
示例#4
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.Assert(false, "Unhandled operator type");
                    goto end_loop;
                }
                Debug.Assert(expr != null, "Failed to create expression");

                NodePush(expr);
                // countinue while loop;
            }
end_loop:
            ;
        }
示例#5
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.Assert(false, "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);
        }
示例#6
0
        internal override ExpressionNode Optimize()
        {
            left = left.Optimize();

            if (op == Operators.Is)
            {
                // only 'Is Null' or 'Is Not Null' are valid
                if (right is UnaryNode)
                {
                    UnaryNode un = (UnaryNode)right;
                    if (un.op != Operators.Not)
                    {
                        throw ExprException.InvalidIsSyntax();
                    }
                    op    = Operators.IsNot;
                    right = un.right;
                }
                if (right is ZeroOpNode)
                {
                    if (((ZeroOpNode)right).op != Operators.Null)
                    {
                        throw ExprException.InvalidIsSyntax();
                    }
                }
                else
                {
                    throw ExprException.InvalidIsSyntax();
                }
            }
            else
            {
                right = right.Optimize();
            }

#if DEBUG
            if (CompModSwitches.BinaryNode.TraceVerbose)
            {
                Debug.WriteLine("Optimizing " + this.ToString());
            }
#endif

            if (this.IsConstant())
            {
                object val = this.Eval();
#if DEBUG
                if (CompModSwitches.BinaryNode.TraceVerbose)
                {
                    Debug.WriteLine("the node value is " + val.ToString());
                }
#endif

                if (val == DBNull.Value)
                {
                    return(new ZeroOpNode(Operators.Null));
                }

                if (val is bool)
                {
                    if ((bool)val)
                    {
                        return(new ZeroOpNode(Operators.True));
                    }
                    else
                    {
                        return(new ZeroOpNode(Operators.False));
                    }
                }
#if DEBUG
                if (CompModSwitches.BinaryNode.TraceVerbose)
                {
                    Debug.WriteLine(val.GetType().ToString());
                }
#endif
                return(new ConstNode(ValueType.Object, val, false));
            }
            else
            {
                return(this);
            }
        }
        private void BuildExpression(int pri)
        {
            OperatorInfo info;
            ExpressionNode node = null;
        Label_0002:
            info = this.ops[this.topOperator - 1];
            if (info.priority >= pri)
            {
                ExpressionNode node2;
                ExpressionNode node3;
                this.topOperator--;
                switch (info.type)
                {
                    case Nodes.Unop:
                        node3 = null;
                        node2 = this.NodePop();
                        switch (info.op)
                        {
                            case 0x19:
                                throw ExprException.UnsupportedOperator(info.op);
                        }
                        node = new UnaryNode(this._table, info.op, node2);
                        goto Label_016C;

                    case Nodes.UnopSpec:
                    case Nodes.BinopSpec:
                        return;

                    case Nodes.Binop:
                        node2 = this.NodePop();
                        node3 = this.NodePop();
                        switch (info.op)
                        {
                            case 4:
                            case 6:
                            case 0x16:
                            case 0x17:
                            case 0x18:
                            case 0x19:
                                throw ExprException.UnsupportedOperator(info.op);
                        }
                        if (info.op == 14)
                        {
                            node = new LikeNode(this._table, info.op, node3, node2);
                        }
                        else
                        {
                            node = new BinaryNode(this._table, info.op, node3, node2);
                        }
                        goto Label_016C;

                    case Nodes.Zop:
                        node = new ZeroOpNode(info.op);
                        goto Label_016C;
                }
            }
            return;
        Label_016C:
            this.NodePush(node);
            goto Label_0002;
        }
        internal ExpressionNode Parse()
        {
            ExpressionNode node;
            OperatorInfo info;
            this.expression = null;
            this.StartScan();
            int num = 0;
            goto Label_078F;
        Label_0014:
            this.Scan();
            switch (this.token)
            {
                case Tokens.Name:
                case Tokens.Numeric:
                case Tokens.Decimal:
                case Tokens.Float:
                case Tokens.StringConst:
                case Tokens.Date:
                case Tokens.Parent:
                {
                    node = null;
                    string constant = null;
                    if (this.prevOperand != 0)
                    {
                        throw ExprException.MissingOperator(new string(this.text, this.start, this.pos - this.start));
                    }
                    if (this.topOperator > 0)
                    {
                        info = this.ops[this.topOperator - 1];
                        if (((info.type == Nodes.Binop) && (info.op == 5)) && (this.token != Tokens.Parent))
                        {
                            throw ExprException.InWithoutParentheses();
                        }
                    }
                    this.prevOperand = 1;
                    switch (this.token)
                    {
                        case Tokens.Name:
                            info = this.ops[this.topOperator - 1];
                            node = new NameNode(this._table, this.text, this.start, this.pos);
                            goto Label_0338;

                        case Tokens.Numeric:
                            constant = new string(this.text, this.start, this.pos - this.start);
                            node = new ConstNode(this._table, System.Data.ValueType.Numeric, constant);
                            goto Label_0338;

                        case Tokens.Decimal:
                            constant = new string(this.text, this.start, this.pos - this.start);
                            node = new ConstNode(this._table, System.Data.ValueType.Decimal, constant);
                            goto Label_0338;

                        case Tokens.Float:
                            constant = new string(this.text, this.start, this.pos - this.start);
                            node = new ConstNode(this._table, System.Data.ValueType.Float, constant);
                            goto Label_0338;

                        case Tokens.StringConst:
                            constant = new string(this.text, this.start + 1, (this.pos - this.start) - 2);
                            node = new ConstNode(this._table, System.Data.ValueType.Str, constant);
                            goto Label_0338;

                        case Tokens.Date:
                            constant = new string(this.text, this.start + 1, (this.pos - this.start) - 2);
                            node = new ConstNode(this._table, System.Data.ValueType.Date, constant);
                            goto Label_0338;

                        case Tokens.Parent:
                        {
                            string str2;
                            try
                            {
                                this.Scan();
                                if (this.token == Tokens.LeftParen)
                                {
                                    this.ScanToken(Tokens.Name);
                                    str2 = NameNode.ParseName(this.text, this.start, this.pos);
                                    this.ScanToken(Tokens.RightParen);
                                    this.ScanToken(Tokens.Dot);
                                }
                                else
                                {
                                    str2 = null;
                                    this.CheckToken(Tokens.Dot);
                                }
                            }
                            catch (Exception exception)
                            {
                                if (!ADP.IsCatchableExceptionType(exception))
                                {
                                    throw;
                                }
                                throw ExprException.LookupArgument();
                            }
                            this.ScanToken(Tokens.Name);
                            string columnName = NameNode.ParseName(this.text, this.start, this.pos);
                            info = this.ops[this.topOperator - 1];
                            node = new LookupNode(this._table, columnName, str2);
                            goto Label_0338;
                        }
                    }
                    break;
                }
                case Tokens.ListSeparator:
                {
                    if (this.prevOperand == 0)
                    {
                        throw ExprException.MissingOperandBefore(",");
                    }
                    this.BuildExpression(3);
                    info = this.ops[this.topOperator - 1];
                    if (info.type != Nodes.Call)
                    {
                        throw ExprException.SyntaxError();
                    }
                    ExpressionNode argument = this.NodePop();
                    FunctionNode node4 = (FunctionNode) this.NodePop();
                    node4.AddArgument(argument);
                    this.NodePush(node4);
                    this.prevOperand = 0;
                    goto Label_0014;
                }
                case Tokens.LeftParen:
                    num++;
                    if (this.prevOperand != 0)
                    {
                        this.BuildExpression(0x16);
                        this.prevOperand = 0;
                        ExpressionNode node5 = this.NodePeek();
                        if ((node5 == null) || (node5.GetType() != typeof(NameNode)))
                        {
                            throw ExprException.SyntaxError();
                        }
                        NameNode node9 = (NameNode) this.NodePop();
                        node = new FunctionNode(this._table, node9.name);
                        Aggregate aggregate = (Aggregate) ((FunctionNode) node).Aggregate;
                        if (aggregate != Aggregate.None)
                        {
                            node = this.ParseAggregateArgument((FunctionId) aggregate);
                            this.NodePush(node);
                            this.prevOperand = 2;
                        }
                        else
                        {
                            this.NodePush(node);
                            this.ops[this.topOperator++] = new OperatorInfo(Nodes.Call, 0, 2);
                        }
                    }
                    else
                    {
                        info = this.ops[this.topOperator - 1];
                        if ((info.type != Nodes.Binop) || (info.op != 5))
                        {
                            this.ops[this.topOperator++] = new OperatorInfo(Nodes.Paren, 0, 2);
                        }
                        else
                        {
                            node = new FunctionNode(this._table, "In");
                            this.NodePush(node);
                            this.ops[this.topOperator++] = new OperatorInfo(Nodes.Call, 0, 2);
                        }
                    }
                    goto Label_0014;

                case Tokens.RightParen:
                    if (this.prevOperand != 0)
                    {
                        this.BuildExpression(3);
                    }
                    if (this.topOperator <= 1)
                    {
                        throw ExprException.TooManyRightParentheses();
                    }
                    this.topOperator--;
                    info = this.ops[this.topOperator];
                    if ((this.prevOperand == 0) && (info.type != Nodes.Call))
                    {
                        throw ExprException.MissingOperand(info);
                    }
                    if (info.type == Nodes.Call)
                    {
                        if (this.prevOperand != 0)
                        {
                            ExpressionNode node8 = this.NodePop();
                            FunctionNode node2 = (FunctionNode) this.NodePop();
                            node2.AddArgument(node8);
                            node2.Check();
                            this.NodePush(node2);
                        }
                    }
                    else
                    {
                        node = this.NodePop();
                        node = new UnaryNode(this._table, 0, node);
                        this.NodePush(node);
                    }
                    this.prevOperand = 2;
                    num--;
                    goto Label_0014;

                case Tokens.ZeroOp:
                    if (this.prevOperand != 0)
                    {
                        throw ExprException.MissingOperator(new string(this.text, this.start, this.pos - this.start));
                    }
                    this.ops[this.topOperator++] = new OperatorInfo(Nodes.Zop, this.op, 0x18);
                    this.prevOperand = 2;
                    goto Label_0014;

                case Tokens.UnaryOp:
                    goto Label_0647;

                case Tokens.BinaryOp:
                    if (this.prevOperand != 0)
                    {
                        this.prevOperand = 0;
                        this.BuildExpression(Operators.Priority(this.op));
                        this.ops[this.topOperator++] = new OperatorInfo(Nodes.Binop, this.op, Operators.Priority(this.op));
                        goto Label_0014;
                    }
                    if (this.op != 15)
                    {
                        if (this.op != 0x10)
                        {
                            throw ExprException.MissingOperandBefore(Operators.ToString(this.op));
                        }
                        this.op = 1;
                    }
                    else
                    {
                        this.op = 2;
                    }
                    goto Label_0647;

                case Tokens.Dot:
                {
                    ExpressionNode node3 = this.NodePeek();
                    if ((node3 == null) || !(node3.GetType() == typeof(NameNode)))
                    {
                        goto Label_0763;
                    }
                    this.Scan();
                    if (this.token != Tokens.Name)
                    {
                        goto Label_0763;
                    }
                    NameNode node6 = (NameNode) this.NodePop();
                    string name = node6.name + "." + NameNode.ParseName(this.text, this.start, this.pos);
                    this.NodePush(new NameNode(this._table, name));
                    goto Label_0014;
                }
                case Tokens.EOS:
                    if (this.prevOperand != 0)
                    {
                        this.BuildExpression(3);
                        if (this.topOperator != 1)
                        {
                            throw ExprException.MissingRightParen();
                        }
                    }
                    else if (this.topNode != 0)
                    {
                        info = this.ops[this.topOperator - 1];
                        throw ExprException.MissingOperand(info);
                    }
                    goto Label_078F;

                default:
                    goto Label_0763;
            }
        Label_0338:
            this.NodePush(node);
            goto Label_0014;
        Label_0647:
            this.ops[this.topOperator++] = new OperatorInfo(Nodes.Unop, this.op, Operators.Priority(this.op));
            goto Label_0014;
        Label_0763:
            throw ExprException.UnknownToken(new string(this.text, this.start, this.pos - this.start), this.start + 1);
        Label_078F:
            if (this.token != Tokens.EOS)
            {
                goto Label_0014;
            }
            this.expression = this.NodeStack[0];
            return this.expression;
        }