예제 #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(XPathScanner scanner, IXPathBuilder <Node> builder, LexKind endLex)
        {
            Debug.Assert(this.scanner == null && this.builder == null);
            Debug.Assert(scanner != null && builder != null);

            Node result = default(Node);

            this.scanner = scanner;
            this.builder = builder;
            this.posInfo.Clear();

            try {
                builder.StartBuild();
                result = ParseExpr();
                scanner.CheckToken(endLex);
            }
            catch (XPathCompileException 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
        internal static XPathAxis GetAxis(string axisName, XPathScanner scanner)
        {
            switch (axisName)
            {
            case "ancestor": return(XPathAxis.Ancestor);

            case "ancestor-or-self": return(XPathAxis.AncestorOrSelf);

            case "attribute": return(XPathAxis.Attribute);

            case "child": return(XPathAxis.Child);

            case "descendant": return(XPathAxis.Descendant);

            case "descendant-or-self": return(XPathAxis.DescendantOrSelf);

            case "following": return(XPathAxis.Following);

            case "following-sibling": return(XPathAxis.FollowingSibling);

            case "namespace": return(XPathAxis.Namespace);

            case "parent": return(XPathAxis.Parent);

            case "preceding": return(XPathAxis.Preceding);

            case "preceding-sibling": return(XPathAxis.PrecedingSibling);

            case "self": return(XPathAxis.Self);

            default:
                throw scanner.CreateException(Res.XPath_UnknownAxis, axisName);
            }
        }
예제 #3
0
 private static bool IsNodeType(XPathScanner scanner)
 {
     return(scanner.Prefix.Length == 0 && (
                scanner.Name == "node" ||
                scanner.Name == "text" ||
                scanner.Name == "processing-instruction" ||
                scanner.Name == "comment"
                ));
 }
예제 #4
0
        internal 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.CreateException(Res.XPath_NodeTestExpected, scanner.RawValue);
            }
        }
예제 #5
0
        private QilNode CompileKeyUse(Key key)
        {
            string expr = key.Use;
            XPathScanner scanner;
            QilNode result;

            SetEnvironmentFlags(/*allowVariables:*/false, /*allowCurrent:*/true, /*allowKey:*/false);
            if (expr == null)
            {
                result = _f.Error(_f.String(XslLoadException.CreateMessage(key.SourceLine, SR.Xslt_MissingAttribute, "use")));
            }
            else
            {
                try
                {
                    scanner = new XPathScanner(expr);
                    result = _xpathParser.Parse(scanner, _xpathBuilder, LexKind.Eof);
                }
                catch (XslLoadException e)
                {
                    if (_xslVersion != XslVersion.ForwardsCompatible)
                    {
                        ReportErrorInXPath(/*[XT0300]*/e);
                    }
                    result = _f.Error(_f.String(e.Message));
                }
            }
            if (result is QilIterator)
            {
                result = _f.Nop(result);
            }
            return result;
        }
예제 #6
0
        private QilNode CompileKeyMatch(string pttrn)
        {
            XPathScanner scanner;
            QilNode result;

            if (_keyMatchBuilder == null)
            {
                _keyMatchBuilder = new KeyMatchBuilder((IXPathEnvironment)this);
            }
            SetEnvironmentFlags(/*allowVariables:*/false, /*allowCurrent:*/false, /*allowKey:*/false);
            if (pttrn == null)
            {
                result = PhantomKeyMatch();
            }
            else
            {
                try
                {
                    scanner = new XPathScanner(pttrn);
                    result = _ptrnParser.Parse(scanner, _keyMatchBuilder);
                }
                catch (XslLoadException e)
                {
                    if (_xslVersion != XslVersion.ForwardsCompatible)
                    {
                        ReportErrorInXPath(/*[XT0340]*/e);
                    }
                    result = _f.Error(_f.String(e.Message));
                }
            }
            return result;
        }
예제 #7
0
        private QilNode CompileNumberPattern(string pttrn)
        {
            Debug.Assert(pttrn != null);
            XPathScanner scanner;
            QilNode result;

            SetEnvironmentFlags(/*allowVariables:*/true, /*allowCurrent:*/false, /*allowKey:*/true);
            try
            {
                scanner = new XPathScanner(pttrn);
                result = _ptrnParser.Parse(scanner, _ptrnBuilder);
            }
            catch (XslLoadException e)
            {
                if (_xslVersion != XslVersion.ForwardsCompatible)
                {
                    ReportErrorInXPath(/*[XT0340]*/e);
                }
                result = _f.Error(_f.String(e.Message));
            }
            return result;
        }
예제 #8
0
        private QilNode CompileXPathExpressionWithinAvt(string expr, ref int pos)
        {
            Debug.Assert(expr != null);
            XPathScanner scanner;
            QilNode result;
            int startPos = pos;

            SetEnvironmentFlags(/*allowVariables:*/true, /*allowCurrent:*/true, /*allowKey:*/true);
            try
            {
                scanner = new XPathScanner(expr, pos);
                result = _xpathParser.Parse(scanner, _xpathBuilder, LexKind.RBrace);
                pos = scanner.LexStart + 1;
            }
            catch (XslLoadException e)
            {
                if (_xslVersion != XslVersion.ForwardsCompatible)
                {
                    ReportErrorInXPath(/*[XT0350][XT0360]*/e);
                }
                result = _f.Error(_f.String(e.Message));
                pos = expr.Length;
            }
            if (result is QilIterator)
            {
                result = _f.Nop(result);
            }
            return result;
        }
예제 #9
0
        // Calls to CompileXPathExpression() can't be nested in the XSLT. So we can reuse the same instance of xpathBuilder.
        // The only thing we need to do before its use is adjustment of IXPathEnvironment to have correct context tuple.
        private QilNode CompileXPathExpression(string expr)
        {
            XPathScanner scanner;
            QilNode result;

            SetEnvironmentFlags(/*allowVariables:*/true, /*allowCurrent:*/true, /*allowKey:*/true);
            if (expr == null)
            {
                result = PhantomXPathExpression();
            }
            else
            {
                try
                {
                    // Note that the constructor may throw an exception, for example, in case of the expression "'"
                    scanner = new XPathScanner(expr);
                    result = _xpathParser.Parse(scanner, _xpathBuilder, LexKind.Eof);
                }
                catch (XslLoadException e)
                {
                    if (_xslVersion != XslVersion.ForwardsCompatible)
                    {
                        ReportErrorInXPath(/*[XT0300]*/e);
                    }
                    result = _f.Error(_f.String(e.Message));
                }
            }
            if (result is QilIterator)
            {
                result = _f.Nop(result);
            }
            return result;
        }
예제 #10
0
        private QilNode CompileKeyUse(string expr) {
            XPathScanner    scanner;
            QilNode         result;

            SetEnvironmentFlags(/*allowVariables:*/false, /*allowCurrent:*/true, /*allowKey:*/false);
            if (expr == null) {
                result = PhantomXPathExpression();
            } else {
                try {
                    scanner = new XPathScanner(expr);
                    result = xpathParser.Parse(scanner, xpathBuilder, LexKind.Eof);
                } catch (XslLoadException e) {
                    if (xslVersion != XslVersion.ForwardsCompatible) {
                        ReportErrorInXPath(/*[XT0300]*/e);
                    }
                    result = f.Error(f.String(e.Message));
                }
            }
            if (result is QilIterator) {
                result = f.Nop(result);
            }
            return result;
        }