private XPathExpr ParsePrimaryExpression()
        {
            XPathExpr expr = this.ParseVariableExpression();

            if ((expr == null) && (this.NextToken(XPathTokenID.LParen) != null))
            {
                expr = this.ParseExpression();
                if ((expr == null) || (this.NextToken(XPathTokenID.RParen) == null))
                {
                    this.ThrowError(QueryCompileError.InvalidExpression);
                }
            }
            if (expr == null)
            {
                expr = this.ParseLiteralExpression();
            }
            if (expr == null)
            {
                expr = this.ParseNumberExpression();
            }
            if (expr == null)
            {
                expr = this.ParseFunctionExpression();
            }
            return(expr);
        }
예제 #2
0
        XPathExpr ParseFilterExpression()
        {
            XPathExpr primaryExpr = this.ParsePrimaryExpression();

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

            XPathExpr filterExpr = new XPathExpr(XPathExprType.Filter, primaryExpr.ReturnType);

            filterExpr.Add(primaryExpr);

            XPathExpr predicate = this.ParsePredicateExpression();

            if (null != predicate)
            {
                EnsureReturnsNodeSet(primaryExpr);

                //XPathExpr filterExpr = new XPathExpr(XPathExprType.Filter, ValueDataType.Sequence);

                //filterExpr.Add(primaryExpr);
                filterExpr.Add(predicate);

                // Read in any additional predicates
                while (null != (predicate = this.ParsePredicateExpression()))
                {
                    filterExpr.Add(predicate);
                }

                return(filterExpr);
            }

            return(primaryExpr);
        }
예제 #3
0
        XPathExpr ParsePrimaryExpression()
        {
            XPathExpr expr = this.ParseVariableExpression();

            if (null == expr)
            {
                if (null != this.NextToken(XPathTokenID.LParen))
                {
                    expr = this.ParseExpression();
                    if (null == expr || null == this.NextToken(XPathTokenID.RParen))
                    {
                        this.ThrowError(QueryCompileError.InvalidExpression);
                    }
                }
            }

            if (null == expr)
            {
                expr = this.ParseLiteralExpression();
            }

            if (null == expr)
            {
                expr = this.ParseNumberExpression();
            }

            if (null == expr)
            {
                expr = this.ParseFunctionExpression();
            }

            return(expr);
        }
예제 #4
0
            private void CompileFilter(XPathExpr expr)
            {
                XPathExprList subExpr = expr.SubExpr;
                XPathExpr     expr2   = subExpr[0];

                if ((subExpr.Count > 1) && (ValueDataType.Sequence != expr2.ReturnType))
                {
                    this.ThrowError(QueryCompileError.InvalidExpression);
                }
                this.CompileExpression(expr2);
                if (expr2.ReturnType == ValueDataType.Sequence)
                {
                    if (!this.IsSpecialInternalFunction(expr2) && (expr.SubExprCount > 1))
                    {
                        this.codeBlock.Append(new MergeOpcode());
                        this.codeBlock.Append(new PopSequenceToSequenceStackOpcode());
                    }
                    else if (this.IsSpecialInternalFunction(expr2) && (expr.SubExprCount > 1))
                    {
                        this.codeBlock.DetachLast();
                    }
                    this.compiler.nestingLevel++;
                    if (this.compiler.nestingLevel > 3)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.PredicateNestingTooDeep));
                    }
                    for (int i = 1; i < expr.SubExprCount; i++)
                    {
                        this.CompilePredicate(subExpr[i]);
                    }
                    this.compiler.nestingLevel--;
                }
            }
        private XPathExpr ParseFilterExpression()
        {
            XPathExpr expr = this.ParsePrimaryExpression();

            if (expr == null)
            {
                return(null);
            }
            XPathExpr expr2 = new XPathExpr(XPathExprType.Filter, expr.ReturnType);

            expr2.Add(expr);
            XPathExpr expr3 = this.ParsePredicateExpression();

            if (expr3 == null)
            {
                return(expr);
            }
            this.EnsureReturnsNodeSet(expr);
            expr2.Add(expr3);
            while ((expr3 = this.ParsePredicateExpression()) != null)
            {
                expr2.Add(expr3);
            }
            return(expr2);
        }
예제 #6
0
 private void CompileXsltFunction(XPathXsltFunctionExpr expr)
 {
     if (expr.SubExprCount > 0)
     {
         XPathExprList subExpr = expr.SubExpr;
         for (int i = subExpr.Count - 1; i >= 0; i--)
         {
             XPathExpr expr2 = subExpr[i];
             this.CompileExpression(expr2);
             ValueDataType destType = XPathXsltFunctionExpr.ConvertTypeFromXslt(expr.Function.ArgTypes[i]);
             if ((destType != ValueDataType.None) && (expr2.ReturnType != destType))
             {
                 this.CompileTypecast(destType);
             }
         }
     }
     if (expr.Function is XPathMessageFunction)
     {
         this.codeBlock.Append(new XPathMessageFunctionCallOpcode((XPathMessageFunction)expr.Function, expr.SubExprCount));
         if (this.IsSpecialInternalFunction(expr))
         {
             this.codeBlock.Append(new PopSequenceToValueStackOpcode());
         }
     }
     else
     {
         this.codeBlock.Append(new XsltFunctionCallOpcode(expr.Context, expr.Function, expr.SubExprCount));
     }
 }
