| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Dispatcher
- {
- using System.Runtime;
- using System.Xml;
- using System.Xml.XPath;
- using System.Xml.Xsl;
- class XPathParser
- {
- IFunctionLibrary[] functionLibraries;
- XPathLexer lexer;
- XmlNamespaceManager namespaces;
- XPathToken readToken;
- XsltContext context;
- internal XPathParser(string xpath, XmlNamespaceManager namespaces, IFunctionLibrary[] functionLibraries)
- {
- Fx.Assert(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)
- {
- Fx.Assert(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)
- {
- Fx.Assert(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)
- {
- Fx.Assert(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)
- {
- Fx.Assert(null != prefix, "");
- this.prefix = prefix;
- this.name = name;
- }
- internal string Prefix
- {
- get
- {
- return this.prefix;
- }
- }
- internal string Name
- {
- get
- {
- return this.name;
- }
- }
- }
- }
- }
|