System.Data.ExpressionParser.Parse C# (CSharp) Метод

Parse() приватный Метод

private Parse ( ) : ExpressionNode
Результат ExpressionNode
        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;
        }

Usage Example

Пример #1
0
        internal DataExpression(DataTable table, string expression, Type type)
        {
            ExpressionParser parser = new ExpressionParser(table);
            parser.LoadExpression(expression);

            _originalExpression = expression;
            _expr = null;

            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;
                }
            }
        }
All Usage Examples Of System.Data.ExpressionParser::Parse