예제 #7
0
            // Compiles expressions at nesting level == 1 -> boolean expressions that can be processed
            // with less complex opcodes because they will never track multiple sequences simultaneously
            void CompileBasicBoolean(XPathExpr expr, bool testValue)
            {
                // Boolean expressions must always have at least 2 sub expressions
                Fx.Assert(expr.SubExprCount > 1, "");
                Fx.Assert(this.compiler.nestingLevel == 1, "");

                OpcodeBlock   boolBlock   = new OpcodeBlock(); // struct
                Opcode        blockEnd    = new BlockEndOpcode();
                XPathExprList subExprList = expr.SubExpr;

                // Compile sub-expressions
                for (int i = 0; i < subExprList.Count; ++i)
                {
                    XPathExpr subExpr = subExprList[i];
                    boolBlock.Append(this.CompileBlock(subExpr));
                    // Make sure each sub-expression can produce a boolean result
                    if (subExpr.ReturnType != ValueDataType.Boolean)
                    {
                        boolBlock.Append(new TypecastOpcode(ValueDataType.Boolean));
                    }
                    if (i < (subExprList.Count - 1))
                    {
                        // No point jumping if this is the last expression
                        boolBlock.Append(new JumpIfOpcode(blockEnd, testValue));
                    }
                }
                boolBlock.Append(blockEnd);
                this.codeBlock.Append(boolBlock);
            }
예제 #8
0
            private void CompileLiteralOrdinal(XPathExpr expr)
            {
                int ordinal = 0;

                try
                {
                    XPathNumberExpr expr2 = (XPathNumberExpr)expr;
                    ordinal = Convert.ToInt32(expr2.Number);
                    if (expr2.Negate)
                    {
                        ordinal      = -ordinal;
                        expr2.Negate = false;
                    }
                    if (ordinal < 1)
                    {
                        this.ThrowError(QueryCompileError.InvalidOrdinal);
                    }
                }
                catch (OverflowException)
                {
                    this.ThrowError(QueryCompileError.InvalidOrdinal);
                }
                if ((this.compiler.flags & QueryCompilerFlags.InverseQuery) != QueryCompilerFlags.None)
                {
                    this.codeBlock.Append(new PushContextPositionOpcode());
                    this.codeBlock.Append(new NumberEqualsOpcode((double)ordinal));
                }
                else
                {
                    this.codeBlock.Append(new LiteralOrdinalOpcode(ordinal));
                }
            }
예제 #9
0
        internal static OpcodeBlock CompileForInternalEngine(string xpath, XmlNamespaceManager nsManager, QueryCompilerFlags flags, IFunctionLibrary[] functionLibs, out ValueDataType returnType)
        {
            OpcodeBlock codeBlock;

            returnType = ValueDataType.None;
            if (0 == xpath.Length)
            {
                // 0 length XPaths always match
                codeBlock = new OpcodeBlock();
                codeBlock.Append(new PushBooleanOpcode(true)); // Always match by pushing true on the eval stack
            }
            else
            {
                // Try to parse the xpath. Bind to default function libraries
                // The parser returns an expression tree
                XPathParser parser    = new XPathParser(xpath, nsManager, functionLibs);
                XPathExpr   parseTree = parser.Parse();

                if (null == parseTree)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.CouldNotParseExpression));
                }

                returnType = parseTree.ReturnType;

                // Compile the expression tree
                XPathCompiler compiler = new XPathCompiler(flags);

                codeBlock = compiler.Compile(parseTree);
            }

            return(codeBlock);
        }
예제 #10
0
            void CompileXsltFunction(XPathXsltFunctionExpr expr)
            {
                // Compile each argument expression first, introducing a typecast where appropriate
                // Arguments are pushed C style - right to left
                if (expr.SubExprCount > 0)
                {
                    XPathExprList paramList = expr.SubExpr;
                    for (int i = paramList.Count - 1; i >= 0; --i)
                    {
                        XPathExpr param = paramList[i];
                        this.CompileExpression(param);
                        ValueDataType paramType = XPathXsltFunctionExpr.ConvertTypeFromXslt(expr.Function.ArgTypes[i]);
                        if (ValueDataType.None != paramType)
                        {
                            if (param.ReturnType != paramType)
                            {
                                this.CompileTypecast(paramType);
                            }
                        }
                    }
                }

                if (expr.Function is XPathMessageFunction)
                {
                    this.codeBlock.Append(new XPathMessageFunctionCallOpcode((XPathMessageFunction)expr.Function, expr.SubExprCount));
                    if (IsSpecialInternalFunction(expr))
                    {
                        this.codeBlock.Append(new PopSequenceToValueStackOpcode());
                    }
                }
                else
                {
                    this.codeBlock.Append(new XsltFunctionCallOpcode(expr.Context, expr.Function, expr.SubExprCount));
                }
            }
예제 #11
0
 void CompileRelativePath(XPathExpr expr, bool start)
 {
     Fx.Assert(XPathExprType.RelativePath == expr.Type, "");
     this.CompileSteps(expr.SubExpr, start);
     // Step complete. Transfer results onto the value stack
     this.codeBlock.Append(new PopSequenceToValueStackOpcode());
 }
 private void CompileBoolean(XPathExpr expr, bool testValue)
 {
     if (this.compiler.nestingLevel == 1)
     {
         this.CompileBasicBoolean(expr, testValue);
     }
     else
     {
         OpcodeBlock block = new OpcodeBlock();
         Opcode jump = new BlockEndOpcode();
         block.Append(new PushBooleanOpcode(testValue));
         XPathExprList subExpr = expr.SubExpr;
         XPathExpr expr2 = subExpr[0];
         block.Append(this.CompileBlock(expr2));
         if (expr2.ReturnType != ValueDataType.Boolean)
         {
             block.Append(new TypecastOpcode(ValueDataType.Boolean));
         }
         block.Append(new ApplyBooleanOpcode(jump, testValue));
         for (int i = 1; i < subExpr.Count; i++)
         {
             expr2 = subExpr[i];
             block.Append(new StartBooleanOpcode(testValue));
             block.Append(this.CompileBlock(expr2));
             if (expr2.ReturnType != ValueDataType.Boolean)
             {
                 block.Append(new TypecastOpcode(ValueDataType.Boolean));
             }
             block.Append(new EndBooleanOpcode(jump, testValue));
         }
         block.Append(jump);
         this.codeBlock.Append(block);
     }
 }
