Project

Profile

Help

Revision d82fa842

Added by Michael Kay almost 3 years ago

Feature #4078 - fast XPath parsing for simple expressions

View differences:

latest9.9/hej/net/sf/saxon/expr/parser/ExpressionTool.java
105 105
            terminator = Token.EOF;
106 106
        }
107 107
        Expression exp = parser.parse(expression, start, terminator, env);
108
        // TODO: parser.parse() already sets the retained static context
108 109
        setDeepRetainedStaticContext(exp, env.makeRetainedStaticContext());
109 110
        exp = exp.simplify();
110 111
        return exp;
latest9.9/hej/net/sf/saxon/expr/parser/XPathParser.java
87 87

  
88 88
    /*@Nullable*/
89 89
    protected CodeInjector codeInjector = null;
90
    private Accelerator accelerator = null;
90 91

  
91 92
    protected int language = XPATH;     // know which language we are parsing, for diagnostics
92 93
    public static final int XPATH = 0;
......
98 99
    protected int languageVersion = 20;
99 100
    protected int catchDepth = 0;
100 101

  
102
    public interface Accelerator {
103

  
104
        /**
105
         * Attempt fast parsing of an expression, provided it is sufficiently simple.
106
         *
107
         * @param t          the tokenizer
108
         * @param env        the static context
109
         * @param expression the string containing expression to be parsed
110
         * @param start      start position within the input string
111
         * @param terminator either EOF or RCURLY, indicating how parsing should end
112
         * @return either the parsed expression, or null if it is erroneous or too
113
         * complex to parse.
114
         */
115

  
116
        Expression parse(Tokenizer t, StaticContext env, String expression, int start, int terminator);
117
    }
118

  
101 119
    /**
102 120
     * Create an expression parser
103 121
     */
......
131 149
    }
132 150

  
133 151
    /**
152
     * Set an accelerator which can be used for fast parsing of special cases
153
     * @param accelerator a parsing accelerator
154
     */
155

  
156
    public void setAccelerator(Accelerator accelerator) {
157
        this.accelerator = accelerator;
158
    }
159

  
160
    /**
134 161
     * Get the tokenizer (the lexical analyzer)
135 162
     *
136 163
     * @return the tokenizer (the lexical analyzer)
......
170 197
//        return defaultContainer;
171 198
//    }
172 199

  
200
    /**
201
     * Set a parser extension which can handle extensions to the XPath syntax, e.g. for
202
     * XQuery update extensions
203
     * @param extension a parser extension
204
     */
205

  
173 206
    public void setParserExtension(ParserExtension extension) {
174 207
        this.parserExtension = extension;
175 208
    }
......
443 476
        }
444 477
        setLanguage(language, languageVersion);
445 478

  
446
        qNameParser = new QNameParser(env.getNamespaceResolver());
447
        qNameParser.setAcceptEQName(allowXPath30Syntax);
448
        qNameParser.setDefaultNamespace("");
449
        qNameParser.setErrorOnBadSyntax(language == XSLT_PATTERN ? "XTSE0340" : "XPST0003");
450
        qNameParser.setErrorOnUnresolvedPrefix("XPST0081");
451

  
452
        charChecker = env.getConfiguration().getValidCharacterChecker();
453
        t = new Tokenizer();
454
        t.languageLevel = env.getXPathVersion();
455
        allowSaxonExtensions =
456
                t.allowSaxonExtensions =
457
                        env.getConfiguration().getBooleanProperty(Feature.ALLOW_SYNTAX_EXTENSIONS);
458
        int offset = t.currentTokenStartOffset;
459
        customizeTokenizer(t);
460
        try {
461
            t.tokenize(expression, start, -1);
462
        } catch (XPathException err) {
463
            grumble(err.getMessage());
464
        }
