TARGET_JVM: refer nunit from mono tree
[mono.git] / mcs / class / System.XML / System.Xml.XPath / Parser.jay
1 %{
2 // XPath/XSLT Pattern parser
3 //
4 // Author: Piers Haken <piersh@friskit.com>
5 //         Atsushi Enomoto  <atsushi@ximian.com>
6 //
7 // IMPORTANT:
8 // Do not edit "PatternParser.jay". It is autogenerated from
9 // Parser.jay. It will be overwritten!
10 //
11
12 using System;
13 using System.Collections;
14 using System.Xml;
15 using System.Xml.XPath;
16
17 #if XSLT_PATTERN
18 namespace Mono.Xml.Xsl
19 #else
20 namespace Mono.Xml.XPath
21 #endif
22 {
23 #if XSLT_PATTERN
24         internal class XsltPatternParser
25 #else
26         internal class XPathParser
27 #endif
28         {
29         
30                 internal System.Xml.Xsl.IStaticXsltContext Context;
31                 
32 #if XSLT_PATTERN
33                 public XsltPatternParser () : this (null) {}
34                 internal XsltPatternParser (System.Xml.Xsl.IStaticXsltContext context)
35 #else
36                 public XPathParser () : this (null) {}
37                 internal XPathParser (System.Xml.Xsl.IStaticXsltContext context)
38 #endif
39                 {
40                         Context = context;
41                         ErrorOutput = System.IO.TextWriter.Null;
42 //                      debug = new yydebug.yyDebugSimple ();
43                 }
44                 
45                 internal Expression Compile (string xpath)
46                 {
47                         try {
48                                 Tokenizer tokenizer = new Tokenizer (xpath);
49                                 return (Expression) yyparse (tokenizer);
50                         } catch (XPathException) {
51                                 throw;
52                         } catch (Exception e) {
53                                 throw new XPathException ("Error during parse of " + xpath, e);
54                         }
55                 }
56                 static int yacc_verbose_flag;
57
58                 private NodeSet CreateNodeTest (Axes axis, object nodeTest, ArrayList plist)
59                 {
60                         NodeSet test = CreateNodeTest (axis, nodeTest);
61                         if (plist != null) {
62                                 for (int i = 0; i < plist.Count; i++)
63                                         test = new ExprFilter (test,
64                                                 (Expression) plist [i]);
65                         }
66                         return test;
67                 }
68
69                 private NodeTest CreateNodeTest (Axes axis, object test)
70                 {
71                         if (test is XPathNodeType)
72                                 return new NodeTypeTest (axis,
73                                         (XPathNodeType) test, null);
74                         else if (test is string || test == null)
75                                 return new NodeTypeTest (axis,
76                                         XPathNodeType.ProcessingInstruction,
77                                         (string) test);
78                         XmlQualifiedName q = (XmlQualifiedName) test;
79                         if (q == XmlQualifiedName.Empty)
80                                 return new NodeTypeTest (axis);
81                         else
82                                 return new NodeNameTest (axis, q, Context);
83                 }
84 %}
85
86 %token ERROR
87 %token EOF
88
89 %token SLASH                    "/"
90 %token SLASH2                   "//"
91 %token DOT                              "."
92 %token DOT2                             ".."
93 %token COLON2                   "::"
94 %token COMMA                    ","
95 %token AT                               "@"
96
97 %token FUNCTION_NAME
98
99 %token BRACKET_OPEN             "["
100 %token BRACKET_CLOSE    "]"
101 %token PAREN_OPEN               "("
102 %token PAREN_CLOSE              ")"
103
104 %token AND                              "and"
105 %token OR                               "or"
106 %token DIV                              "div"
107 %token MOD                              "mod"
108 %token PLUS                             "+"
109 %token MINUS                    "-"
110 %token ASTERISK                 "*"
111 %token DOLLAR                   "$"
112 %token BAR                              "|"
113 %token EQ                               "="
114 %token NE                               "!="
115 %token LE                               "<="
116 %token GE                               ">="
117 %token LT                               "<"
118 %token GT                               ">"
119
120 %token ANCESTOR                                 "ancestor"
121 %token ANCESTOR_OR_SELF                 "ancstor-or-self"
122 %token ATTRIBUTE                                "attribute"
123 %token CHILD                                    "child"
124 %token DESCENDANT                               "descendant"
125 %token DESCENDANT_OR_SELF               "descendant-or-self"
126 %token FOLLOWING                                "following"
127 %token FOLLOWING_SIBLING                "sibling"
128 %token NAMESPACE                                "NameSpace"
129 %token PARENT                                   "parent"
130 %token PRECEDING                                "preceding"
131 %token PRECEDING_SIBLING                "preceding-sibling"
132 %token SELF                                             "self"
133
134 %token COMMENT                                  "comment"
135 %token TEXT                                             "text"
136 %token PROCESSING_INSTRUCTION   "processing-instruction"
137 %token NODE                                             "node"
138
139 %token MULTIPLY                 "*"
140
141 %token NUMBER
142 %token LITERAL
143 %token QName
144
145
146 %start Expr
147
148
149 %left AND
150 %left OR
151 %left EQ
152 %left NE
153 %left LE
154 %left GE
155 %left LT
156 %left GT
157
158 %left DIV
159 %left MOD
160 %left PLUS
161 %left MINUS
162
163 %%
164
165 /* XSLT Pattern */
166
167 Pattern
168         : LocationPathPattern
169         | Pattern BAR LocationPathPattern
170         {
171                 $$ = new ExprUNION ((NodeSet) $1, (NodeSet) $3);
172         }
173         ;
174
175 LocationPathPattern
176         : SLASH
177         {
178                 $$ = new ExprRoot ();
179         }
180         | SLASH RelativePathPattern
181         {
182                 $$ = new ExprSLASH (new ExprRoot (), (NodeSet) $2);
183         }
184         | IdKeyPattern
185         | IdKeyPattern SLASH RelativePathPattern
186         {
187                 $$ = new ExprSLASH ((Expression) $1, (NodeSet) $3);
188         }
189         | IdKeyPattern SLASH2 RelativePathPattern
190         {
191                 $$ = new ExprSLASH2 ((Expression) $1, (NodeSet) $3);
192         }
193         | SLASH2 RelativePathPattern
194         {
195                 $$ = new ExprSLASH2 (new ExprRoot (), (NodeSet) $2);
196         }
197         | RelativePathPattern
198         ;
199
200 // to avoid context-sensitive tokenizer, I just reuse FUNCTION_NAME
201 IdKeyPattern
202         : FUNCTION_NAME PAREN_OPEN LITERAL PAREN_CLOSE
203         {
204                 XmlQualifiedName name = (XmlQualifiedName) $1;
205                 if (name.Name != "id" || name.Namespace != String.Empty)
206                         throw new XPathException (String.Format ("Expected 'id' but got '{0}'", name));
207                 $$ = ExprFunctionCall.Factory (name,
208                         new FunctionArguments (
209                                 new ExprLiteral ((string) $3),
210                                 null),
211                         Context);
212         }
213         | FUNCTION_NAME PAREN_OPEN LITERAL COMMA LITERAL PAREN_CLOSE
214         {
215                 XmlQualifiedName name = (XmlQualifiedName) $1;
216                 if (name.Name != "key" || name.Namespace != String.Empty)
217                         throw new XPathException (String.Format ("Expected 'key' but got '{0}'", name));
218                 $$ = Context.TryGetFunction (name,
219                         new FunctionArguments (
220                                 new ExprLiteral ((string) $3),
221                                 new FunctionArguments (
222                                         new ExprLiteral ((string) $5),
223                                         null)));
224         }
225         ;
226
227 RelativePathPattern
228         : StepPattern
229         | RelativePathPattern SLASH StepPattern
230         {
231                 $$ = new ExprSLASH ((Expression) $1, (NodeSet) $3);
232         }
233         | RelativePathPattern SLASH2 StepPattern
234         {
235                 $$ = new ExprSLASH2 ((Expression) $1, (NodeSet) $3);
236         }
237         ;
238
239 StepPattern
240         : ChildOrAttributeAxisSpecifier NodeTest Predicates
241         {
242                 $$ = CreateNodeTest ((Axes) $1, $2, (ArrayList) $3);
243         }
244         ;
245
246 ChildOrAttributeAxisSpecifier
247         : AbbreviatedAxisSpecifier
248         | CHILD COLON2
249         {
250                 $$ = Axes.Child;
251         }
252         | ATTRIBUTE COLON2
253         {
254                 $$ = Axes.Attribute;
255         }
256         ;
257
258 Predicates
259         : // empty
260         {
261                 $$ = null;
262         }
263         | Predicates Predicate
264         {
265                 ArrayList al = (ArrayList) $1;
266                 if (al == null)
267                         al = new ArrayList ();
268                 al.Add ((Expression) $2);
269                 $$ = al;
270         }
271         ;
272
273 /* ---- end of XSLT Pattern ---- */
274
275
276 Expr
277         : OrExpr
278         ;
279         
280 OrExpr
281         : AndExpr 
282         | OrExpr OR AndExpr
283         {
284                 $$ = new ExprOR ((Expression) $1, (Expression) $3);
285         }
286         ;
287
288 AndExpr
289         : EqualityExpr 
290         | AndExpr AND EqualityExpr 
291         {
292                 $$ = new ExprAND ((Expression) $1, (Expression) $3);
293         }
294         ;
295
296 EqualityExpr
297         : RelationalExpr 
298         | EqualityExpr EQ RelationalExpr 
299         {
300                 $$ = new ExprEQ ((Expression) $1, (Expression) $3);
301         }
302         | EqualityExpr NE RelationalExpr 
303         {
304                 $$ = new ExprNE ((Expression) $1, (Expression) $3);
305         }
306         ;
307
308 RelationalExpr
309         : AdditiveExpr 
310         | RelationalExpr LT AdditiveExpr 
311         {
312                 $$ = new ExprLT ((Expression) $1, (Expression) $3);
313         }
314         | RelationalExpr GT AdditiveExpr 
315         {
316                 $$ = new ExprGT ((Expression) $1, (Expression) $3);
317         }
318         | RelationalExpr LE AdditiveExpr 
319         {
320                 $$ = new ExprLE ((Expression) $1, (Expression) $3);
321         }
322         | RelationalExpr GE AdditiveExpr 
323         {
324                 $$ = new ExprGE ((Expression) $1, (Expression) $3);
325         }
326         ;
327
328 AdditiveExpr
329         : MultiplicativeExpr 
330         | AdditiveExpr PLUS MultiplicativeExpr
331         {
332                 $$ = new ExprPLUS ((Expression) $1, (Expression) $3);
333         }
334         | AdditiveExpr MINUS MultiplicativeExpr
335         {
336                 $$ = new ExprMINUS ((Expression) $1, (Expression) $3);
337         }
338         ;
339
340 MultiplicativeExpr
341         : UnaryExpr 
342         | MultiplicativeExpr MULTIPLY UnaryExpr 
343         {
344                 $$ = new ExprMULT ((Expression) $1, (Expression) $3);
345         }
346         | MultiplicativeExpr DIV UnaryExpr
347         {
348                 $$ = new ExprDIV ((Expression) $1, (Expression) $3);
349         }
350         | MultiplicativeExpr MOD UnaryExpr
351         {
352                 $$ = new ExprMOD ((Expression) $1, (Expression) $3);
353         }
354         ;
355
356 UnaryExpr
357         : UnionExpr 
358         | MINUS UnaryExpr 
359         {
360                 $$ = new ExprNEG ((Expression) $2);
361         }
362         ;
363
364 UnionExpr
365         : PathExpr 
366         | UnionExpr BAR PathExpr
367         {
368                 $$ = new ExprUNION ((Expression) $1, (Expression) $3);
369         }
370         ;
371
372 PathExpr
373         : LocationPath
374         | FilterExpr
375         | FilterExpr SLASH RelativeLocationPath
376         {
377                 $$ = new ExprSLASH ((Expression) $1, (NodeSet) $3);
378         }
379         | FilterExpr SLASH2 RelativeLocationPath
380         {
381                 $$ = new ExprSLASH2 ((Expression) $1, (NodeSet) $3);
382         }
383         ;
384
385 LocationPath
386         : RelativeLocationPath
387         | AbsoluteLocationPath
388         ;
389
390 AbsoluteLocationPath
391         : SLASH
392         {
393                 $$ = new ExprRoot ();
394         }
395         | SLASH RelativeLocationPath
396         {
397                 $$ = new ExprSLASH (new ExprRoot (), (NodeSet) $2);
398         }
399         | SLASH2 RelativeLocationPath
400         {
401                 $$ = new ExprSLASH2 (new ExprRoot (), (NodeSet) $2);
402         }
403         ;
404
405 RelativeLocationPath
406         : Step
407         | RelativeLocationPath SLASH Step 
408         {
409                 $$ = new ExprSLASH ((NodeSet) $1, (NodeSet) $3);
410         }
411         | RelativeLocationPath SLASH2 Step 
412         {
413                 $$ = new ExprSLASH2 ((NodeSet) $1, (NodeSet) $3);
414         }
415         ;
416
417 Step
418         : AxisSpecifier NodeTest Predicates
419         {
420                 $$ = CreateNodeTest ((Axes) $1, $2, (ArrayList) $3);
421         }
422         | AbbreviatedStep
423         ;
424
425 NodeTest // QName, XPathNodeType or string
426         : NameTest
427         | NodeType PAREN_OPEN PAREN_CLOSE
428         {
429                 $$ = (XPathNodeType) $1;
430         }
431         | PROCESSING_INSTRUCTION PAREN_OPEN OptionalLiteral PAREN_CLOSE
432         {
433                 $$ = (string) $3;
434         }
435         ;
436
437 NameTest
438         : ASTERISK
439         {
440                 $$ = XmlQualifiedName.Empty;
441         }
442         | QName // token QName also contains "blah:*"
443         ;
444
445 AbbreviatedStep
446         : DOT
447         {
448                 $$ = new NodeTypeTest (Axes.Self, XPathNodeType.All);
449         }
450         | DOT2
451         {
452                 $$ = new NodeTypeTest (Axes.Parent, XPathNodeType.All);
453         }
454         ;
455
456 Predicates
457         : /* empty */
458         {
459                 $$ = null;
460         }
461         | Predicates Predicate
462         {
463                 ArrayList al = (ArrayList) $1;
464                 if (al == null)
465                         al = new ArrayList ();
466                 al.Add ($2);
467                 $$ = al;
468         }
469         ;
470
471 AxisSpecifier
472         : AxisName COLON2
473         {
474                 $$ = $1;
475         }
476         | AbbreviatedAxisSpecifier
477         ;
478
479 AbbreviatedAxisSpecifier
480         : /* empty */
481         {
482                 $$ = Axes.Child;
483         }
484         | AT
485         {
486                 $$ = Axes.Attribute;
487         }
488         ;
489
490 NodeType
491         : COMMENT                                       { $$ = XPathNodeType.Comment; }
492         | TEXT                                          { $$ = XPathNodeType.Text; }
493         | PROCESSING_INSTRUCTION        { $$ = XPathNodeType.ProcessingInstruction; }
494         | NODE                                          { $$ = XPathNodeType.All; }
495         ;
496
497
498 FilterExpr
499         : PrimaryExpr 
500         | FilterExpr Predicate 
501         {
502                 $$ = new ExprFilter ((Expression) $1, (Expression) $2);
503         }
504         ;
505
506 PrimaryExpr
507         : DOLLAR QName
508         {
509                 Expression ret = null;
510                 if (Context != null)
511                         ret = Context.TryGetVariable (((XmlQualifiedName) $2).ToString ());
512                 
513                 if (ret == null)
514                         ret = new ExprVariable ((XmlQualifiedName) $2, Context);
515                         
516                 $$ = ret;
517         }
518         | PAREN_OPEN Expr PAREN_CLOSE
519         {
520                 $$ = new ExprParens ((Expression) $2);
521         }
522         | LITERAL
523         {
524                 $$ = new ExprLiteral ((String) $1);
525         }
526         | NUMBER
527         {
528                 $$ = new ExprNumber ((double) $1);
529         }
530         | FunctionCall
531         ;
532
533 FunctionCall
534         : FUNCTION_NAME PAREN_OPEN OptionalArgumentList PAREN_CLOSE
535         {
536                 Expression ret = null;
537                 if (Context != null)
538                         ret = Context.TryGetFunction ((XmlQualifiedName) $1, (FunctionArguments) $3);
539                 if (ret == null)
540                         ret = ExprFunctionCall.Factory ((XmlQualifiedName) $1, (FunctionArguments) $3, Context);
541                 
542                 $$ = ret;
543         }
544         ;
545
546 OptionalArgumentList
547         : /* empty */
548         | Expr OptionalArgumentListTail
549         {
550                 $$ = new FunctionArguments ((Expression) $1, (FunctionArguments) $2);
551         }
552         ;
553
554 OptionalArgumentListTail
555         : /* empty */
556         | COMMA Expr OptionalArgumentListTail
557         {
558                 $$ = new FunctionArguments ((Expression) $2, (FunctionArguments) $3);
559         }
560         ;
561
562 Predicate
563         : BRACKET_OPEN Expr BRACKET_CLOSE
564         {
565                 $$ = $2;
566         }
567         ;
568
569 AxisName
570         : ANCESTOR                              { $$ = Axes.Ancestor; }
571         | ANCESTOR_OR_SELF              { $$ = Axes.AncestorOrSelf; }
572         | ATTRIBUTE                             { $$ = Axes.Attribute; }
573         | CHILD                                 { $$ = Axes.Child; }
574         | DESCENDANT                    { $$ = Axes.Descendant; }
575         | DESCENDANT_OR_SELF    { $$ = Axes.DescendantOrSelf; }
576         | FOLLOWING                             { $$ = Axes.Following; }
577         | FOLLOWING_SIBLING             { $$ = Axes.FollowingSibling; }
578         | NAMESPACE                             { $$ = Axes.Namespace; }
579         | PARENT                                { $$ = Axes.Parent; }
580         | PRECEDING                             { $$ = Axes.Preceding; }
581         | PRECEDING_SIBLING             { $$ = Axes.PrecedingSibling; }
582         | SELF                                  { $$ = Axes.Self; }
583         ;
584
585 OptionalLiteral
586         : /* empty */
587         | LITERAL
588         ;
589
590 %%
591         }