예제 #13
0
 private void CompileBoolean(XPathExpr expr, bool testValue)
 {
     if (this.compiler.nestingLevel == 1)
     {
         this.CompileBasicBoolean(expr, testValue);
     }
     else
     {
         OpcodeBlock block = new OpcodeBlock();
         Opcode      jump  = new BlockEndOpcode();
         block.Append(new PushBooleanOpcode(testValue));
         XPathExprList subExpr = expr.SubExpr;
         XPathExpr     expr2   = subExpr[0];
         block.Append(this.CompileBlock(expr2));
         if (expr2.ReturnType != ValueDataType.Boolean)
         {
             block.Append(new TypecastOpcode(ValueDataType.Boolean));
         }
         block.Append(new ApplyBooleanOpcode(jump, testValue));
         for (int i = 1; i < subExpr.Count; i++)
         {
             expr2 = subExpr[i];
             block.Append(new StartBooleanOpcode(testValue));
             block.Append(this.CompileBlock(expr2));
             if (expr2.ReturnType != ValueDataType.Boolean)
             {
                 block.Append(new TypecastOpcode(ValueDataType.Boolean));
             }
             block.Append(new EndBooleanOpcode(jump, testValue));
         }
         block.Append(jump);
         this.codeBlock.Append(block);
     }
 }
예제 #14
0
 private void TypecastIfRequired(XPathExpr expr)
 {
     if (expr.TypecastRequired)
     {
         expr.TypecastRequired = false;
         this.CompileTypecast(expr.ReturnType);
     }
 }
예제 #15
0
 XPathExpr EnsureReturnsNodeSet(XPathExpr expr)
 {
     if (expr.ReturnType != ValueDataType.Sequence)
     {
         this.ThrowError(QueryCompileError.InvalidFunction);
     }
     return(expr);
 }
예제 #16
0
 XPathExpr EnsureReturnsNodeSet(XPathExpr expr)
 {
     if (expr.ReturnType != ValueDataType.Sequence)
     {
         this.ThrowError(QueryCompileError.InvalidFunction);
     }
     return expr;
 }
        private XPathExpr ParseFunctionExpression()
        {
            XPathExpr  expr;
            XPathToken token = this.NextToken(XPathTokenID.Function);

            if (token == null)
            {
                return(null);
            }
            NodeQName name = this.QualifyName(token.Prefix, token.Name);

            this.NextToken(XPathTokenID.LParen, QueryCompileError.InvalidFunction);
            XPathExprList args = new XPathExprList();

            while ((expr = this.ParseExpression()) != null)
            {
                args.Add(expr);
                if (this.NextToken(XPathTokenID.Comma) == null)
                {
                    break;
                }
            }
            XPathExpr expr2 = null;

            if (this.functionLibraries != null)
            {
                QueryFunction function = null;
                for (int i = 0; i < this.functionLibraries.Length; i++)
                {
                    function = this.functionLibraries[i].Bind(name.Name, name.Namespace, args);
                    if (function != null)
                    {
                        expr2 = new XPathFunctionExpr(function, args);
                        break;
                    }
                }
            }
            if ((expr2 == null) && (this.context != null))
            {
                XPathResultType[] argTypes = new XPathResultType[args.Count];
                for (int j = 0; j < args.Count; j++)
                {
                    argTypes[j] = XPathXsltFunctionExpr.ConvertTypeToXslt(args[j].ReturnType);
                }
                string prefix = this.context.LookupPrefix(name.Namespace);
                IXsltContextFunction function2 = this.context.ResolveFunction(prefix, name.Name, argTypes);
                if (function2 != null)
                {
                    expr2 = new XPathXsltFunctionExpr(this.context, function2, args);
                }
            }
            if (expr2 == null)
            {
                this.ThrowError(QueryCompileError.UnsupportedFunction);
            }
            this.NextToken(XPathTokenID.RParen, QueryCompileError.InvalidFunction);
            return(expr2);
        }
 internal XPathConjunctExpr(XPathExprType type, ValueDataType returnType, XPathExpr left, XPathExpr right) : base(type, returnType)
 {
     if ((left == null) || (right == null))
     {
         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.InvalidExpression));
     }
     base.SubExpr.Add(left);
     base.SubExpr.Add(right);
 }
예제 #19
0
 internal XPathConjunctExpr(XPathExprType type, ValueDataType returnType, XPathExpr left, XPathExpr right) : base(type, returnType)
 {
     if ((left == null) || (right == null))
     {
         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.InvalidExpression));
     }
     base.SubExpr.Add(left);
     base.SubExpr.Add(right);
 }
예제 #20
0
 private void NegateIfRequired(XPathExpr expr)
 {
     this.TypecastIfRequired(expr);
     if (expr.Negate)
     {
         expr.Negate = false;
         this.codeBlock.Append(new NegateOpcode());
     }
 }
예제 #21
0
 void NegateIfRequired(XPathExpr expr)
 {
     // We can combine these two since the flags they examine are set in exactly one (the same) place.
     TypecastIfRequired(expr);
     if (expr.Negate)
     {
         expr.Negate = false;
         this.codeBlock.Append(new NegateOpcode());
     }
 }
예제 #22
0
            private void CompileLocationPath(XPathExpr expr)
            {
                XPathStepExpr expr2 = (XPathStepExpr)expr.SubExpr[0];

                this.CompileSteps(expr.SubExpr);
                if (1 == this.compiler.nestingLevel)
                {
                    this.compiler.SetPushInitialContext(expr2.SelectDesc.Type != QueryNodeType.Root);
                }
            }
예제 #23
0
        XPathExpr ParseRelationalExpression()
        {
            XPathExpr leftExpr = this.ParseAdditiveExpression();

            if (null != leftExpr)
            {
                RelationOperator op;

                do
                {
                    op = RelationOperator.None;

                    XPathToken token = this.NextToken();

                    if (null != token)
                    {
                        switch (token.TokenID)
                        {
                        default:
                            this.PushToken(token);
                            break;

                        case XPathTokenID.Lt:
                            op = RelationOperator.Lt;
                            break;

                        case XPathTokenID.Lte:
                            op = RelationOperator.Le;
                            break;

                        case XPathTokenID.Gt:
                            op = RelationOperator.Gt;
                            break;

                        case XPathTokenID.Gte:
                            op = RelationOperator.Ge;
                            break;
                        }
                        if (RelationOperator.None != op)
                        {
                            XPathExpr rightExpr = this.ParseAdditiveExpression();

                            if (null == rightExpr)
                            {
                                this.ThrowError(QueryCompileError.InvalidExpression);
                            }

                            leftExpr = new XPathRelationExpr(op, leftExpr, rightExpr);
                        }
                    }
                } while (RelationOperator.None != op);
            }

            return(leftExpr);
        }
예제 #24
0
        XPathExpr ParsePathExpression()
        {
            XPathExpr pathExpr = this.ParseLocationPath();

            if (null != pathExpr)
            {
                return(pathExpr);
            }

            // Perhaps we have a filter expression
            XPathExpr filterExpr = this.ParseFilterExpression();

            if (null != filterExpr)
            {
                if (null != this.NextToken(XPathTokenID.Slash))
                {
                    EnsureReturnsNodeSet(filterExpr);

                    // Is this a complex filter expression.. i.e. followed by further selections..
                    XPathExprList relPath = this.ParseRelativePath();
                    if (null == relPath)
                    {
                        this.ThrowError(QueryCompileError.InvalidLocationPath);
                    }

                    XPathExpr relPathExpr = new XPathExpr(XPathExprType.RelativePath, ValueDataType.Sequence, relPath);

                    pathExpr = new XPathExpr(XPathExprType.Path, ValueDataType.Sequence);
                    pathExpr.Add(filterExpr);
                    pathExpr.Add(relPathExpr);
                }
                else if (null != this.NextToken(XPathTokenID.DblSlash))
                {
                    EnsureReturnsNodeSet(filterExpr);

                    XPathExprList relPath = this.ParseRelativePath();
                    if (null == relPath)
                    {
                        this.ThrowError(QueryCompileError.InvalidLocationPath);
                    }

                    XPathExpr relPathExpr = new XPathExpr(XPathExprType.RelativePath, ValueDataType.Sequence, relPath);
                    pathExpr = new XPathExpr(XPathExprType.Path, ValueDataType.Sequence);
                    pathExpr.Add(filterExpr);
                    pathExpr.Add(new XPathStepExpr(new NodeSelectCriteria(QueryAxisType.DescendantOrSelf, NodeQName.Empty, QueryNodeType.All)));
                    pathExpr.Add(relPathExpr);
                }
                else
                {
                    pathExpr = filterExpr;
                }
            }

            return(pathExpr);
        }
예제 #25
0
            void CompileLocationPath(XPathExpr expr)
            {
                Fx.Assert(expr.SubExprCount > 0, "");

                XPathStepExpr firstStep = (XPathStepExpr)expr.SubExpr[0];

                this.CompileSteps(expr.SubExpr);

                if (1 == this.compiler.nestingLevel)
                {
                    this.compiler.SetPushInitialContext(firstStep.SelectDesc.Type != QueryNodeType.Root);
                }
            }
예제 #26
0
        XPathExpr ParseMultiplicativeExpression()
        {
            XPathExpr leftExpr = this.ParseUnaryExpression();

            if (null != leftExpr)
            {
                MathOperator op;

                do
                {
                    op = MathOperator.None;

                    XPathToken token = this.NextToken();

                    if (null != token)
                    {
                        switch (token.TokenID)
                        {
                        default:
                            this.PushToken(token);
                            break;

                        case XPathTokenID.Multiply:
                            op = MathOperator.Multiply;
                            break;

                        case XPathTokenID.Div:
                            op = MathOperator.Div;
                            break;

                        case XPathTokenID.Mod:
                            op = MathOperator.Mod;
                            break;
                        }
                        if (MathOperator.None != op)
                        {
                            XPathExpr rightExpr = this.ParseUnaryExpression();

                            if (null == rightExpr)
                            {
                                this.ThrowError(QueryCompileError.InvalidExpression);
                            }

                            leftExpr = new XPathMathExpr(op, leftExpr, rightExpr);
                        }
                    }
                } while (MathOperator.None != op);
            }

            return(leftExpr);
        }
        internal XPathExpr Parse()
        {
            XPathExpr expr = this.ParseExpression();

            if (expr == null)
            {
                this.ThrowError(QueryCompileError.InvalidExpression);
            }
            if (this.NextToken() != null)
            {
                this.ThrowError(QueryCompileError.UnexpectedToken);
            }
            return(expr);
        }
예제 #28
0
            private void CompileFunctionParam(QueryFunction function, XPathExprList paramList, int index)
            {
                XPathExpr expr = paramList[index];

                this.CompileExpression(expr);
                if ((function.ParamTypes[index] != ValueDataType.None) && (expr.ReturnType != function.ParamTypes[index]))
                {
                    if (function.ParamTypes[index] == ValueDataType.Sequence)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.InvalidTypeConversion));
                    }
                    this.CompileTypecast(function.ParamTypes[index]);
                }
            }