465
        if (t.currentToken == terminator) {
466
            if (allowAbsentExpression) {
467
                Expression result = Literal.makeEmptySequence();
468
                result.setRetainedStaticContext(env.makeRetainedStaticContext());
469
                setLocation(result);
470
                return result;
471
            } else {
472
                grumble("The expression is empty");
479
        Expression exp = null;
480
        int offset = start;
481
        if (accelerator != null) {
482
            if (expression.length() - start < 30 || terminator == Token.RCURLY) {
483
                // We need the tokenizer to be visible so that the caller can ask
484
                // about where the expression ended within the input string
485
                t = new Tokenizer();
486
                t.languageLevel = env.getXPathVersion();
487
                exp = accelerator.parse(t, env, expression, start, terminator);
473 488
            }
474 489
        }
475
        Expression exp = parseExpression();
476
        if (t.currentToken != terminator) {
477
            if (t.currentToken == Token.EOF && terminator == Token.RCURLY) {
478
                grumble("Missing curly brace after expression in value template", "XTSE0350");
479
            } else {
480
                grumble("Unexpected token " + currentTokenDisplay() + " beyond end of expression");
490

  
491
        if (exp == null) {
492

  
493
            qNameParser = new QNameParser(env.getNamespaceResolver());
494
            qNameParser.setAcceptEQName(allowXPath30Syntax);
495
            qNameParser.setDefaultNamespace("");
496
            qNameParser.setErrorOnBadSyntax(language == XSLT_PATTERN ? "XTSE0340" : "XPST0003");
497
            qNameParser.setErrorOnUnresolvedPrefix("XPST0081");
498

  
499
            charChecker = env.getConfiguration().getValidCharacterChecker();
500
            t = new Tokenizer();
501
            t.languageLevel = env.getXPathVersion();
502
            allowSaxonExtensions =
503
                    t.allowSaxonExtensions =
504
                            env.getConfiguration().getBooleanProperty(Feature.ALLOW_SYNTAX_EXTENSIONS);
505
            offset = t.currentTokenStartOffset;
506
            customizeTokenizer(t);
507
            try {
508
                t.tokenize(expression, start, -1);
509
            } catch (XPathException err) {
510
                grumble(err.getMessage());
511
            }
512
            if (t.currentToken == terminator) {
513
                if (allowAbsentExpression) {
514
                    Expression result = Literal.makeEmptySequence();
515
                    result.setRetainedStaticContext(env.makeRetainedStaticContext());
516
                    setLocation(result);
517
                    return result;
518
                } else {
519
                    grumble("The expression is empty");
520
                }
481 521
            }
522
            exp = parseExpression();
523
            if (t.currentToken != terminator) {
524
                if (t.currentToken == Token.EOF && terminator == Token.RCURLY) {
525
                    grumble("Missing curly brace after expression in value template", "XTSE0350");
526
                } else {
527
                    grumble("Unexpected token " + currentTokenDisplay() + " beyond end of expression");
528
                }
529
            }
530
            setLocation(exp, offset);
482 531
        }
483 532
        exp.setRetainedStaticContextThoroughly(env.makeRetainedStaticContext());
484
        setLocation(exp, offset);
485 533
        //exp.verifyParentPointers();
486 534
        return exp;
487 535
    }
latest9.9/hej/net/sf/saxon/functions/ScalarSystemFunction.java
73 73

  
74 74
    @Override
75 75
    public Expression makeFunctionCall(Expression[] arguments) {
76
        return new SystemFunctionCall(this, arguments) {
76
        SystemFunctionCall call = new SystemFunctionCall(this, arguments) {
77 77
            @Override
78 78
            public AtomicValue evaluateItem(XPathContext context) throws XPathException {
79 79
                // cut out some of the call overhead
......
85 85
                }
86 86
            }
87 87
        };
88
        call.setRetainedStaticContext(getRetainedStaticContext());
89
        return call;
88 90
    }
89 91
}
90 92

  
latest9.9/hej/net/sf/saxon/om/NamePool.java
198 198

  
199 199
    /*@NotNull*/
200 200
    public String getURI(int nameCode) {
201
        return getUnprefixedQName(nameCode).getURI();
201
        int fp = nameCode & FP_MASK;
202
        if ((fp & USER_DEFINED_MASK) == 0) {
203
            return StandardNames.getURI(fp);
204
        }
205
        return getUnprefixedQName(fp).getURI();
202 206
    }
203 207

  
204 208
    /**

Also available in: Unified diff