XPathParser.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Dispatcher / XPathParser.cs / 1 / XPathParser.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------
namespace System.ServiceModel.Dispatcher
{ 
    using System.Diagnostics;
    using System.Xml; 
    using System.Xml.Xsl; 
    using System.Xml.XPath;
 
    internal class XPathParser
    {
        IFunctionLibrary[] functionLibraries;
 
        XPathLexer lexer;
 
        XmlNamespaceManager namespaces; 

        XPathToken readToken; 

        XsltContext context;

        internal XPathParser(string xpath, XmlNamespaceManager namespaces, IFunctionLibrary[] functionLibraries) 
        {
            DiagnosticUtility.DebugAssert(null != xpath, ""); 
            this.functionLibraries = functionLibraries; 
            this.namespaces = namespaces;
            this.lexer = new XPathLexer(xpath); 
            this.context = namespaces as XsltContext;
        }

        XPathExpr EnsureReturnsNodeSet(XPathExpr expr) 
        {
            if(expr.ReturnType != ValueDataType.Sequence) 
            { 
                this.ThrowError(QueryCompileError.InvalidFunction);
            } 
            return expr;
        }

        XPathToken NextToken() 
        {
            if (null != this.readToken) 
            { 
                XPathToken nextToken = this.readToken;
 
                this.readToken = null;
                return nextToken;
            }
 
            while (this.lexer.MoveNext())
            { 
                if (XPathTokenID.Whitespace != this.lexer.Token.TokenID) 
                {
                    return this.lexer.Token; 
                }
            }

            return null; 
        }
 
        XPathToken NextToken(XPathTokenID id) 
        {
            XPathToken token = this.NextToken(); 

            if (null != token)
            {
                if (id == token.TokenID) 
                {
                    return token; 
                } 

                this.readToken = token; 
            }

            return null;
        } 

        XPathToken NextToken(XPathTokenID id, QueryCompileError error) 
        { 
            XPathToken token = this.NextToken(id);
 
            if (null == token)
            {
                this.ThrowError(error);
            } 

            return token; 
        } 

        XPathToken NextTokenClass(XPathTokenID tokenClass) 
        {
            XPathToken token = this.NextToken();

            if (null != token) 
            {
                if (0 != (token.TokenID & tokenClass)) 
                { 
                    return token;
                } 

                this.readToken = token;
            }
 
            return null;
        } 
 
        NodeQName QualifyName(string prefix, string name)
        { 
            if (null != this.namespaces && null != prefix && prefix.Length > 0)
            {
                prefix = this.namespaces.NameTable.Add(prefix);
 
                string ns = this.namespaces.LookupNamespace(prefix);
 
                if (null == ns) 
                {
                    this.ThrowError(QueryCompileError.NoNamespaceForPrefix); 
                }

                return new NodeQName(name, ns);
            } 

            return new NodeQName(name); 
        } 

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

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

            // If we stopped before the entire xpath was lexed, we hit something we could not tokenize 
            XPathToken lastToken = this.NextToken();

            if (null != lastToken)
            { 
                this.ThrowError(QueryCompileError.UnexpectedToken);
            } 
 
            return expr;
        } 

        XPathExprList ParseAbsolutePath()
        {
            XPathExprList path = null; 
            XPathToken token = this.NextToken();
 
            if (null != token) 
            {
                switch (token.TokenID) 
                {
                    default:
                        this.PushToken(token);
                        break; 

                    case XPathTokenID.Slash: 
                        path = new XPathExprList(); 
                        path.Add(new XPathStepExpr(new NodeSelectCriteria(QueryAxisType.Child, NodeQName.Empty, QueryNodeType.Root)));
                        break; 

                    case XPathTokenID.DblSlash:
                        // '//' is special. If found at the start of an absolute path, it implies that the descendant-or-self axis
                        // is applied to the ROOT 
                        path = new XPathExprList();
                        path.Add(new XPathStepExpr(new NodeSelectCriteria(QueryAxisType.Child, NodeQName.Empty, QueryNodeType.Root))); 
                        path.Add(new XPathStepExpr(new NodeSelectCriteria(QueryAxisType.DescendantOrSelf, NodeQName.Empty, QueryNodeType.All))); 
                        break;
                } 
            }

            if (null != path)
            { 
                this.ParseRelativePath(path);
            } 
 
            return path;
        } 