예제 #29
0
            private bool IsSpecialInternalFunction(XPathExpr expr)
            {
                if (expr.Type != XPathExprType.XsltFunction)
                {
                    return(false);
                }
                XPathMessageFunction function = ((XPathXsltFunctionExpr)expr).Function as XPathMessageFunction;

                if (function == null)
                {
                    return(false);
                }
                return((function.ReturnType == XPathResultType.NodeSet) && (function.Maxargs == 0));
            }
        private XPathExpr ParseRelationalExpression()
        {
            XPathExpr left = this.ParseAdditiveExpression();

            if (left != null)
            {
                RelationOperator none;
                do
                {
                    none = RelationOperator.None;
                    XPathToken token = this.NextToken();
                    if (token != null)
                    {
                        switch (token.TokenID)
                        {
                        case XPathTokenID.Gt:
                            none = RelationOperator.Gt;
                            break;

                        case XPathTokenID.Gte:
                            none = RelationOperator.Ge;
                            break;

                        case XPathTokenID.Lt:
                            none = RelationOperator.Lt;
                            break;

                        case XPathTokenID.Lte:
                            none = RelationOperator.Le;
                            break;

                        default:
                            this.PushToken(token);
                            break;
                        }
                        if (none != RelationOperator.None)
                        {
                            XPathExpr right = this.ParseAdditiveExpression();
                            if (right == null)
                            {
                                this.ThrowError(QueryCompileError.InvalidExpression);
                            }
                            left = new XPathRelationExpr(none, left, right);
                        }
                    }
                }while (none != RelationOperator.None);
            }
            return(left);
        }
 internal virtual OpcodeBlock Compile(XPathExpr expr)
 {
     this.nestingLevel = 1;
     this.pushInitialContext = false;
     OpcodeBlock block = new XPathExprCompiler(this).Compile(expr);
     if (this.pushInitialContext)
     {
         OpcodeBlock block2 = new OpcodeBlock();
         block2.Append(new PushContextNodeOpcode());
         block2.Append(block);
         block2.Append(new PopContextNodes());
         return block2;
     }
     return block;
 }
 internal void AddBooleanExpression(XPathExprType boolExprType, XPathExpr expr)
 {
     if (boolExprType == expr.Type)
     {
         XPathExprList subExpr = expr.SubExpr;
         for (int i = 0; i < subExpr.Count; i++)
         {
             this.AddBooleanExpression(boolExprType, subExpr[i]);
         }
     }
     else
     {
         this.Add(expr);
     }
 }
        private XPathExpr ParsePredicateExpression()
        {
            XPathExpr expr = null;

            if (this.NextToken(XPathTokenID.LBracket) != null)
            {
                expr = this.ParseExpression();
                if (expr == null)
                {
                    this.ThrowError(QueryCompileError.InvalidPredicate);
                }
                this.NextToken(XPathTokenID.RBracket, QueryCompileError.InvalidPredicate);
            }
            return(expr);
        }
 internal void AddBooleanExpression(XPathExprType boolExprType, XPathExpr expr)
 {
     if (boolExprType == expr.Type)
     {
         XPathExprList subExpr = expr.SubExpr;
         for (int i = 0; i < subExpr.Count; i++)
         {
             this.AddBooleanExpression(boolExprType, subExpr[i]);
         }
     }
     else
     {
         this.Add(expr);
     }
 }
예제 #35
0
 private void CompilePath(XPathExpr expr)
 {
     if (expr.Type == XPathExprType.Filter)
     {
         this.CompileFilter(expr.SubExpr[0]);
     }
     else
     {
         this.CompileExpression(expr.SubExpr[0]);
         if (expr.SubExpr[0].ReturnType == ValueDataType.Sequence)
         {
             if (this.IsSpecialInternalFunction(expr.SubExpr[0]))
             {
                 this.codeBlock.DetachLast();
             }
             else
             {
                 this.codeBlock.Append(new MergeOpcode());
                 this.codeBlock.Append(new PopSequenceToSequenceStackOpcode());
             }
         }
     }
     if (expr.SubExprCount == 2)
     {
         this.CompileRelativePath(expr.SubExpr[1], false);
     }
     else if (expr.SubExprCount == 3)
     {
         XPathExpr     expr2 = expr.SubExpr[1];
         XPathStepExpr expr3 = (XPathStepExpr)expr2;
         if (!expr3.SelectDesc.Axis.IsSupported())
         {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.UnsupportedAxis));
         }
         this.codeBlock.Append(new SelectOpcode(expr3.SelectDesc));
         if (expr3.SubExprCount > 0)
         {
             this.compiler.nestingLevel++;
             if (this.compiler.nestingLevel > 3)
             {
                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.PredicateNestingTooDeep));
             }
             this.CompilePredicates(expr3.SubExpr);
             this.compiler.nestingLevel--;
         }
         this.CompileRelativePath(expr.SubExpr[2], false);
     }
 }
예제 #36
0
        // Compiles top level expressions
        internal virtual OpcodeBlock Compile(XPathExpr expr)
        {
            Fx.Assert(null != expr, "");

            this.nestingLevel = 1;
            this.pushInitialContext = false;

            XPathExprCompiler exprCompiler = new XPathExprCompiler(this);
            OpcodeBlock mainBlock = exprCompiler.Compile(expr);
            if (this.pushInitialContext)
            {
                OpcodeBlock expandedBlock = new OpcodeBlock();
                expandedBlock.Append(new PushContextNodeOpcode());
                expandedBlock.Append(mainBlock);
                expandedBlock.Append(new PopContextNodes());
                return expandedBlock;
            }
            return mainBlock;
        }
예제 #37
0
 internal OpcodeBlock Compile(XPathExpr expr)
 {
     this.codeBlock = new OpcodeBlock(); // struct
     this.CompileExpression(expr);
     return this.codeBlock;
 }
예제 #38
0
 void CompileRelativePath(XPathExpr expr, bool start)
 {
     Fx.Assert(XPathExprType.RelativePath == expr.Type, "");
     this.CompileSteps(expr.SubExpr, start);
     // Step complete. Transfer results onto the value stack
     this.codeBlock.Append(new PopSequenceToValueStackOpcode());
 }
예제 #39
0
 void CompilePredicate(XPathExpr expr)
 {
     // If the expression does not return a boolean, introduce a typecast
     // If the predicate expression is a standalone number literal, interpret it as a literal
     if (expr.IsLiteral && XPathExprType.Number == expr.Type)
     {
         this.CompileLiteralOrdinal(expr);
     }
     else
     {
         this.CompileExpression(expr);
         if (expr.ReturnType == ValueDataType.Double)
         {
             this.codeBlock.Append(new OrdinalOpcode());
         }
         else if (expr.ReturnType != ValueDataType.Boolean)
         {
             this.CompileTypecast(ValueDataType.Boolean);
         }
     }
     // Apply the results of the predicate on the context sequence
     this.codeBlock.Append(new ApplyFilterOpcode());
 }
