private static void ComposeFilter(Filter node, StringBuilder expr) { ComposeExpression(node.Input, expr); expr.Append(s_LBracket); ComposeExpression(node.Condition, expr); expr.Append(s_RBracket); }
//>> StepPattern ::= ChildOrAttributeAxisSpecifier NodeTest Predicate* //>> ChildOrAttributeAxisSpecifier ::= @ ? | ('child' | 'attribute') '::' private AstNode ParseStepPattern(AstNode qyInput) { AstNode opnd; Axis.AxisType axisType = Axis.AxisType.Child; switch (this.scanner.Kind) { case XPathScanner.LexKind.At: //>> '@' axisType = Axis.AxisType.Attribute; NextLex(); break; case XPathScanner.LexKind.Axe: //>> AxisName '::' axisType = GetAxis(this.scanner); if (axisType != Axis.AxisType.Child && axisType != Axis.AxisType.Attribute) { throw new XPathException(Res.Xp_InvalidToken, scanner.SourceText); } NextLex(); break; } XPathNodeType nodeType = ( axisType == Axis.AxisType.Attribute ? XPathNodeType.Attribute : /* default: */ XPathNodeType.Element ); opnd = ParseNodeTest(qyInput, axisType, nodeType); while (XPathScanner.LexKind.LBracket == this.scanner.Kind) { opnd = new Filter(opnd, ParsePredicate(opnd)); } return opnd; }
//>> FilterExpr ::= PrimaryExpr | FilterExpr Predicate private AstNode ParseFilterExpr(AstNode qyInput) { AstNode opnd = ParsePrimaryExpr(qyInput); while (this.scanner.Kind == XPathScanner.LexKind.LBracket) { // opnd must be a query opnd = new Filter(opnd, ParsePredicate(opnd)); } return opnd; }
//>> Step ::= '.' | '..' | ( AxisName '::' | '@' )? NodeTest Predicate* private AstNode ParseStep(AstNode qyInput) { AstNode opnd; if (XPathScanner.LexKind.Dot == this.scanner.Kind) { //>> '.' NextLex(); opnd = new Axis(Axis.AxisType.Self, qyInput); } else if (XPathScanner.LexKind.DotDot == this.scanner.Kind) { //>> '..' NextLex(); opnd = new Axis(Axis.AxisType.Parent, qyInput); } else { //>> ( AxisName '::' | '@' )? NodeTest Predicate* Axis.AxisType axisType = Axis.AxisType.Child; switch (this.scanner.Kind) { case XPathScanner.LexKind.At: //>> '@' axisType = Axis.AxisType.Attribute; NextLex(); break; case XPathScanner.LexKind.Axe: //>> AxisName '::' axisType = GetAxis(this.scanner); NextLex(); break; } XPathNodeType nodeType = ( axisType == Axis.AxisType.Attribute ? XPathNodeType.Attribute : // axisType == Axis.AxisType.Namespace ? XPathNodeType.Namespace : // No Idea why it's this way but othervise Axes doesn't work /* default: */ XPathNodeType.Element ); opnd = ParseNodeTest(qyInput, axisType, nodeType); while (XPathScanner.LexKind.LBracket == this.scanner.Kind) { opnd = new Filter(opnd, ParsePredicate(opnd)); } } return opnd; }
/* private bool SplitQuery(BaseAxisQuery origQuery, BaseAxisQuery parent, BaseAxisQuery input) { parent = origQuery as BaseAxisQuery; if (parent == null || parent is GroupQuery || parent is PositionQuery || parent is OrQuery) { return false; } input = parent = (BaseAxisQuery)parent.Clone(); parent = (BaseAxisQuery) parent.m_qyInput; while (parent != null && !parent.IsAxis) { parent = (BaseAxisQuery)parent.m_qyInput; } if (parent == null) { return false; } BaseAxisQuery temp = (BaseAxisQuery)parent.m_qyInput; if (temp == null) { return false; } parent.m_qyInput = null; parent = temp; return true; } */ private IQuery ProcessFilter(Filter root, ref bool cache, ref bool position) { bool _cache = false; bool merge = false; bool _position = false; _specialAxis = false; bool filterflag = true; bool first = (filterCount == 0); IQuery opnd = ProcessNode(root.Condition, null, Regular_D, Axis.AxisType.None, ref _cache, ref _position); filterCount++; if (root.Condition.ReturnType == XPathResultType.Error ) { _position = true; } if (root.Condition.ReturnType == XPathResultType.Number || _cache || _position ) { hasPosition = true; filterflag = false; _smart = 0; } IQuery qyInput = ProcessNode(root.Input, null, Regular_D, Axis.AxisType.None, ref cache, ref position ); if (hasPosition && qyInput is CacheQuery) { qyInput = ((CacheQuery)qyInput).m_qyInput; } if (firstInput == null) { firstInput = qyInput as BaseAxisQuery; } _smart = 2; merge = qyInput.Merge; if (_cache || _position) { hasPosition = true; if (hasReverseAxis) { if (merge) { qyInput = new ReversePositionQuery(qyInput); } else if (_cache) { qyInput = new ForwardPositionQuery(qyInput); } } else { if (_cache) { qyInput = new ForwardPositionQuery(qyInput); } } } else if (root.Condition.ReturnType == XPathResultType.Number ) { hasPosition = true; if (hasReverseAxis && merge) { qyInput = new ReversePositionQuery(qyInput); } } if (first && firstInput != null) { if (merge && hasPosition) { qyInput = new FilterQuery(qyInput, opnd); IQuery parent = firstInput.m_qyInput; if (parent == null || !firstInput.Merge) { firstInput = null; return qyInput; } IQuery input = qyInput; qyInput = qyInput.Clone(); firstInput.m_qyInput = null; firstInput = null; return new MergeFilterQuery(parent, input); } firstInput = null; } return new FilterQuery(qyInput, opnd, filterflag); }