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); } }
public QueryFunction Bind(string functionName, string functionNamespace, XPathExprList args) { Fx.Assert(null != functionName && null != args, ""); // Variable length argument list requires a special case here if (functionName == "concat" && args.Count > 4) { ConcatFunction f = new ConcatFunction(args.Count); if (f.Bind(functionName, args)) { return(f); } } else { for (int i = 0; i < XPathFunctionLibrary.functionTable.Length; ++i) { // XPath functions are typeless, so don't check types if (XPathFunctionLibrary.functionTable[i].Bind(functionName, args)) { return(XPathFunctionLibrary.functionTable[i]); } } } return(null); }
// 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); }
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); }
void CompileFunction(XPathFunctionExpr expr) { // In some scenarios, some functions are handled in a special way if (this.CompileFunctionSpecial(expr)) { return; } // Generic function compilation QueryFunction function = expr.Function; // 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) { this.CompileFunctionParam(function, expr.SubExpr, i); } } this.codeBlock.Append(new FunctionCallOpcode(function)); if (1 == this.compiler.nestingLevel && function.TestFlag(QueryFunctionFlag.UsesContextNode)) { this.compiler.SetPushInitialContext(true); } }
private bool ParseRelativePath(XPathExprList path) { XPathStepExpr expr = this.ParseStep(); if (expr == null) { return(false); } path.Add(expr); while (true) { if (this.NextToken(XPathTokenID.Slash) != null) { expr = this.ParseStep(); } else { if (this.NextToken(XPathTokenID.DblSlash) == null) { return(true); } expr = new XPathStepExpr(new NodeSelectCriteria(QueryAxisType.DescendantOrSelf, NodeQName.Empty, QueryNodeType.All)); path.Add(expr); expr = this.ParseStep(); } if (expr == null) { this.ThrowError(QueryCompileError.InvalidLocationPath); } path.Add(expr); } }
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)); } }
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 XPathExprList ParseAbsolutePath() { XPathExprList path = null; XPathToken token = this.NextToken(); if (token != null) { XPathTokenID tokenID = token.TokenID; if (tokenID == XPathTokenID.Slash) { path = new XPathExprList(); path.Add(new XPathStepExpr(new NodeSelectCriteria(QueryAxisType.Child, NodeQName.Empty, QueryNodeType.Root))); } else if (tokenID == XPathTokenID.DblSlash) { 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))); } else { this.PushToken(token); } } if (path != null) { this.ParseRelativePath(path); } return(path); }
private void CompilePredicates(XPathExprList exprList) { for (int i = 0; i < exprList.Count; i++) { this.CompilePredicate(exprList[i]); } }
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)); } }
void CompilePredicates(XPathExprList exprList) { // Compile each predicate expression first for (int i = 0; i < exprList.Count; ++i) { this.CompilePredicate(exprList[i]); } }
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); }
private XPathExprList ParseRelativePath() { XPathExprList path = new XPathExprList(); if (this.ParseRelativePath(path)) { return(path); } return(null); }
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); }
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)); }
internal XPathExpr ParseLocationPath() { XPathExprList subExpr = this.ParseAbsolutePath(); if (subExpr == null) { subExpr = this.ParseRelativePath(); } if (subExpr != null) { return(new XPathExpr(XPathExprType.LocationPath, ValueDataType.Sequence, subExpr)); } return(null); }
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]); } }
internal bool Bind(string name, XPathExprList args) { Fx.Assert(null != name && null != args, ""); if ( 0 != string.CompareOrdinal(this.name, name) || this.paramTypes.Length != args.Count ) { return(false); } return(this.paramTypes.Length == args.Count); }
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 XPathExprList ParsePredicates() { XPathExprList list = null; XPathExpr expr = this.ParsePredicateExpression(); if (expr != null) { list = new XPathExprList(); list.Add(expr); while ((expr = this.ParsePredicateExpression()) != null) { list.Add(expr); } } return(list); }
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); }
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); }
private XPathExpr ParsePathExpression() { XPathExpr expr = this.ParseLocationPath(); if (expr != null) { return(expr); } XPathExpr expr2 = this.ParseFilterExpression(); if (expr2 == null) { return(expr); } if (this.NextToken(XPathTokenID.Slash) != null) { this.EnsureReturnsNodeSet(expr2); XPathExprList subExpr = this.ParseRelativePath(); if (subExpr == null) { this.ThrowError(QueryCompileError.InvalidLocationPath); } XPathExpr expr3 = new XPathExpr(XPathExprType.RelativePath, ValueDataType.Sequence, subExpr); expr = new XPathExpr(XPathExprType.Path, ValueDataType.Sequence); expr.Add(expr2); expr.Add(expr3); return(expr); } if (this.NextToken(XPathTokenID.DblSlash) != null) { this.EnsureReturnsNodeSet(expr2); XPathExprList list2 = this.ParseRelativePath(); if (list2 == null) { this.ThrowError(QueryCompileError.InvalidLocationPath); } XPathExpr expr4 = new XPathExpr(XPathExprType.RelativePath, ValueDataType.Sequence, list2); expr = new XPathExpr(XPathExprType.Path, ValueDataType.Sequence); expr.Add(expr2); expr.Add(new XPathStepExpr(new NodeSelectCriteria(QueryAxisType.DescendantOrSelf, NodeQName.Empty, QueryNodeType.All))); expr.Add(expr4); return(expr); } return(expr2); }
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); }
void CompileSteps(XPathExprList steps, bool start) { for (int i = 0; i < steps.Count; ++i) { Fx.Assert(XPathExprType.PathStep == steps[i].Type, ""); XPathStepExpr step = (XPathStepExpr)steps[i]; if (!step.SelectDesc.Axis.IsSupported()) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.UnsupportedAxis)); } Opcode stepOpcode = null; if (start && 0 == i) { // First steps // Is this an absolute path? We have an absolute path if the first step selects the root if (QueryNodeType.Root == step.SelectDesc.Type) { stepOpcode = new SelectRootOpcode(); } else { stepOpcode = new InitialSelectOpcode(step.SelectDesc); } } else { Fx.Assert(QueryNodeType.Root != step.SelectDesc.Type, ""); stepOpcode = new SelectOpcode(step.SelectDesc); } this.codeBlock.Append(stepOpcode); // 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--; } } }
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--; } }
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); } }
private XPathStepExpr ParseStep() { QueryAxisType axisType = this.ParseAxisSpecifier(); NodeSelectCriteria desc = null; bool flag = false; if (axisType != QueryAxisType.None) { desc = this.ParseNodeTest(axisType); } else if (this.NextToken(XPathTokenID.Period) != null) { desc = new NodeSelectCriteria(QueryAxisType.Self, NodeQName.Empty, QueryNodeType.All); flag = true; } else if (this.NextToken(XPathTokenID.DblPeriod) != null) { desc = new NodeSelectCriteria(QueryAxisType.Parent, NodeQName.Empty, QueryNodeType.Ancestor); flag = true; } else { desc = this.ParseNodeTest(QueryAxisType.Child); if (desc == null) { return(null); } } if (desc == null) { this.ThrowError(QueryCompileError.InvalidLocationStep); } XPathExprList predicates = null; if (!flag) { predicates = this.ParsePredicates(); } return(new XPathStepExpr(desc, predicates)); }
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); }
public QueryFunction Bind(string functionName, string functionNamespace, XPathExprList args) { if ((functionName == "concat") && (args.Count > 4)) { ConcatFunction function = new ConcatFunction(args.Count); if (function.Bind(functionName, args)) { return function; } } else { for (int i = 0; i < functionTable.Length; i++) { if (functionTable[i].Bind(functionName, args)) { return functionTable[i]; } } } return null; }
void CompileFunctionParam(QueryFunction function, XPathExprList paramList, int index) { XPathExpr param = paramList[index]; this.CompileExpression(param); if (ValueDataType.None != function.ParamTypes[index]) { if (param.ReturnType != function.ParamTypes[index]) { if (function.ParamTypes[index] == ValueDataType.Sequence) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.InvalidTypeConversion)); } this.CompileTypecast(function.ParamTypes[index]); } } }
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(XPathExprType type, ValueDataType returnType, XPathExprList subExpr) : this(type, returnType) { this.subExpr = subExpr; }
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; }
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; }
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; }
internal XPathFunctionExpr(QueryFunction function, XPathExprList subExpr) : base(XPathExprType.Function, function.ReturnType, subExpr) { Fx.Assert(null != function, ""); this.function = function; }
internal XPathXsltFunctionExpr(XsltContext context, IXsltContextFunction function, XPathExprList subExpr) : base(XPathExprType.XsltFunction, ConvertTypeFromXslt(function.ReturnType), subExpr) { this.function = function; this.context = context; }
private XPathExprList ParsePredicates() { XPathExprList list = null; XPathExpr expr = this.ParsePredicateExpression(); if (expr != null) { list = new XPathExprList(); list.Add(expr); while ((expr = this.ParsePredicateExpression()) != null) { list.Add(expr); } } return list; }
private void CompileSteps(XPathExprList steps) { this.CompileSteps(steps, true); }
private void CompileSteps(XPathExprList steps, bool start) { for (int i = 0; i < steps.Count; i++) { XPathStepExpr expr = (XPathStepExpr) steps[i]; if (!expr.SelectDesc.Axis.IsSupported()) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.UnsupportedAxis)); } Opcode opcode = null; if (start && (i == 0)) { if (QueryNodeType.Root == expr.SelectDesc.Type) { opcode = new SelectRootOpcode(); } else { opcode = new InitialSelectOpcode(expr.SelectDesc); } } else { opcode = new SelectOpcode(expr.SelectDesc); } this.codeBlock.Append(opcode); if (expr.SubExprCount > 0) { this.compiler.nestingLevel++; if (this.compiler.nestingLevel > 3) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.PredicateNestingTooDeep)); } this.CompilePredicates(expr.SubExpr); this.compiler.nestingLevel--; } } }
void CompileSteps(XPathExprList steps) { CompileSteps(steps, true); }
internal XPathStepExpr(NodeSelectCriteria desc, XPathExprList predicates) : base(XPathExprType.PathStep, ValueDataType.Sequence, predicates) { this.selectDesc = desc; }
internal XPathFunctionExpr(QueryFunction function, XPathExprList subExpr) : base(XPathExprType.Function, function.ReturnType, subExpr) { this.function = function; }
internal bool Bind(string name, XPathExprList args) { Fx.Assert(null != name && null != args, ""); if ( 0 != string.CompareOrdinal(this.name, name) || this.paramTypes.Length != args.Count ) { return false; } return (this.paramTypes.Length == args.Count); }
private bool ParseRelativePath(XPathExprList path) { XPathStepExpr expr = this.ParseStep(); if (expr == null) { return false; } path.Add(expr); while (true) { if (this.NextToken(XPathTokenID.Slash) != null) { expr = this.ParseStep(); } else { if (this.NextToken(XPathTokenID.DblSlash) == null) { return true; } expr = new XPathStepExpr(new NodeSelectCriteria(QueryAxisType.DescendantOrSelf, NodeQName.Empty, QueryNodeType.All)); path.Add(expr); expr = this.ParseStep(); } if (expr == null) { this.ThrowError(QueryCompileError.InvalidLocationPath); } path.Add(expr); } }
public QueryFunction Bind(string functionName, string functionNamespace, XPathExprList args) { Fx.Assert(null != functionName && null != args, ""); // Variable length argument list requires a special case here if (functionName == "concat" && args.Count > 4) { ConcatFunction f = new ConcatFunction(args.Count); if (f.Bind(functionName, args)) { return f; } } else { for (int i = 0; i < XPathFunctionLibrary.functionTable.Length; ++i) { // XPath functions are typeless, so don't check types if (XPathFunctionLibrary.functionTable[i].Bind(functionName, args)) { return XPathFunctionLibrary.functionTable[i]; } } } return null; }
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; }
internal bool Bind(string name, XPathExprList args) { return (((string.CompareOrdinal(this.name, name) == 0) && (this.paramTypes.Length == args.Count)) && (this.paramTypes.Length == args.Count)); }
XPathExprList ParseRelativePath() { XPathExprList path = new XPathExprList(); if (this.ParseRelativePath(path)) { return path; } return null; }
private XPathExprList ParseAbsolutePath() { XPathExprList path = null; XPathToken token = this.NextToken(); if (token != null) { XPathTokenID tokenID = token.TokenID; if (tokenID == XPathTokenID.Slash) { path = new XPathExprList(); path.Add(new XPathStepExpr(new NodeSelectCriteria(QueryAxisType.Child, NodeQName.Empty, QueryNodeType.Root))); } else if (tokenID == XPathTokenID.DblSlash) { 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))); } else { this.PushToken(token); } } if (path != null) { this.ParseRelativePath(path); } return path; }