1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 [hpp]#include <sngxml/xpath/XPathExpr.hpp>
  7 #include <sngxml/xpath/XPathLexer.hpp>
  8 #include <sngxml/xpath/XPathTokens.hpp>
  9 #include <sngxml/xpath/XPathTokenValueParsers.hpp>
 10 
 11 using namespace XPathTokens;
 12 
 13 parser XPathParser
 14 {
 15     uselexer XPathLexer;
 16     main;
 17 
 18     Expr : sngxml::xpath::XPathExpr*
 19         ::= OrExpr:orExpr{ return orExpr; }
 20         ;
 21 
 22     OrExpr(var std::unique_ptr expr) : sngxml::xpath::XPathExpr*
 23         ::= (AndExpr:left{ expr.reset(left); } (NAME{ soulng::lexer::Token token = lexer.GetToken(pos); pass = lexer.GetKeywordToken(token.match) == OR; } AndExpr:right{ expr.reset(new sngxml::xpath::XPathOrExpr(expr.release(), right)); })*)
 24         {
 25             return expr.release();
 26         }
 27         ;
 28 
 29     AndExpr(var std::unique_ptr expr) : sngxml::xpath::XPathExpr*
 30         ::= (EqualityExpr:left{ expr.reset(left); } (NAME{ soulng::lexer::Token token = lexer.GetToken(pos); pass = lexer.GetKeywordToken(token.match) == AND; } EqualityExpr:right{ expr.reset(new sngxml::xpath::XPathAndExpr(expr.release(), right)); })*)
 31         {
 32             return expr.release();
 33         }
 34         ;
 35 
 36     EqualityExpr(var std::unique_ptr expr, var sngxml::xpath::Operator op) : sngxml::xpath::XPathExpr*
 37         ::=
 38         (   RelationalExpr:left{ expr.reset(left); }
 39             (   (EQ{ op = sngxml::xpath::Operator::equal; } | NEQ{ op = sngxml::xpath::Operator::notEqual; })
 40                 RelationalExpr:right!
 41                 {
 42                     switch (op)
 43                     {
 44                         case sngxml::xpath::Operator::equal: expr.reset(new sngxml::xpath::XPathEqualExpr(expr.release(), right)); break;
 45                         case sngxml::xpath::Operator::notEqual: expr.reset(new sngxml::xpath::XPathNotEqualExpr(expr.release(), right)); break;
 46                     }
 47                 }
 48             )*
 49         )
 50         {
 51             return expr.release();
 52         }
 53         ;
 54 
 55     RelationalExpr(var std::unique_ptr expr, var sngxml::xpath::Operator op) : sngxml::xpath::XPathExpr*
 56         ::=
 57         (   AdditiveExpr:left{ expr.reset(left); }
 58             (   (LEQ{ op = sngxml::xpath::Operator::lessOrEqual; } | GEQ{ op = sngxml::xpath::Operator::greaterOrEqual; } | LESS{ op = sngxml::xpath::Operator::less; } | GREATER{ op = sngxml::xpath::Operator::greater; })
 59                 AdditiveExpr:right!
 60                 {
 61                     switch (op)
 62                     {
 63                         case sngxml::xpath::Operator::lessOrEqual: expr.reset(new sngxml::xpath::XPathLessOrEqualExpr(expr.release(), right)); break;
 64                         case sngxml::xpath::Operator::greaterOrEqual: expr.reset(new sngxml::xpath::XPathGreaterOrEqualExpr(expr.release(), right)); break;
 65                         case sngxml::xpath::Operator::less: expr.reset(new sngxml::xpath::XPathLessExpr(expr.release(), right)); break;
 66                         case sngxml::xpath::Operator::greater: expr.reset(new sngxml::xpath::XPathGreaterExpr(expr.release(), right)); break;
 67                     }
 68                 }
 69             )*
 70         )
 71         {
 72             return expr.release();
 73         }
 74         ;
 75 
 76     AdditiveExpr(var std::unique_ptr expr, var sngxml::xpath::Operator op) : sngxml::xpath::XPathExpr*
 77         ::=
 78         (   MultiplicativeExpr:left{ expr.reset(left); }
 79             (   (PLUS{ op = sngxml::xpath::Operator::plus; } | MINUS{ op = sngxml::xpath::Operator::minus; })
 80                 MultiplicativeExpr:right!
 81                 {
 82                     switch (op)
 83                     {
 84                         case sngxml::xpath::Operator::plus: expr.reset(new sngxml::xpath::XPathAddExpr(expr.release(), right)); break;
 85                         case sngxml::xpath::Operator::minus: expr.reset(new sngxml::xpath::XPathSubExpr(expr.release(), right)); break;
 86                     }
 87                 }
 88             )*
 89         )
 90         {
 91             return expr.release();
 92         }
 93         ;
 94 
 95     MultiplicativeExpr(var std::unique_ptr expr, var sngxml::xpath::Operator op) : sngxml::xpath::XPathExpr*
 96         ::=
 97         (   UnaryExpr:left{ expr.reset(left); }
 98             (   (STAR{ op = sngxml::xpath::Operator::mul; }
 99                 |   NAME
100                 {
101                     soulng::lexer::Token token = lexer.GetToken(pos);
102                     switch (lexer.GetKeywordToken(token.match))
103                     {
104                         case DIV: op = sngxml::xpath::Operator::div; break;
105                         case MOD: op = sngxml::xpath::Operator::mod; break;
106                         default: pass = false; break;
107                     }
108                 }
109             )
110                 UnaryExpr:right!
111                 {
112                     switch (op)
113                     {
114                         case sngxml::xpath::Operator::mul: expr.reset(new sngxml::xpath::XPathMulExpr(expr.release(), right)); break;
115                         case sngxml::xpath::Operator::div: expr.reset(new sngxml::xpath::XPathDivExpr(expr.release(), right)); break;
116                         case sngxml::xpath::Operator::mod: expr.reset(new sngxml::xpath::XPathModExpr(expr.release(), right)); break;
117                     }
118                 }
119             )*
120         )
121         {
122             return expr.release();
123         }
124         ;
125 
126     UnaryExpr : sngxml::xpath::XPathExpr*
127         ::= MINUS UnaryExpr:subject{ return new sngxml::xpath::XPathUnaryMinusExpr(subject); }
128         |   UnionExpr:unionExpr{ return unionExpr; }
129         ;
130 
131     UnionExpr(var std::unique_ptr expr) : sngxml::xpath::XPathExpr*
132         ::= (PathExpr:left{ expr.reset(left); } (UNION PathExpr:right{ expr.reset(new sngxml::xpath::XPathUnionExpr(expr.release(), right)); })*)
133         {
134             return expr.release();
135         }
136         ;
137 
138     PathExpr(var std::unique_ptr expr, var sngxml::xpath::Operator op) : sngxml::xpath::XPathExpr*
139         ::= (LocationPath:locationPath - FunctionCall:functionCall){ return locationPath; }
140         |   (FilterExpr:filterExpr{ expr.reset(filterExpr); } ((SLASHSLASH{ op = sngxml::xpath::Operator::slashSlash; } | SLASH{ op = sngxml::xpath::Operator::slash; }) RelativeLocationPath:right
141             {
142                 switch (op)
143                 {
144                     case sngxml::xpath::Operator::slashSlash:
145                     {
146                         return new sngxml::xpath::XPathCombineStepExpr(expr.release(),
147                             new sngxml::xpath::XPathCombineStepExpr(new sngxml::xpath::XPathLocationStepExpr(sngxml::dom::Axis::descendantOrSelf, new sngxml::xpath::XPathAnyNodeTest()), right));
148                     }
149                     case sngxml::xpath::Operator::slash:
150                     {
151                         return new sngxml::xpath::XPathCombineStepExpr(expr.release(), right);
152                     }
153                 }
154             }
155             )?
156         )
157         {
158             return expr.release();
159         }
160         ;
161 
162     FilterExpr(var std::unique_ptr expr) : sngxml::xpath::XPathExpr*
163         ::= (PrimaryExpr:primaryExpr{ expr.reset(primaryExpr); } (Predicate:predicate{ expr.reset(new sngxml::xpath::XPathFilterExpr(expr.release(), predicate)); })*)
164         {
165             return expr.release();
166         }
167         ;
168 
169     LocationPath : sngxml::xpath::XPathExpr*
170         ::= AbsoluteLocationPath:absoluteLocationPath{ return absoluteLocationPath; }
171         |   RelativeLocationPath:relativeLocationPath{ return relativeLocationPath; }
172         ;
173 
174     AbsoluteLocationPath(var std::unique_ptr expr) : sngxml::xpath::XPathExpr*
175         ::=
176         (   AbbreviatedAbsoluteLocationPath:abbreviatedAbsoluteLocationPath{ expr.reset(abbreviatedAbsoluteLocationPath); }
177         |   SLASH{ expr.reset(new sngxml::xpath::XPathRootNodeExpr()); } (RelativeLocationPath:right{ expr.reset(new sngxml::xpath::XPathCombineStepExpr(expr.release(), right)); })?
178         )
179         {
180             return expr.release();
181         }
182         ;
183 
184     AbbreviatedAbsoluteLocationPath : sngxml::xpath::XPathExpr*
185         ::= SLASHSLASH RelativeLocationPath:right
186         {
187             return new sngxml::xpath::XPathCombineStepExpr(new sngxml::xpath::XPathRootNodeExpr(), new sngxml::xpath::XPathCombineStepExpr(
188                 new sngxml::xpath::XPathLocationStepExpr(sngxml::dom::Axis::descendantOrSelf, new sngxml::xpath::XPathAnyNodeTest()), right));
189         }
190         ;
191 
192     RelativeLocationPath(var std::unique_ptr expr, var sngxml::xpath::Operator op) : sngxml::xpath::XPathExpr*
193         ::=
194         (
195             Step:left{ expr.reset(left); } ((SLASHSLASH{ op = sngxml::xpath::Operator::slashSlash; } | SLASH{ op = sngxml::xpath::Operator::slash; }) Step:right
196             {
197                 switch (op)
198                 {
199                     case sngxml::xpath::Operator::slashSlash:
200                     {
201                         expr.reset(new sngxml::xpath::XPathCombineStepExpr(expr.release(), new sngxml::xpath::XPathCombineStepExpr(
202                             new sngxml::xpath::XPathLocationStepExpr(sngxml::dom::Axis::descendantOrSelf, new sngxml::xpath::XPathAnyNodeTest()), right)));
203                         break;
204                     }
205                     case sngxml::xpath::Operator::slash:
206                     {
207                         expr.reset(new sngxml::xpath::XPathCombineStepExpr(expr.release(), right));
208                         break;
209                     }
210                 }
211             }
212             )*
213         )
214         {
215             return expr.release();
216         }
217         ;
218 
219     Step(var std::unique_ptr expr) : sngxml::xpath::XPathLocationStepExpr*
220         ::=
221         (   AxisSpecifier:axis NodeTest:nodeTest{ expr.reset(new sngxml::xpath::XPathLocationStepExpr(axis, nodeTest)); } (Predicate:predicate{ expr->AddPredicate(predicate); })*
222         |   AbbreviatedStep:abbreviatedStep{ expr.reset(abbreviatedStep); }
223         )
224         {
225             return expr.release();
226         }
227         ;
228 
229     AxisSpecifier : sngxml::dom::Axis
230         ::= AxisName:axis COLONCOLON{ return axis;}
231         |   AbbreviatedAxisSpecifier:abbreviatedAxisSpecifier{ return abbreviatedAxisSpecifier; }
232         ;
233 
234     AxisName : sngxml::dom::Axis
235         ::= NAME
236         {
237             soulng::lexer::Token token = lexer.GetToken(pos);
238             switch (lexer.GetKeywordToken(token.match))
239             {
240                 case ANCESTOR:
241                 {
242                     return sngxml::dom::Axis::ancestor;
243                 }
244                 case ANCESTOR_OR_SELF:
245                 {
246                     return sngxml::dom::Axis::ancestorOrSelf;
247                 }
248                 case ATTRIBUTE:
249                 {
250                     return sngxml::dom::Axis::attribute;
251                 }
252                 case CHILD :
253                 {
254                     return sngxml::dom::Axis::child;
255                 }
256                 case DESCENDANT:
257                 {
258                     return sngxml::dom::Axis::descendant;
259                 }
260                 case DESCENDANT_OR_SELF:
261                 {
262                     return sngxml::dom::Axis::descendantOrSelf;
263                 }
264                 case FOLLOWING:
265                 {
266                     return sngxml::dom::Axis::following;
267                 }
268                 case FOLLOWING_SIBLING:
269                 {
270                     return sngxml::dom::Axis::followingSibling;
271                 }
272                 case NAMESPACE:
273                 {
274                     return sngxml::dom::Axis::ns;
275                 }
276                 case PARENT:
277                 {
278                     return sngxml::dom::Axis::parent;
279                 }
280                 case PRECEDING:
281                 {
282                     return sngxml::dom::Axis::preceding;
283                 }
284                 case PRECEDING_SIBLING:
285                 {
286                     return sngxml::dom::Axis::precedingSibling;
287                 }
288                 case SELF:
289                 {
290                     return sngxml::dom::Axis::self;
291                 }
292                 default:
293                 {
294                     pass = false;
295                     break;
296                 }
297             }
298         }
299         ;
300 
301     AbbreviatedAxisSpecifier : sngxml::dom::Axis
302         ::= AT{ return sngxml::dom::Axis::attribute; }
303         |   empty{ return sngxml::dom::Axis::child; }
304         ;
305 
306     NodeTest : sngxml::xpath::XPathNodeTestExpr*
307         ::= NAME{ soulng::lexer::Token token = lexer.GetToken(pos); pass = lexer.GetKeywordToken(token.match) == PROCESSING_INSTRUCTION; } LPAREN Literal:pi RPAREN{ return new sngxml::xpath::XPathPILiteralTest(pi); }
308         |   NodeType:nodeType LPAREN RPAREN{ return nodeType; }
309         |   NameTest:nameTest{ return nameTest; }
310         ;
311 
312     NodeType : sngxml::xpath::XPathNodeTestExpr*
313         ::= NAME
314         {
315             soulng::lexer::Token token = lexer.GetToken(pos);
316             switch (lexer.GetKeywordToken(token.match))
317             {
318                 case COMMENT: return new sngxml::xpath::XPathCommentNodeTest();
319                 case TEXT: return new sngxml::xpath::XPathTextNodeTest();
320                 case PROCESSING_INSTRUCTION: return new sngxml::xpath::XPathPINodeTest();
321                 case NODE: return new sngxml::xpath::XPathAnyNodeTest();
322                 default:
323                 {
324                     pass = false;
325                     break;
326                 }
327             }
328         }
329         ;
330 
331     NameTest : sngxml::xpath::XPathNodeTestExpr*
332         ::= STAR{ return new sngxml::xpath::XPathPrincipalNodeTest(); }
333         |   NCName:ncname COLON STAR{ return new sngxml::xpath::XPathPrefixTest(ncname); }
334         |   QName:qname{ return new sngxml::xpath::XPathNameTest(qname); }
335         ;
336 
337     AbbreviatedStep : sngxml::xpath::XPathLocationStepExpr*
338         ::= DOTDOT{ return new sngxml::xpath::XPathLocationStepExpr(sngxml::dom::Axis::parent, new sngxml::xpath::XPathAnyNodeTest()); }
339         |   DOT{ return new sngxml::xpath::XPathLocationStepExpr(sngxml::dom::Axis::self, new sngxml::xpath::XPathAnyNodeTest()); }
340         ;
341 
342     Literal : sngxml::xpath::XPathExpr*
343         ::= DQSTRING{ soulng::lexer::Token token = lexer.GetToken(pos); return new sngxml::xpath::XPathLiteral(sngxml::xpath::ParseDQString(lexer.FileName(), token)); }
344         |   SQSTRING{ soulng::lexer::Token token = lexer.GetToken(pos); return new sngxml::xpath::XPathLiteral(sngxml::xpath::ParseSQString(lexer.FileName(), token)); }
345         ;
346 
347     Number : sngxml::xpath::XPathExpr*
348         ::= NUMBER{ soulng::lexer::Token token = lexer.GetToken(pos); return new sngxml::xpath::XPathNumberExpr(token.match.ToString()); }
349         ;
350 
351     Predicate : sngxml::xpath::XPathExpr*
352         ::= (LBRACKET PredicateExpr:expr RBRACKET){ return expr; }
353         ;
354 
355     PredicateExpr : sngxml::xpath::XPathExpr*
356         ::= Expr:expr{ return expr; }
357         ;
358 
359     PrimaryExpr : sngxml::xpath::XPathExpr*
360         ::= FunctionCall:functionCall{ return functionCall; }
361         |   VariableReference:variableReference{ return variableReference; }
362         |   (LPAREN Expr:expr RPAREN){ return expr; }
363         |   Literal:literal{ return literal; }
364         |   Number:number{ return number; }
365         ;
366 
367     VariableReference : sngxml::xpath::XPathExpr*
368         ::= (DOLLAR QName:qname){ return new sngxml::xpath::XPathVariableReference(qname); }
369         ;
370 
371     FunctionCall(var std::unique_ptr functionCall) : sngxml::xpath::XPathExpr*
372         ::= (FunctionName:functionName LPAREN{ functionCall.reset(new sngxml::xpath::XPathFunctionCall(functionName)); } (Argument:arg{ functionCall->AddArgument(arg); } % COMMA)? RPAREN)
373         {
374             return functionCall.release();
375         }
376         ;
377 
378     FunctionName : std::u32string
379         ::= (QName:qname - NodeType:nodeType){ return qname; }
380         ;
381 
382     Argument : sngxml::xpath::XPathExpr*
383         ::= Expr:expr{ return expr; }
384         ;
385 
386     QName : std::u32string
387         ::= PrefixedName:prefixedName{ return prefixedName; }
388         |   UnprefixedName:unprefixedName{ return unprefixedName; }
389         ;
390 
391     PrefixedName : std::u32string
392         ::= (Prefix:prefix COLON LocalPart:localPart){ return prefix + U":" + localPart; }
393         ;
394 
395     Prefix : std::u32string
396         ::= NCName:ncname{ return ncname; }
397         ;
398 
399     UnprefixedName : std::u32string
400         ::= LocalPart:localPart{ return localPart; }
401         ;
402 
403     LocalPart : std::u32string
404         ::= NCName:ncname{ return ncname; }
405         ;
406 
407     NCName : std::u32string
408         ::= NAME{ soulng::lexer::Token token = lexer.GetToken(pos); return token.match.ToString(); }
409         ;
410 
411 }