XPathPatternParser.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / XmlUtils / System / Xml / Xsl / Xslt / XPathPatternParser.cs / 1 / XPathPatternParser.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
using System.Collections.Generic; 
using System.Diagnostics;
using System.Xml; 
using System.Xml.Xsl.Qil;
using System.Xml.Xsl.XPath;

namespace System.Xml.Xsl.Xslt { 
    using XPathParser   = XPathParser;
    using XPathNodeType = System.Xml.XPath.XPathNodeType; 
    using Res           = System.Xml.Utils.Res; 

    internal class XPathPatternParser { 
        public interface IPatternBuilder : IXPathBuilder {
            IXPathBuilder GetPredicateBuilder(QilNode context);
        }
 
        XPathScanner    scanner;
        IPatternBuilder ptrnBuilder; 
        XPathParser     predicateParser = new XPathParser(); 

        public QilNode Parse(XPathScanner scanner, IPatternBuilder ptrnBuilder) { 
            Debug.Assert(this.scanner == null && this.ptrnBuilder == null);
            Debug.Assert(scanner != null && ptrnBuilder != null);
            QilNode result = null;
            ptrnBuilder.StartBuild(); 
            try {
                this.scanner     = scanner; 
                this.ptrnBuilder = ptrnBuilder; 
                result = this.ParsePattern();
                this.scanner.CheckToken(LexKind.Eof); 
            } finally {
                result = ptrnBuilder.EndBuild(result);
#if DEBUG
                this.ptrnBuilder = null; 
                this.scanner = null;
#endif 
            } 
            return result;
        } 

        /*
        *   Pattern ::= LocationPathPattern ('|' LocationPathPattern)*
        */ 
        private QilNode ParsePattern() {
            QilNode opnd = ParseLocationPathPattern(); 
 
            while (scanner.Kind == LexKind.Union) {
                scanner.NextLex(); 
                opnd = ptrnBuilder.Operator(XPathOperator.Union, opnd, ParseLocationPathPattern());
            }
            return opnd;
        } 

        /* 
        *   LocationPathPattern ::= '/' RelativePathPattern? | '//'? RelativePathPattern | IdKeyPattern (('/' | '//') RelativePathPattern)? 
        */
        private QilNode ParseLocationPathPattern() { 
            QilNode opnd;

            switch (scanner.Kind) {
            case LexKind.Slash : 
                scanner.NextLex();
                opnd = ptrnBuilder.Axis(XPathAxis.Root, XPathNodeType.All, null, null); 
 
                if (XPathParser.IsStep(scanner.Kind)) {
                    opnd = ptrnBuilder.JoinStep(opnd, ParseRelativePathPattern()); 
                }
                return opnd;
            case LexKind.SlashSlash :
                scanner.NextLex(); 
                return ptrnBuilder.JoinStep(
                    ptrnBuilder.Axis(XPathAxis.Root, XPathNodeType.All, null, null), 
                    ptrnBuilder.JoinStep( 
                        ptrnBuilder.Axis(XPathAxis.DescendantOrSelf, XPathNodeType.All, null, null),
                        ParseRelativePathPattern() 
                    )
                );
            case LexKind.Name :
                if (scanner.CanBeFunction && scanner.Prefix.Length == 0 && (scanner.Name == "id" || scanner.Name == "key")) { 
                    opnd = ParseIdKeyPattern();
                    switch (scanner.Kind) { 
                    case LexKind.Slash : 
                        scanner.NextLex();
                        opnd = ptrnBuilder.JoinStep(opnd, ParseRelativePathPattern()); 
                        break;
                    case LexKind.SlashSlash :
                        scanner.NextLex();
                        opnd = ptrnBuilder.JoinStep(opnd, 
                            ptrnBuilder.JoinStep(
                                ptrnBuilder.Axis(XPathAxis.DescendantOrSelf, XPathNodeType.All, null, null), 
                                ParseRelativePathPattern() 
                            )
                        ); 
                        break;
                    }
                    return opnd;
                } 
                break;
            } 
            opnd = ParseRelativePathPattern(); 
            return opnd;
        } 

        /*
        *   IdKeyPattern ::= 'id' '(' Literal ')' | 'key' '(' Literal ',' Literal ')'
        */ 
        private QilNode ParseIdKeyPattern() {
            Debug.Assert(scanner.CanBeFunction); 
            Debug.Assert(scanner.Prefix.Length == 0); 
            Debug.Assert(scanner.Name == "id" || scanner.Name == "key");
            List args = new List(2); 

            if (scanner.Name == "id") {
                scanner.NextLex();
                scanner.PassToken(LexKind.LParens); 
                scanner.CheckToken(LexKind.String);
                args.Add(ptrnBuilder.String(scanner.StringValue)); 
                scanner.NextLex(); 
                scanner.PassToken(LexKind.RParens);
                return ptrnBuilder.Function("", "id", args); 
            } else {
                scanner.NextLex();
                scanner.PassToken(LexKind.LParens);
                scanner.CheckToken(LexKind.String); 
                args.Add(ptrnBuilder.String(scanner.StringValue));
                scanner.NextLex(); 
                scanner.PassToken(LexKind.Comma); 
                scanner.CheckToken(LexKind.String);
                args.Add(ptrnBuilder.String(scanner.StringValue)); 
                scanner.NextLex();
                scanner.PassToken(LexKind.RParens);
                return ptrnBuilder.Function("", "key", args);
            } 
        }
 
        /* 
        *   RelativePathPattern ::= StepPattern (('/' | '//') StepPattern)*
        */ 
        private QilNode ParseRelativePathPattern() {
            QilNode opnd = ParseStepPattern();
            if (scanner.Kind == LexKind.Slash) {
                scanner.NextLex(); 
                opnd = ptrnBuilder.JoinStep(opnd, ParseRelativePathPattern());
            } else if (scanner.Kind == LexKind.SlashSlash) { 
                scanner.NextLex(); 
                opnd = ptrnBuilder.JoinStep(opnd,
                    ptrnBuilder.JoinStep( 
                        ptrnBuilder.Axis(XPathAxis.DescendantOrSelf, XPathNodeType.All, null, null),
                        ParseRelativePathPattern()
                    )
                ); 
            }
            return opnd; 
        } 

        /* 
        *   StepPattern ::= ChildOrAttributeAxisSpecifier NodeTest Predicate*
        *   ChildOrAttributeAxisSpecifier ::= @ ? | ('child' | 'attribute') '::'
        */
        private QilNode ParseStepPattern() { 
            QilNode     opnd;
            XPathAxis   axis; 
 
            switch (scanner.Kind) {
            case LexKind.Dot: 
            case LexKind.DotDot:
                throw scanner.CreateException(Res.XPath_InvalidAxisInPattern);
            case LexKind.At:                               //>> '@'
                axis = XPathAxis.Attribute; 
                scanner.NextLex();
                break; 
            case LexKind.Axis:                             //>> AxisName '::' 
                axis = XPathParser.GetAxis(scanner.Name, scanner);
                if (axis != XPathAxis.Child && axis != XPathAxis.Attribute) { 
                    throw scanner.CreateException(Res.XPath_InvalidAxisInPattern);
                }
                scanner.NextLex();
                break; 
            case LexKind.Name:
            case LexKind.Star: 
                // NodeTest must start with Name or '*' 
                axis = XPathAxis.Child;
                break; 
            default:
                throw scanner.CreateException(Res.XPath_UnexpectedToken, scanner.RawValue);
            }
 
            XPathNodeType  nodeType;
            string         nodePrefix, nodeName; 
            XPathParser.InternalParseNodeTest(scanner, axis, out nodeType, out nodePrefix, out nodeName); 
            opnd = ptrnBuilder.Axis(axis, nodeType, nodePrefix, nodeName);
 
            while (scanner.Kind == LexKind.LBracket) {
                opnd = ptrnBuilder.Predicate(opnd, ParsePredicate(opnd), /*reverseStep:*/false);
            }
            return opnd; 
        }
 
        /* 
        *   Predicate ::= '[' Expr ']'
        */ 
        private QilNode ParsePredicate(QilNode context) {
            Debug.Assert(scanner.Kind == LexKind.LBracket);
            scanner.NextLex();
            QilNode result = predicateParser.Parse(scanner, ptrnBuilder.GetPredicateBuilder(context), LexKind.RBracket); 
            Debug.Assert(scanner.Kind == LexKind.RBracket);
            scanner.NextLex(); 
            return result; 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
using System.Collections.Generic; 
using System.Diagnostics;
using System.Xml; 
using System.Xml.Xsl.Qil;
using System.Xml.Xsl.XPath;

namespace System.Xml.Xsl.Xslt { 
    using XPathParser   = XPathParser;
    using XPathNodeType = System.Xml.XPath.XPathNodeType; 
    using Res           = System.Xml.Utils.Res; 

    internal class XPathPatternParser { 
        public interface IPatternBuilder : IXPathBuilder {
            IXPathBuilder GetPredicateBuilder(QilNode context);
        }
 
        XPathScanner    scanner;
        IPatternBuilder ptrnBuilder; 
        XPathParser     predicateParser = new XPathParser(); 

        public QilNode Parse(XPathScanner scanner, IPatternBuilder ptrnBuilder) { 
            Debug.Assert(this.scanner == null && this.ptrnBuilder == null);
            Debug.Assert(scanner != null && ptrnBuilder != null);
            QilNode result = null;
            ptrnBuilder.StartBuild(); 
            try {
                this.scanner     = scanner; 
                this.ptrnBuilder = ptrnBuilder; 
                result = this.ParsePattern();
                this.scanner.CheckToken(LexKind.Eof); 
            } finally {
                result = ptrnBuilder.EndBuild(result);
#if DEBUG
                this.ptrnBuilder = null; 
                this.scanner = null;
#endif 
            } 
            return result;
        } 

        /*
        *   Pattern ::= LocationPathPattern ('|' LocationPathPattern)*
        */ 
        private QilNode ParsePattern() {
            QilNode opnd = ParseLocationPathPattern(); 
 
            while (scanner.Kind == LexKind.Union) {
                scanner.NextLex(); 
                opnd = ptrnBuilder.Operator(XPathOperator.Union, opnd, ParseLocationPathPattern());
            }
            return opnd;
        } 

        /* 
        *   LocationPathPattern ::= '/' RelativePathPattern? | '//'? RelativePathPattern | IdKeyPattern (('/' | '//') RelativePathPattern)? 
        */
        private QilNode ParseLocationPathPattern() { 
            QilNode opnd;

            switch (scanner.Kind) {
            case LexKind.Slash : 
                scanner.NextLex();
                opnd = ptrnBuilder.Axis(XPathAxis.Root, XPathNodeType.All, null, null); 
 
                if (XPathParser.IsStep(scanner.Kind)) {
                    opnd = ptrnBuilder.JoinStep(opnd, ParseRelativePathPattern()); 
                }
                return opnd;
            case LexKind.SlashSlash :
                scanner.NextLex(); 
                return ptrnBuilder.JoinStep(
                    ptrnBuilder.Axis(XPathAxis.Root, XPathNodeType.All, null, null), 
                    ptrnBuilder.JoinStep( 
                        ptrnBuilder.Axis(XPathAxis.DescendantOrSelf, XPathNodeType.All, null, null),
                        ParseRelativePathPattern() 
                    )
                );
            case LexKind.Name :
                if (scanner.CanBeFunction && scanner.Prefix.Length == 0 && (scanner.Name == "id" || scanner.Name == "key")) { 
                    opnd = ParseIdKeyPattern();
                    switch (scanner.Kind) { 
                    case LexKind.Slash : 
                        scanner.NextLex();
                        opnd = ptrnBuilder.JoinStep(opnd, ParseRelativePathPattern()); 
                        break;
                    case LexKind.SlashSlash :
                        scanner.NextLex();
                        opnd = ptrnBuilder.JoinStep(opnd, 
                            ptrnBuilder.JoinStep(
                                ptrnBuilder.Axis(XPathAxis.DescendantOrSelf, XPathNodeType.All, null, null), 
                                ParseRelativePathPattern() 
                            )
                        ); 
                        break;
                    }
                    return opnd;
                } 
                break;
            } 
            opnd = ParseRelativePathPattern(); 
            return opnd;
        } 

        /*
        *   IdKeyPattern ::= 'id' '(' Literal ')' | 'key' '(' Literal ',' Literal ')'
        */ 
        private QilNode ParseIdKeyPattern() {
            Debug.Assert(scanner.CanBeFunction); 
            Debug.Assert(scanner.Prefix.Length == 0); 
            Debug.Assert(scanner.Name == "id" || scanner.Name == "key");
            List args = new List(2); 

            if (scanner.Name == "id") {
                scanner.NextLex();
                scanner.PassToken(LexKind.LParens); 
                scanner.CheckToken(LexKind.String);
                args.Add(ptrnBuilder.String(scanner.StringValue)); 
                scanner.NextLex(); 
                scanner.PassToken(LexKind.RParens);
                return ptrnBuilder.Function("", "id", args); 
            } else {
                scanner.NextLex();
                scanner.PassToken(LexKind.LParens);
                scanner.CheckToken(LexKind.String); 
                args.Add(ptrnBuilder.String(scanner.StringValue));
                scanner.NextLex(); 
                scanner.PassToken(LexKind.Comma); 
                scanner.CheckToken(LexKind.String);
                args.Add(ptrnBuilder.String(scanner.StringValue)); 
                scanner.NextLex();
                scanner.PassToken(LexKind.RParens);
                return ptrnBuilder.Function("", "key", args);
            } 
        }
 
        /* 
        *   RelativePathPattern ::= StepPattern (('/' | '//') StepPattern)*
        */ 
        private QilNode ParseRelativePathPattern() {
            QilNode opnd = ParseStepPattern();
            if (scanner.Kind == LexKind.Slash) {
                scanner.NextLex(); 
                opnd = ptrnBuilder.JoinStep(opnd, ParseRelativePathPattern());
            } else if (scanner.Kind == LexKind.SlashSlash) { 
                scanner.NextLex(); 
                opnd = ptrnBuilder.JoinStep(opnd,
                    ptrnBuilder.JoinStep( 
                        ptrnBuilder.Axis(XPathAxis.DescendantOrSelf, XPathNodeType.All, null, null),
                        ParseRelativePathPattern()
                    )
                ); 
            }
            return opnd; 
        } 

        /* 
        *   StepPattern ::= ChildOrAttributeAxisSpecifier NodeTest Predicate*
        *   ChildOrAttributeAxisSpecifier ::= @ ? | ('child' | 'attribute') '::'
        */
        private QilNode ParseStepPattern() { 
            QilNode     opnd;
            XPathAxis   axis; 
 
            switch (scanner.Kind) {
            case LexKind.Dot: 
            case LexKind.DotDot:
                throw scanner.CreateException(Res.XPath_InvalidAxisInPattern);
            case LexKind.At:                               //>> '@'
                axis = XPathAxis.Attribute; 
                scanner.NextLex();
                break; 
            case LexKind.Axis:                             //>> AxisName '::' 
                axis = XPathParser.GetAxis(scanner.Name, scanner);
                if (axis != XPathAxis.Child && axis != XPathAxis.Attribute) { 
                    throw scanner.CreateException(Res.XPath_InvalidAxisInPattern);
                }
                scanner.NextLex();
                break; 
            case LexKind.Name:
            case LexKind.Star: 
                // NodeTest must start with Name or '*' 
                axis = XPathAxis.Child;
                break; 
            default:
                throw scanner.CreateException(Res.XPath_UnexpectedToken, scanner.RawValue);
            }
 
            XPathNodeType  nodeType;
            string         nodePrefix, nodeName; 
            XPathParser.InternalParseNodeTest(scanner, axis, out nodeType, out nodePrefix, out nodeName); 
            opnd = ptrnBuilder.Axis(axis, nodeType, nodePrefix, nodeName);
 
            while (scanner.Kind == LexKind.LBracket) {
                opnd = ptrnBuilder.Predicate(opnd, ParsePredicate(opnd), /*reverseStep:*/false);
            }
            return opnd; 
        }
 
        /* 
        *   Predicate ::= '[' Expr ']'
        */ 
        private QilNode ParsePredicate(QilNode context) {
            Debug.Assert(scanner.Kind == LexKind.LBracket);
            scanner.NextLex();
            QilNode result = predicateParser.Parse(scanner, ptrnBuilder.GetPredicateBuilder(context), LexKind.RBracket); 
            Debug.Assert(scanner.Kind == LexKind.RBracket);
            scanner.NextLex(); 
            return result; 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

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