        XPathExpr ParseAdditiveExpression()
        {
            XPathExpr leftExpr = this.ParseMultiplicativeExpression(); 

            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.Plus: 
                                op = MathOperator.Plus; 
                                break;
 
                            case XPathTokenID.Minus:
                                op = MathOperator.Minus;
                                break;
                        } 
                        if (MathOperator.None != op)
                        { 
                            XPathExpr rightExpr = this.ParseMultiplicativeExpression(); 

                            if (null == rightExpr) 
                            {
                                this.ThrowError(QueryCompileError.InvalidExpression);
                            }
 
                            leftExpr = new XPathMathExpr(op, leftExpr, rightExpr);
                        } 
                    } 
                } while (MathOperator.None != op);
            } 

            return leftExpr;
        }
 
        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; 
        }
 
        QueryAxisType ParseAxisSpecifier()
        {
            if (null != this.NextToken(XPathTokenID.AtSign))
            { 
                return QueryAxisType.Attribute;
            } 
 
            QueryAxisType axisType = QueryAxisType.None;
            XPathToken token; 

            if (null != (token = this.NextTokenClass(XPathTokenID.Axis)))
            {
                switch (token.TokenID) 
                {
                    default: 
                        this.ThrowError(QueryCompileError.UnsupportedAxis); 
                        break;
 
                    case XPathTokenID.Attribute:
                        axisType = QueryAxisType.Attribute;
                        break;
 
                    case XPathTokenID.Child:
                        axisType = QueryAxisType.Child; 
                        break; 

                    case XPathTokenID.Descendant: 
                        axisType = QueryAxisType.Descendant;
                        break;

                    case XPathTokenID.DescendantOrSelf: 
                        axisType = QueryAxisType.DescendantOrSelf;
                        break; 
 
                    case XPathTokenID.Self:
                        axisType = QueryAxisType.Self; 
                        break;
                }

                // axis specifiers must be followed by a '::' 
                this.NextToken(XPathTokenID.DblColon, QueryCompileError.InvalidAxisSpecifier);
            } 
 
            return axisType;
        } 

        XPathExpr ParseEqualityExpression()
        {
            XPathExpr leftExpr = this.ParseRelationalExpression(); 

            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.Eq: 
                                op = RelationOperator.Eq; 
                                break;
 
                            case XPathTokenID.Neq:
                                op = RelationOperator.Ne;
                                break;
                        } 
                        if (RelationOperator.None != op)
                        { 
                            XPathExpr rightExpr = this.ParseRelationalExpression(); 

                            if (null == rightExpr) 
                            {
                                this.ThrowError(QueryCompileError.InvalidExpression);
                            }
 
                            leftExpr = new XPathRelationExpr(op, leftExpr, rightExpr);
                        } 
                    } 
                } while (RelationOperator.None != op);
            } 

            return leftExpr;
        }
 
        XPathExpr ParseExpression()
        { 
            return this.ParseOrExpression(); 
        }
 
        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; 
        } 

        XPathExpr ParseFunctionExpression() 
        {
            XPathToken functionToken = this.NextToken(XPathTokenID.Function);

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

            NodeQName functionName = this.QualifyName(functionToken.Prefix, functionToken.Name); 
            this.NextToken(XPathTokenID.LParen, QueryCompileError.InvalidFunction);

            XPathExprList args = new XPathExprList();
 
            // Read in arguments
            XPathExpr arg; 
 
            while (null != (arg = this.ParseExpression()))
            { 
                args.Add(arg);
                if (null == this.NextToken(XPathTokenID.Comma))
                {
                    break; 
                }
            } 
 
            // Bind to the function
            // Try each library until we can bind the function 
            XPathExpr functionImpl = null;
            if (null != this.functionLibraries)
            {
                QueryFunction fun = null; 
                for (int i = 0; i < this.functionLibraries.Length; ++i)
                { 
                    if (null != (fun = this.functionLibraries[i].Bind(functionName.Name, functionName.Namespace, args))) 
                    {
                        functionImpl = new XPathFunctionExpr(fun, args); 
                        break;
                    }
                }
            } 

            // Try to bind using the XsltContext 
            if (null == functionImpl && this.context != null) 
            {
                XPathResultType[] argTypes = new XPathResultType[args.Count]; 
                for(int i = 0; i < args.Count; ++i)
                {
                    argTypes[i] = XPathXsltFunctionExpr.ConvertTypeToXslt(args[i].ReturnType);
                } 
                string prefix = this.context.LookupPrefix(functionName.Namespace);
                IXsltContextFunction xsltFun = this.context.ResolveFunction(prefix, functionName.Name, argTypes); 
                if(xsltFun != null) 
                {
                    functionImpl = new XPathXsltFunctionExpr(this.context, xsltFun, args); 
                }
            }

            if (null == functionImpl) 
            {
                this.ThrowError(QueryCompileError.UnsupportedFunction); 
            } 

            this.NextToken(XPathTokenID.RParen, QueryCompileError.InvalidFunction); 
            return functionImpl;
        }

        internal XPathExpr ParseLocationPath() 
        {
            XPathExprList path = this.ParseAbsolutePath(); 
 
            if (null == path)
            { 
                path = this.ParseRelativePath();
            }

            if (null != path) 
            {
                return new XPathExpr(XPathExprType.LocationPath, ValueDataType.Sequence, path); 
            } 

            return null; 
        }

        XPathExpr ParseLiteralExpression()
        { 
            XPathToken literal;
 
            if (null != (literal = this.NextToken(XPathTokenID.Literal))) 
            {
                return new XPathStringExpr(literal.Name); 
            }

            return null;
        } 

        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;
        }

        NodeSelectCriteria ParseNodeTest(QueryAxisType axisType) 
        {
            DiagnosticUtility.DebugAssert(QueryAxisType.None != axisType, ""); 
 
            QueryAxis axis = QueryDataModel.GetAxis(axisType);
            XPathToken token; 
            NodeQName qname = NodeQName.Empty;

            if (null != (token = this.NextTokenClass(XPathTokenID.NameTest)))
            { 
                switch (token.TokenID)
                { 
                    default: 
                        this.ThrowError(QueryCompileError.UnexpectedToken);
                        break; 

                    case XPathTokenID.Wildcard:
                        qname = new NodeQName(QueryDataModel.Wildcard, QueryDataModel.Wildcard);
                        break; 

                    case XPathTokenID.NameTest: 
                        qname = this.QualifyName(token.Prefix, token.Name); 
                        break;
 
                    case XPathTokenID.NameWildcard:
                        qname = this.QualifyName(token.Prefix, QueryDataModel.Wildcard);
                        break;
                } 
            }
 
            QueryNodeType nodeType = QueryNodeType.Any; 

            if (qname.IsEmpty) 
            {
                // Check for nodeTests
                if (null == (token = this.NextTokenClass(XPathTokenID.NodeType)))
                { 
                    // Not a NodeTest either.
                    return null; 
                } 

                switch (token.TokenID) 
                {
                    default:
                        this.ThrowError(QueryCompileError.UnsupportedNodeTest);
                        break; 

                    case XPathTokenID.Comment: 
                        nodeType = QueryNodeType.Comment; 
                        break;
 
                    case XPathTokenID.Text:
                        nodeType = QueryNodeType.Text;
                        break;
 
                    case XPathTokenID.Processing:
                        nodeType = QueryNodeType.Processing; 
                        break; 

                    case XPathTokenID.Node: 
                        nodeType = QueryNodeType.All;
                        break;
                }
 
                // Make sure the nodes being selected CAN actually be selected from this axis
                if (0 == (axis.ValidNodeTypes & nodeType)) 
                { 
                    this.ThrowError(QueryCompileError.InvalidNodeType);
                } 

                // Eat ()
                this.NextToken(XPathTokenID.LParen, QueryCompileError.InvalidNodeTest);
                this.NextToken(XPathTokenID.RParen, QueryCompileError.InvalidNodeTest); 
            }
            else 
            { 
                nodeType = axis.PrincipalNodeType;
            } 

            return new NodeSelectCriteria(axisType, qname, nodeType);
        }
 
        XPathExpr ParseNumberExpression()
        { 
            XPathToken number; 

            if (null != (number = this.NextTokenClass(XPathTokenID.Number))) 
            {
                return new XPathNumberExpr(number.Number);
            }
 
            return null;
        } 
 
        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;
        }

        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;
        }
 
        XPathExprList ParsePredicates()
        { 
            XPathExprList predicates = null; 
            XPathExpr predicate = this.ParsePredicateExpression();
 
            if (null != predicate)
            {
                predicates = new XPathExprList();
                predicates.Add(predicate); 
                while (null != (predicate = this.ParsePredicateExpression()))
                { 
                    predicates.Add(predicate); 
                }
            } 

            return predicates;
        }
 
        XPathExpr ParsePredicateExpression()
        { 
            XPathExpr predicate = null; 

            if (null != this.NextToken(XPathTokenID.LBracket)) 
            {
                predicate = this.ParseExpression();
                if (null == predicate)
                { 
                    this.ThrowError(QueryCompileError.InvalidPredicate);
                } 
 
                this.NextToken(XPathTokenID.RBracket, QueryCompileError.InvalidPredicate);
            } 

            return predicate;
        }
 
        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; 
        }

        XPathExprList ParseRelativePath()
        { 
            XPathExprList path = new XPathExprList();
 
            if (this.ParseRelativePath(path)) 
            {
                return path; 
            }

            return null;
        } 

        bool ParseRelativePath(XPathExprList path) 
        { 
            DiagnosticUtility.DebugAssert(null != path, "");
 
            XPathStepExpr step = this.ParseStep();

            if (null == step)
            { 
                return false;
            } 
 
            path.Add(step);
            while (true) 
            {
                if (null != this.NextToken(XPathTokenID.Slash))
                {
                    step = this.ParseStep(); 
                }
                else if (null != this.NextToken(XPathTokenID.DblSlash)) 
                { 
                    step = new XPathStepExpr(new NodeSelectCriteria(QueryAxisType.DescendantOrSelf, NodeQName.Empty, QueryNodeType.All));
                    path.Add(step); 
                    step = this.ParseStep();
                }
                else
                { 
                    break;
                } 
 
                if (null == step)
                { 
                    this.ThrowError(QueryCompileError.InvalidLocationPath);
                }

                path.Add(step); 
            }
 
            return true; 
        }
 
        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; 
        }

        XPathStepExpr ParseStep()
        { 
            QueryAxisType axis = this.ParseAxisSpecifier();
            NodeSelectCriteria selectDesc = null; 
            bool abbreviatedStep = false; 

            if (QueryAxisType.None != axis) 
            {
                // Valid axis specifier - must be followed by a nodeTest
                selectDesc = this.ParseNodeTest(axis);
            } 
            else
            { 
                // No axis specifier. This could be an abbreviated step - shortcuts for 'self' or 'parent' 
                if (null != this.NextToken(XPathTokenID.Period))
                { 
                    selectDesc = new NodeSelectCriteria(QueryAxisType.Self, NodeQName.Empty, QueryNodeType.All);
                    abbreviatedStep = true;
                }
                else if (null != this.NextToken(XPathTokenID.DblPeriod)) 
                {
                    // A shortcut for parent 
                    selectDesc = new NodeSelectCriteria(QueryAxisType.Parent, NodeQName.Empty, QueryNodeType.Ancestor); 
                    abbreviatedStep = true;
                } 
                else
                {
                    // No axis specifier provided. Assume child
                    if (null == (selectDesc = this.ParseNodeTest(QueryAxisType.Child))) 
                    {
                        // No nodeTest either.. clearly not a Step 
                        return null; 
                    }
                } 
            }

            if (null == selectDesc)
            { 
                this.ThrowError(QueryCompileError.InvalidLocationStep);
            } 
 
            XPathExprList predicates = null;
 
            if (!abbreviatedStep)
            {
                // Abbreviated steps are not permitted predicates
                predicates = this.ParsePredicates(); 
            }
 
            return new XPathStepExpr(selectDesc, predicates); 
        }
 
        XPathExpr ParseUnaryExpression()
        {
            bool negate = false, anyNegate = false;
            for(; null != this.NextToken(XPathTokenID.Minus); anyNegate = true, negate = !negate); 
            XPathExpr expr = ParseUnionExpression();
            if(expr != null) 
            { 
                // If there were any negations at all, the type gets converted to a number
                if(anyNegate && expr.ReturnType != ValueDataType.Double) 
                {
                    expr.ReturnType = ValueDataType.Double;
                    expr.TypecastRequired = true;
                } 
                expr.Negate = negate;
            } 
            return expr; 
        }
 
        internal XPathExpr ParseUnionExpression()
        {
            XPathExpr leftExpr = this.ParsePathExpression();
 
            if (null != leftExpr)
            { 
                if (null != this.NextToken(XPathTokenID.Pipe)) 
                {
                    EnsureReturnsNodeSet(leftExpr); 

                    XPathExpr rightExpr = this.ParseUnionExpression();
                    if(rightExpr == null)
                    { 
                        ThrowError(QueryCompileError.CouldNotParseExpression);
                    } 
                    EnsureReturnsNodeSet(rightExpr); 

                    return new XPathConjunctExpr(XPathExprType.Union, ValueDataType.Sequence, leftExpr, rightExpr); 
                }
            }

            return leftExpr; 
        }
 
        internal XPathExpr ParseVariableExpression() 
        {
            XPathExpr expr = null; 
            if(this.context != null)
            {
                XPathToken varTok = this.NextToken(XPathTokenID.Variable);
                if(varTok != null) 
                {
                    NodeQName varName = this.QualifyName(varTok.Prefix, varTok.Name); 
                    string prefix = this.context.LookupPrefix(varName.Namespace); 

                    IXsltContextVariable var = this.context.ResolveVariable(prefix, varName.Name); 
                    if(var != null)
                    {
                        expr = new XPathXsltVariableExpr(this.context, var);
                    } 
                }
            } 
            return expr; 
        }
 
        void PushToken(XPathToken token)
        {
            DiagnosticUtility.DebugAssert(null == this.readToken, "");
            this.readToken = token; 
        }
 
        internal void ThrowError(QueryCompileError error) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(error, this.lexer.ConsumedSubstring())); 
        }

        internal struct QName
        { 
            string prefix;
 
            string name; 

            internal QName(string prefix, string name) 
            {
                DiagnosticUtility.DebugAssert(null != prefix, "");
                this.prefix = prefix;
                this.name = name; 
            }
 
            internal string Prefix 
            {
                get 
                {
                    return this.prefix;
                }
            } 

            internal string Name 
            { 
                get
                { 
                    return this.name;
                }
            }
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK