示例#1
0
        // Six possible causes of exceptions in the builder:
        // 1. Undefined prefix in a node test.
        // 2. Undefined prefix in a variable reference, or unknown variable.
        // 3. Undefined prefix in a function call, or unknown function, or wrong number/types of arguments.
        // 4. Argument of Union operator is not a node-set.
        // 5. First argument of Predicate is not a node-set.
        // 6. Argument of Axis is not a node-set.

        public Node Parse(string xpathExpr, IXPathBuilder <Node> builder)
        {
            Debug.Assert(this.scanner == null && this.builder == null);
            Debug.Assert(builder != null);

            Node result = default(Node);

            this.scanner = new XPathScanner(xpathExpr);
            this.builder = builder;
            this.posInfo.Clear();

            try {
                builder.StartBuild();
                result = ParseExpr();
                scanner.CheckToken(LexKind.Eof);
            }
            catch (XPathParserException e) {
                if (e.queryString == null)
                {
                    e.queryString = scanner.Source;
                    PopPosInfo(out e.startChar, out e.endChar);
                }
                throw;
            }
            finally {
                result = builder.EndBuild(result);
#if DEBUG
                this.builder = null;
                this.scanner = null;
#endif
            }
            Debug.Assert(posInfo.Count == 0, "PushPosInfo() and PopPosInfo() calls have been unbalanced");
            return(result);
        }
示例#2
0
        /*
         *   PrimaryExpr ::= Literal | Number | VariableReference | '(' Expr ')' | FunctionCall
         */
        private Node ParsePrimaryExpr()
        {
            Debug.Assert(IsPrimaryExpr());
            Node opnd;

            switch (scanner.Kind)
            {
            case LexKind.String:
                opnd = builder.String(scanner.StringValue);
                scanner.NextLex();
                break;

            case LexKind.Number:
                opnd = builder.Number(scanner.RawValue);
                scanner.NextLex();
                break;

            case LexKind.Dollar:
                int startChar = scanner.LexStart;
                scanner.NextLex();
                scanner.CheckToken(LexKind.Name);
                PushPosInfo(startChar, scanner.LexStart + scanner.LexSize);
                opnd = builder.Variable(scanner.Prefix, scanner.Name);
                PopPosInfo();
                scanner.NextLex();
                break;

            case LexKind.LParens:
                scanner.NextLex();
                opnd = ParseExpr();
                scanner.PassToken(LexKind.RParens);
                break;

            default:
                Debug.Assert(
                    scanner.Kind == LexKind.Name && scanner.CanBeFunction && !IsNodeType(scanner),
                    "IsPrimaryExpr() returned true, but the lexeme is not recognized"
                    );
                opnd = ParseFunctionCall();
                break;
            }
            return(opnd);
        }
示例#3
0
        private static void InternalParseNodeTest(XPathScanner scanner, XPathAxis axis, out XPathNodeType nodeType, out string nodePrefix, out string nodeName)
        {
            switch (scanner.Kind)
            {
            case LexKind.Name:
                if (scanner.CanBeFunction && IsNodeType(scanner))
                {
                    nodePrefix = null;
                    nodeName   = null;
                    switch (scanner.Name)
                    {
                    case "comment": nodeType = XPathNodeType.Comment; break;

                    case "text": nodeType = XPathNodeType.Text;    break;

                    case "node": nodeType = XPathNodeType.All;     break;

                    default:
                        Debug.Assert(scanner.Name == "processing-instruction");
                        nodeType = XPathNodeType.ProcessingInstruction;
                        break;
                    }

                    scanner.NextLex();
                    scanner.PassToken(LexKind.LParens);

                    if (nodeType == XPathNodeType.ProcessingInstruction)
                    {
                        if (scanner.Kind != LexKind.RParens)    // 'processing-instruction' '(' Literal ')'
                        {
                            scanner.CheckToken(LexKind.String);
                            // It is not needed to set nodePrefix here, but for our current implementation
                            // comparing whole QNames is faster than comparing just local names
                            nodePrefix = string.Empty;
                            nodeName   = scanner.StringValue;
                            scanner.NextLex();
                        }
                    }

                    scanner.PassToken(LexKind.RParens);
                }
                else
                {
                    nodePrefix = scanner.Prefix;
                    nodeName   = scanner.Name;
                    nodeType   = PrincipalNodeType(axis);
                    scanner.NextLex();
                    if (nodeName == "*")
                    {
                        nodeName = null;
                    }
                }
                break;

            case LexKind.Star:
                nodePrefix = null;
                nodeName   = null;
                nodeType   = PrincipalNodeType(axis);
                scanner.NextLex();
                break;

            default:
                throw scanner.NodeTestExpectedException(scanner.RawValue);
            }
        }