예제 #40
0
        XPathExpr ParseAndExpression()
        {
            XPathExpr eqExpr = this.ParseEqualityExpression();

            if (null != eqExpr && null != this.NextToken(XPathTokenID.And))
            {
                XPathExpr andExpr = new XPathExpr(XPathExprType.And, ValueDataType.Boolean);

                andExpr.AddBooleanExpression(XPathExprType.And, eqExpr);
                do
                {
                    eqExpr = this.ParseEqualityExpression();
                    if (eqExpr == null)
                        this.ThrowError(QueryCompileError.InvalidExpression);
                    andExpr.AddBooleanExpression(XPathExprType.And, eqExpr);
                } while (null != this.NextToken(XPathTokenID.And));

                return andExpr;
            }

            return eqExpr;
        }
예제 #41
0
 internal void Add(XPathExpr expr)
 {
     Fx.Assert(null != expr, "");
     this.list.Add(expr);
 }
예제 #42
0
        XPathExpr ParsePathExpression()
        {
            XPathExpr pathExpr = this.ParseLocationPath();

            if (null != pathExpr)
            {
                return pathExpr;
            }

            // Perhaps we have a filter expression
            XPathExpr filterExpr = this.ParseFilterExpression();
            if (null != filterExpr)
            {
                if (null != this.NextToken(XPathTokenID.Slash))
                {
                    EnsureReturnsNodeSet(filterExpr);

                    // Is this a complex filter expression.. i.e. followed by further selections..
                    XPathExprList relPath = this.ParseRelativePath();
                    if (null == relPath)
                    {
                        this.ThrowError(QueryCompileError.InvalidLocationPath);
                    }

                    XPathExpr relPathExpr = new XPathExpr(XPathExprType.RelativePath, ValueDataType.Sequence, relPath);

                    pathExpr = new XPathExpr(XPathExprType.Path, ValueDataType.Sequence);
                    pathExpr.Add(filterExpr);
                    pathExpr.Add(relPathExpr);
                }
                else if (null != this.NextToken(XPathTokenID.DblSlash))
                {
                    EnsureReturnsNodeSet(filterExpr);

                    XPathExprList relPath = this.ParseRelativePath();
                    if (null == relPath)
                    {
                        this.ThrowError(QueryCompileError.InvalidLocationPath);
                    }

                    XPathExpr relPathExpr = new XPathExpr(XPathExprType.RelativePath, ValueDataType.Sequence, relPath);
                    pathExpr = new XPathExpr(XPathExprType.Path, ValueDataType.Sequence);
                    pathExpr.Add(filterExpr);
                    pathExpr.Add(new XPathStepExpr(new NodeSelectCriteria(QueryAxisType.DescendantOrSelf, NodeQName.Empty, QueryNodeType.All)));
                    pathExpr.Add(relPathExpr);
                }
                else
                {
                    pathExpr = filterExpr;
                }
            }

            return pathExpr;
        }
예제 #43
0
 OpcodeBlock CompileBlock(XPathExpr expr)
 {
     XPathExprCompiler compiler = new XPathExprCompiler(this);
     return compiler.Compile(expr);
 }
예제 #44
0
            bool IsSpecialInternalFunction(XPathExpr expr)
            {
                if (expr.Type != XPathExprType.XsltFunction)
                {
                    return false;
                }

                XPathMessageFunction func = ((XPathXsltFunctionExpr)expr).Function as XPathMessageFunction;
                if (func != null)
                {
                    return func.ReturnType == XPathResultType.NodeSet && func.Maxargs == 0;
                }

                return false;
            }
예제 #45
0
        XPathExpr ParseOrExpression()
        {
            XPathExpr andExpr = this.ParseAndExpression();

            if (null != andExpr && null != this.NextToken(XPathTokenID.Or))
            {
                XPathExpr orExpr = new XPathExpr(XPathExprType.Or, ValueDataType.Boolean);

                orExpr.AddBooleanExpression(XPathExprType.Or, andExpr);
                do
                {
                    andExpr = this.ParseAndExpression();
                    if (andExpr == null)
                        this.ThrowError(QueryCompileError.InvalidExpression);
                    orExpr.AddBooleanExpression(XPathExprType.Or, andExpr);
                } while (null != this.NextToken(XPathTokenID.Or));

                return orExpr;
            }

            return andExpr;
        }
예제 #46
0
        XPathExpr ParseFilterExpression()
        {
            XPathExpr primaryExpr = this.ParsePrimaryExpression();

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

            XPathExpr filterExpr = new XPathExpr(XPathExprType.Filter, primaryExpr.ReturnType);
            filterExpr.Add(primaryExpr);

            XPathExpr predicate = this.ParsePredicateExpression();

            if (null != predicate)
            {
                EnsureReturnsNodeSet(primaryExpr);

                //XPathExpr filterExpr = new XPathExpr(XPathExprType.Filter, ValueDataType.Sequence);

                //filterExpr.Add(primaryExpr);
                filterExpr.Add(predicate);

                // Read in any additional predicates
                while (null != (predicate = this.ParsePredicateExpression()))
                {
                    filterExpr.Add(predicate);
                }

                return filterExpr;
            }

            return primaryExpr;
        }
예제 #47
0
            // Compiles expressions at nesting level == 1 -> boolean expressions that can be processed
            // with less complex opcodes because they will never track multiple sequences simultaneously
            void CompileBasicBoolean(XPathExpr expr, bool testValue)
            {
                // Boolean expressions must always have at least 2 sub expressions
                Fx.Assert(expr.SubExprCount > 1, "");
                Fx.Assert(this.compiler.nestingLevel == 1, "");

                OpcodeBlock boolBlock = new OpcodeBlock(); // struct
                Opcode blockEnd = new BlockEndOpcode();
                XPathExprList subExprList = expr.SubExpr;

                // Compile sub-expressions
                for (int i = 0; i < subExprList.Count; ++i)
                {
                    XPathExpr subExpr = subExprList[i];
                    boolBlock.Append(this.CompileBlock(subExpr));
                    // Make sure each sub-expression can produce a boolean result
                    if (subExpr.ReturnType != ValueDataType.Boolean)
                    {
                        boolBlock.Append(new TypecastOpcode(ValueDataType.Boolean));
                    }
                    if (i < (subExprList.Count - 1))
                    {
                        // No point jumping if this is the last expression
                        boolBlock.Append(new JumpIfOpcode(blockEnd, testValue));
                    }
                }
                boolBlock.Append(blockEnd);
                this.codeBlock.Append(boolBlock);
            }
 internal void Add(XPathExpr expr)
 {
     this.list.Add(expr);
 }
 internal XPathRelationExpr(RelationOperator op, XPathExpr left, XPathExpr right) : base(XPathExprType.Relational, ValueDataType.Boolean, left, right)
 {
     this.op = op;
 }
예제 #50
0
 void NegateIfRequired(XPathExpr expr)
 {
     // We can combine these two since the flags they examine are set in exactly one (the same) place.
     TypecastIfRequired(expr);
     if (expr.Negate)
     {
         expr.Negate = false;
         this.codeBlock.Append(new NegateOpcode());
     }
 }
예제 #51
0
 void TypecastIfRequired(XPathExpr expr)
 {
     if (expr.TypecastRequired)
     {
         expr.TypecastRequired = false;
         CompileTypecast(expr.ReturnType);
     }
 }
예제 #52
0
            void CompileLiteralOrdinal(XPathExpr expr)
            {
                int ordinal = 0;
                try
                {
                    XPathNumberExpr numExpr = (XPathNumberExpr)expr;
                    ordinal = Convert.ToInt32(numExpr.Number);
                    if (numExpr.Negate)
                    {
                        ordinal = -ordinal;
                        numExpr.Negate = false;
                    }
                    if (ordinal < 1)
                    {
                        this.ThrowError(QueryCompileError.InvalidOrdinal);
                    }
                }
                catch (OverflowException)
                {
                    this.ThrowError(QueryCompileError.InvalidOrdinal);
                }

                if (0 != (this.compiler.flags & QueryCompilerFlags.InverseQuery))
                {
                    this.codeBlock.Append(new PushContextPositionOpcode());
                    this.codeBlock.Append(new NumberEqualsOpcode(ordinal));
                }
                else
                {
                    this.codeBlock.Append(new LiteralOrdinalOpcode(ordinal));
                }
            }
예제 #53
0
            void CompileBoolean(XPathExpr expr, bool testValue)
            {
                // Boolean expressions must always have at least 2 sub expressions
                Fx.Assert(expr.SubExprCount > 1, "");

                if (this.compiler.nestingLevel == 1)
                {
                    this.CompileBasicBoolean(expr, testValue);
                    return;
                }

                OpcodeBlock boolBlock = new OpcodeBlock(); // struct
                Opcode blockEnd = new BlockEndOpcode();
                // Set up the result mask
                boolBlock.Append(new PushBooleanOpcode(testValue));
                XPathExprList subExprList = expr.SubExpr;
                XPathExpr subExpr;

                // the first expression needs the least work..
                subExpr = subExprList[0];
                boolBlock.Append(this.CompileBlock(subExpr));
                if (subExpr.ReturnType != ValueDataType.Boolean)
                {
                    boolBlock.Append(new TypecastOpcode(ValueDataType.Boolean));
                }
                boolBlock.Append(new ApplyBooleanOpcode(blockEnd, testValue));

                // Compile remaining sub-expressions
                for (int i = 1; i < subExprList.Count; ++i)
                {
                    subExpr = subExprList[i];
                    boolBlock.Append(new StartBooleanOpcode(testValue));
                    boolBlock.Append(this.CompileBlock(subExpr));
                    // Make sure each sub-expression can produce a boolean result
                    if (subExpr.ReturnType != ValueDataType.Boolean)
                    {
                        boolBlock.Append(new TypecastOpcode(ValueDataType.Boolean));
                    }
                    boolBlock.Append(new EndBooleanOpcode(blockEnd, testValue));
                }
                boolBlock.Append(blockEnd);
                this.codeBlock.Append(boolBlock);
            }
예제 #54
0
            void CompileLocationPath(XPathExpr expr)
            {
                Fx.Assert(expr.SubExprCount > 0, "");

                XPathStepExpr firstStep = (XPathStepExpr)expr.SubExpr[0];

                this.CompileSteps(expr.SubExpr);

                if (1 == this.compiler.nestingLevel)
                {
                    this.compiler.SetPushInitialContext(firstStep.SelectDesc.Type != QueryNodeType.Root);
                }
            }
예제 #55
0
        internal void AddBooleanExpression(XPathExprType boolExprType, XPathExpr expr)
        {
            Fx.Assert(boolExprType == this.type, "");

            // An boolean sub0expression that is of the same type as its container should be merged and flattened
            // into its parent
            if (boolExprType == expr.Type)
            {
                XPathExprList subExprList = expr.SubExpr;
                for (int i = 0; i < subExprList.Count; ++i)
                {
                    this.AddBooleanExpression(boolExprType, subExprList[i]);
                }
            }
            else
            {
                this.Add(expr);
            }
        }
예제 #56
0
            void CompilePath(XPathExpr expr)
            {
                Fx.Assert(expr.SubExprCount == 2 || expr.SubExprCount == 3, "");

                if (expr.Type == XPathExprType.Filter)
                {
                    this.CompileFilter(expr.SubExpr[0]);
                }
                else
                {
                    this.CompileExpression(expr.SubExpr[0]);
                    if (expr.SubExpr[0].ReturnType == ValueDataType.Sequence)
                    {
                        if (IsSpecialInternalFunction(expr.SubExpr[0]))
                        {
                            this.codeBlock.DetachLast();
                        }
                        else
                        {
                            this.codeBlock.Append(new MergeOpcode());
                            this.codeBlock.Append(new PopSequenceToSequenceStackOpcode());
                        }
                    }
                }

                if (expr.SubExprCount == 2)
                {
                    this.CompileRelativePath(expr.SubExpr[1], false);
                }
                else if (expr.SubExprCount == 3)
                {
                    // Compile the step
                    XPathExpr e = expr.SubExpr[1];
                    Fx.Assert(XPathExprType.PathStep == e.Type, "");

                    XPathStepExpr step = (XPathStepExpr)e;
                    Fx.Assert(QueryNodeType.Root != step.SelectDesc.Type, "");

                    if (!step.SelectDesc.Axis.IsSupported())
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.UnsupportedAxis));
                    }

                    this.codeBlock.Append(new SelectOpcode(step.SelectDesc));

                    // The step may have predicates..
                    if (step.SubExprCount > 0)
                    {
                        this.compiler.nestingLevel++;
                        if (this.compiler.nestingLevel > 3) // throw if we find something deepter than [ [ ] ]
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.PredicateNestingTooDeep));
                        }
                        this.CompilePredicates(step.SubExpr);
                        this.compiler.nestingLevel--;
                    }

                    // Compile the relative path
                    this.CompileRelativePath(expr.SubExpr[2], false);
                }
            }
예제 #57
0
            void CompileExpression(XPathExpr expr)
            {
                Fx.Assert(null != expr, "");

                switch (expr.Type)
                {
                    default:
                        this.ThrowError(QueryCompileError.UnsupportedExpression);
                        break;

                    case XPathExprType.And:
                        this.CompileBoolean(expr, true);
                        break;

                    case XPathExprType.Or:
                        this.CompileBoolean(expr, false);
                        break;

                    case XPathExprType.Relational:
                        this.CompileRelational((XPathRelationExpr)expr);
                        break;

                    case XPathExprType.Function:
                        this.CompileFunction((XPathFunctionExpr)expr);
                        break;

                    case XPathExprType.Union:
                        {
                            XPathConjunctExpr unionExpr = (XPathConjunctExpr)expr;
                            this.CompileExpression(unionExpr.Left);
                            this.CompileExpression(unionExpr.Right);
                            this.codeBlock.Append(new UnionOpcode());
                        }
                        break;

                    case XPathExprType.RelativePath:
                        this.CompileRelativePath(expr, true);
                        break;

                    case XPathExprType.LocationPath:
                        if (expr.SubExprCount > 0)
                        {
                            this.CompileLocationPath(expr);
                            // Step complete. Transfer results onto the value stack
                            this.codeBlock.Append(new PopSequenceToValueStackOpcode());
                        }
                        break;

                    case XPathExprType.Math:
                        this.CompileMath((XPathMathExpr)expr);
                        break;

                    case XPathExprType.Number:
                        XPathNumberExpr number = (XPathNumberExpr)expr;
                        double literal = number.Number;
                        if (number.Negate)
                        {
                            number.Negate = false;
                            literal = -literal;
                        }
                        this.codeBlock.Append(new PushNumberOpcode(literal));
                        break;

                    case XPathExprType.String:
                        this.codeBlock.Append(new PushStringOpcode(((XPathStringExpr)expr).String));
                        break;

                    case XPathExprType.Filter:
                        this.CompileFilter(expr);
                        if (expr.ReturnType == ValueDataType.Sequence)
                        {
                            this.codeBlock.Append(new PopSequenceToValueStackOpcode());
                        }
                        break;

                    case XPathExprType.Path:
                        this.CompilePath(expr);
                        if (expr.SubExprCount == 0 && expr.ReturnType == ValueDataType.Sequence)
                        {
                            this.codeBlock.Append(new PopSequenceToValueStackOpcode());
                        }
                        break;

                    case XPathExprType.XsltFunction:
                        this.CompileXsltFunction((XPathXsltFunctionExpr)expr);
                        break;

                    case XPathExprType.XsltVariable:
                        this.CompileXsltVariable((XPathXsltVariableExpr)expr);
                        break;
                }

                NegateIfRequired(expr);
            }
 internal void Add(XPathExpr expr)
 {
     this.SubExpr.Add(expr);
 }
예제 #59
0
            void CompileFilter(XPathExpr expr)
            {
                Fx.Assert(XPathExprType.Filter == expr.Type, "");
                // The filter expression has two components - the expression and its predicate
                // It may have an optional relative path following it
                //Debug.Assert(expr.SubExprCount <= 3);                
                XPathExprList subExpr = expr.SubExpr;

                XPathExpr filterExpr = subExpr[0];
                if (subExpr.Count > 1 && ValueDataType.Sequence != filterExpr.ReturnType)
                {
                    this.ThrowError(QueryCompileError.InvalidExpression);
                }
                // The filter expression will return a sequence and push it onto the value stack
                // Transfer it back to the sequence stack, so we can keep working on it
                this.CompileExpression(filterExpr);
                if (filterExpr.ReturnType == ValueDataType.Sequence)
                {
                    if (!IsSpecialInternalFunction(filterExpr) && expr.SubExprCount > 1)
                    {
                        // Flatten the sequence and move it to the sequence stack
                        this.codeBlock.Append(new MergeOpcode());
                        this.codeBlock.Append(new PopSequenceToSequenceStackOpcode());
                    }
                    else if (IsSpecialInternalFunction(filterExpr) && expr.SubExprCount > 1)
                    {
                        this.codeBlock.DetachLast();
                    }

                    // Now, apply the predicates
                    this.compiler.nestingLevel++;
                    if (this.compiler.nestingLevel > 3) // throw if we find something deepter than [ [ ] ]
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.PredicateNestingTooDeep));
                    }
                    for (int i = 1; i < expr.SubExprCount; ++i)
                    {
                        this.CompilePredicate(subExpr[i]);
                    }
                    this.compiler.nestingLevel--;
                }
            }
예제 #60
0
 internal XPathMathExpr(MathOperator op, XPathExpr left, XPathExpr right)
     : base(XPathExprType.Math, ValueDataType.Double, left, right)
 {
     this.op = op;
 }