1/*
2 * Copyright 2005 Frerich Raabe <raabe@kde.org>
3 * Copyright (C) 2006 Apple Inc. All rights reserved.
4 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28%{
29
30#include "config.h"
31
32#include "core/xml/XPathFunctions.h"
33#include "core/xml/XPathNSResolver.h"
34#include "core/xml/XPathParser.h"
35#include "core/xml/XPathPath.h"
36#include "core/xml/XPathPredicate.h"
37#include "core/xml/XPathStep.h"
38#include "core/xml/XPathVariableReference.h"
39#include "wtf/FastMalloc.h"
40
41#define YYMALLOC fastMalloc
42#define YYFREE fastFree
43
44#define YYENABLE_NLS 0
45#define YYLTYPE_IS_TRIVIAL 1
46#define YYDEBUG 0
47#define YYMAXDEPTH 10000
48
49using namespace blink;
50using namespace XPath;
51
52%}
53
54%pure-parser
55%parse-param { blink::XPath::Parser* parser }
56
57%union
58{
59    blink::XPath::Step::Axis axis;
60    blink::XPath::Step::NodeTest* nodeTest;
61    blink::XPath::NumericOp::Opcode numop;
62    blink::XPath::EqTestOp::Opcode eqop;
63    String* str;
64    blink::XPath::Expression* expr;
65    WillBeHeapVector<OwnPtrWillBeMember<blink::XPath::Predicate> >* predList;
66    WillBeHeapVector<OwnPtrWillBeMember<blink::XPath::Expression> >* argList;
67    blink::XPath::Step* step;
68    blink::XPath::LocationPath* locationPath;
69}
70
71%{
72
73static int xpathyylex(YYSTYPE* yylval) { return Parser::current()->lex(yylval); }
74static void xpathyyerror(void*, const char*) { }
75
76%}
77
78%left <numop> MULOP
79%left <eqop> EQOP RELOP
80%left PLUS MINUS
81%left OR AND
82%token <axis> AXISNAME
83%token <str> NODETYPE PI FUNCTIONNAME LITERAL
84%token <str> VARIABLEREFERENCE NUMBER
85%token DOTDOT SLASHSLASH
86%token <str> NAMETEST
87%token XPATH_ERROR
88
89%type <locationPath> LocationPath
90%type <locationPath> AbsoluteLocationPath
91%type <locationPath> RelativeLocationPath
92%type <step> Step
93%type <axis> AxisSpecifier
94%type <step> DescendantOrSelf
95%type <nodeTest> NodeTest
96%type <expr> Predicate
97%type <predList> OptionalPredicateList
98%type <predList> PredicateList
99%type <step> AbbreviatedStep
100%type <expr> Expr
101%type <expr> PrimaryExpr
102%type <expr> FunctionCall
103%type <argList> ArgumentList
104%type <expr> Argument
105%type <expr> UnionExpr
106%type <expr> PathExpr
107%type <expr> FilterExpr
108%type <expr> OrExpr
109%type <expr> AndExpr
110%type <expr> EqualityExpr
111%type <expr> RelationalExpr
112%type <expr> AdditiveExpr
113%type <expr> MultiplicativeExpr
114%type <expr> UnaryExpr
115
116%%
117
118Expr:
119    OrExpr
120    {
121        parser->m_topExpr = $1;
122    }
123    ;
124
125LocationPath:
126    RelativeLocationPath
127    {
128        $$->setAbsolute(false);
129    }
130    |
131    AbsoluteLocationPath
132    {
133        $$->setAbsolute(true);
134    }
135    ;
136
137AbsoluteLocationPath:
138    '/'
139    {
140        $$ = new LocationPath;
141        parser->registerParseNode($$);
142    }
143    |
144    '/' RelativeLocationPath
145    {
146        $$ = $2;
147    }
148    |
149    DescendantOrSelf RelativeLocationPath
150    {
151        $$ = $2;
152        $$->insertFirstStep($1);
153        parser->unregisterParseNode($1);
154    }
155    ;
156
157RelativeLocationPath:
158    Step
159    {
160        $$ = new LocationPath;
161        $$->appendStep($1);
162        parser->unregisterParseNode($1);
163        parser->registerParseNode($$);
164    }
165    |
166    RelativeLocationPath '/' Step
167    {
168        $$->appendStep($3);
169        parser->unregisterParseNode($3);
170    }
171    |
172    RelativeLocationPath DescendantOrSelf Step
173    {
174        $$->appendStep($2);
175        $$->appendStep($3);
176        parser->unregisterParseNode($2);
177        parser->unregisterParseNode($3);
178    }
179    ;
180
181Step:
182    NodeTest OptionalPredicateList
183    {
184        if ($2) {
185            $$ = new Step(Step::ChildAxis, *$1, *$2);
186            parser->deletePredicateVector($2);
187        } else
188            $$ = new Step(Step::ChildAxis, *$1);
189        parser->deleteNodeTest($1);
190        parser->registerParseNode($$);
191    }
192    |
193    NAMETEST OptionalPredicateList
194    {
195        AtomicString localName;
196        AtomicString namespaceURI;
197        if (!parser->expandQName(*$1, localName, namespaceURI)) {
198            parser->m_gotNamespaceError = true;
199            YYABORT;
200        }
201
202        if ($2) {
203            $$ = new Step(Step::ChildAxis, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI), *$2);
204            parser->deletePredicateVector($2);
205        } else
206            $$ = new Step(Step::ChildAxis, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI));
207        parser->deleteString($1);
208        parser->registerParseNode($$);
209    }
210    |
211    AxisSpecifier NodeTest OptionalPredicateList
212    {
213        if ($3) {
214            $$ = new Step($1, *$2, *$3);
215            parser->deletePredicateVector($3);
216        } else
217            $$ = new Step($1, *$2);
218        parser->deleteNodeTest($2);
219        parser->registerParseNode($$);
220    }
221    |
222    AxisSpecifier NAMETEST OptionalPredicateList
223    {
224        AtomicString localName;
225        AtomicString namespaceURI;
226        if (!parser->expandQName(*$2, localName, namespaceURI)) {
227            parser->m_gotNamespaceError = true;
228            YYABORT;
229        }
230
231        if ($3) {
232            $$ = new Step($1, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI), *$3);
233            parser->deletePredicateVector($3);
234        } else
235            $$ = new Step($1, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI));
236        parser->deleteString($2);
237        parser->registerParseNode($$);
238    }
239    |
240    AbbreviatedStep
241    ;
242
243AxisSpecifier:
244    AXISNAME
245    |
246    '@'
247    {
248        $$ = Step::AttributeAxis;
249    }
250    ;
251
252NodeTest:
253    NODETYPE '(' ')'
254    {
255        if (*$1 == "node")
256            $$ = new Step::NodeTest(Step::NodeTest::AnyNodeTest);
257        else if (*$1 == "text")
258            $$ = new Step::NodeTest(Step::NodeTest::TextNodeTest);
259        else if (*$1 == "comment")
260            $$ = new Step::NodeTest(Step::NodeTest::CommentNodeTest);
261
262        parser->deleteString($1);
263        parser->registerNodeTest($$);
264    }
265    |
266    PI '(' ')'
267    {
268        $$ = new Step::NodeTest(Step::NodeTest::ProcessingInstructionNodeTest);
269        parser->deleteString($1);
270        parser->registerNodeTest($$);
271    }
272    |
273    PI '(' LITERAL ')'
274    {
275        $$ = new Step::NodeTest(Step::NodeTest::ProcessingInstructionNodeTest, $3->stripWhiteSpace());
276        parser->deleteString($1);
277        parser->deleteString($3);
278        parser->registerNodeTest($$);
279    }
280    ;
281
282OptionalPredicateList:
283    /* empty */
284    {
285        $$ = 0;
286    }
287    |
288    PredicateList
289    ;
290
291PredicateList:
292    Predicate
293    {
294        $$ = new WillBeHeapVector<OwnPtrWillBeMember<Predicate> >;
295        $$->append(adoptPtrWillBeNoop(new Predicate(adoptPtrWillBeNoop($1))));
296        parser->unregisterParseNode($1);
297        parser->registerPredicateVector($$);
298    }
299    |
300    PredicateList Predicate
301    {
302        $$->append(adoptPtrWillBeNoop(new Predicate(adoptPtrWillBeNoop($2))));
303        parser->unregisterParseNode($2);
304    }
305    ;
306
307Predicate:
308    '[' Expr ']'
309    {
310        $$ = $2;
311    }
312    ;
313
314DescendantOrSelf:
315    SLASHSLASH
316    {
317        $$ = new Step(Step::DescendantOrSelfAxis, Step::NodeTest(Step::NodeTest::AnyNodeTest));
318        parser->registerParseNode($$);
319    }
320    ;
321
322AbbreviatedStep:
323    '.'
324    {
325        $$ = new Step(Step::SelfAxis, Step::NodeTest(Step::NodeTest::AnyNodeTest));
326        parser->registerParseNode($$);
327    }
328    |
329    DOTDOT
330    {
331        $$ = new Step(Step::ParentAxis, Step::NodeTest(Step::NodeTest::AnyNodeTest));
332        parser->registerParseNode($$);
333    }
334    ;
335
336PrimaryExpr:
337    VARIABLEREFERENCE
338    {
339        $$ = new VariableReference(*$1);
340        parser->deleteString($1);
341        parser->registerParseNode($$);
342    }
343    |
344    '(' Expr ')'
345    {
346        $$ = $2;
347    }
348    |
349    LITERAL
350    {
351        $$ = new StringExpression(*$1);
352        parser->deleteString($1);
353        parser->registerParseNode($$);
354    }
355    |
356    NUMBER
357    {
358        $$ = new Number($1->toDouble());
359        parser->deleteString($1);
360        parser->registerParseNode($$);
361    }
362    |
363    FunctionCall
364    ;
365
366FunctionCall:
367    FUNCTIONNAME '(' ')'
368    {
369        $$ = createFunction(*$1);
370        if (!$$)
371            YYABORT;
372        parser->deleteString($1);
373        parser->registerParseNode($$);
374    }
375    |
376    FUNCTIONNAME '(' ArgumentList ')'
377    {
378        $$ = createFunction(*$1, *$3);
379        if (!$$)
380            YYABORT;
381        parser->deleteString($1);
382        parser->deleteExpressionVector($3);
383        parser->registerParseNode($$);
384    }
385    ;
386
387ArgumentList:
388    Argument
389    {
390        $$ = new WillBeHeapVector<OwnPtrWillBeMember<Expression> >;
391        $$->append(adoptPtrWillBeNoop($1));
392        parser->unregisterParseNode($1);
393        parser->registerExpressionVector($$);
394    }
395    |
396    ArgumentList ',' Argument
397    {
398        $$->append(adoptPtrWillBeNoop($3));
399        parser->unregisterParseNode($3);
400    }
401    ;
402
403Argument:
404    Expr
405    ;
406
407UnionExpr:
408    PathExpr
409    |
410    UnionExpr '|' PathExpr
411    {
412        $$ = new Union;
413        $$->addSubExpression(adoptPtrWillBeNoop($1));
414        $$->addSubExpression(adoptPtrWillBeNoop($3));
415        parser->unregisterParseNode($1);
416        parser->unregisterParseNode($3);
417        parser->registerParseNode($$);
418    }
419    ;
420
421PathExpr:
422    LocationPath
423    {
424        $$ = $1;
425    }
426    |
427    FilterExpr
428    |
429    FilterExpr '/' RelativeLocationPath
430    {
431        $3->setAbsolute(true);
432        $$ = new Path($1, $3);
433        parser->unregisterParseNode($1);
434        parser->unregisterParseNode($3);
435        parser->registerParseNode($$);
436    }
437    |
438    FilterExpr DescendantOrSelf RelativeLocationPath
439    {
440        $3->insertFirstStep($2);
441        $3->setAbsolute(true);
442        $$ = new Path($1, $3);
443        parser->unregisterParseNode($1);
444        parser->unregisterParseNode($2);
445        parser->unregisterParseNode($3);
446        parser->registerParseNode($$);
447    }
448    ;
449
450FilterExpr:
451    PrimaryExpr
452    |
453    PrimaryExpr PredicateList
454    {
455        $$ = new Filter(adoptPtrWillBeNoop($1), *$2);
456        parser->unregisterParseNode($1);
457        parser->deletePredicateVector($2);
458        parser->registerParseNode($$);
459    }
460    ;
461
462OrExpr:
463    AndExpr
464    |
465    OrExpr OR AndExpr
466    {
467        $$ = new LogicalOp(LogicalOp::OP_Or, adoptPtrWillBeNoop($1), adoptPtrWillBeNoop($3));
468        parser->unregisterParseNode($1);
469        parser->unregisterParseNode($3);
470        parser->registerParseNode($$);
471    }
472    ;
473
474AndExpr:
475    EqualityExpr
476    |
477    AndExpr AND EqualityExpr
478    {
479        $$ = new LogicalOp(LogicalOp::OP_And, adoptPtrWillBeNoop($1), adoptPtrWillBeNoop($3));
480        parser->unregisterParseNode($1);
481        parser->unregisterParseNode($3);
482        parser->registerParseNode($$);
483    }
484    ;
485
486EqualityExpr:
487    RelationalExpr
488    |
489    EqualityExpr EQOP RelationalExpr
490    {
491        $$ = new EqTestOp($2, adoptPtrWillBeNoop($1), adoptPtrWillBeNoop($3));
492        parser->unregisterParseNode($1);
493        parser->unregisterParseNode($3);
494        parser->registerParseNode($$);
495    }
496    ;
497
498RelationalExpr:
499    AdditiveExpr
500    |
501    RelationalExpr RELOP AdditiveExpr
502    {
503        $$ = new EqTestOp($2, adoptPtrWillBeNoop($1), adoptPtrWillBeNoop($3));
504        parser->unregisterParseNode($1);
505        parser->unregisterParseNode($3);
506        parser->registerParseNode($$);
507    }
508    ;
509
510AdditiveExpr:
511    MultiplicativeExpr
512    |
513    AdditiveExpr PLUS MultiplicativeExpr
514    {
515        $$ = new NumericOp(NumericOp::OP_Add, adoptPtrWillBeNoop($1), adoptPtrWillBeNoop($3));
516        parser->unregisterParseNode($1);
517        parser->unregisterParseNode($3);
518        parser->registerParseNode($$);
519    }
520    |
521    AdditiveExpr MINUS MultiplicativeExpr
522    {
523        $$ = new NumericOp(NumericOp::OP_Sub, adoptPtrWillBeNoop($1), adoptPtrWillBeNoop($3));
524        parser->unregisterParseNode($1);
525        parser->unregisterParseNode($3);
526        parser->registerParseNode($$);
527    }
528    ;
529
530MultiplicativeExpr:
531    UnaryExpr
532    |
533    MultiplicativeExpr MULOP UnaryExpr
534    {
535        $$ = new NumericOp($2, adoptPtrWillBeNoop($1), adoptPtrWillBeNoop($3));
536        parser->unregisterParseNode($1);
537        parser->unregisterParseNode($3);
538        parser->registerParseNode($$);
539    }
540    ;
541
542UnaryExpr:
543    UnionExpr
544    |
545    MINUS UnaryExpr
546    {
547        $$ = new Negative;
548        $$->addSubExpression(adoptPtrWillBeNoop($2));
549        parser->unregisterParseNode($2);
550        parser->registerParseNode($$);
551    }
552    ;
553
554%%
555