xref: /reactos/dll/win32/msxml3/xslpattern.y (revision 40462c92)
1 /*
2  *    XSLPattern parser (XSLPattern => XPath)
3  *
4  * Copyright 2010 Adam Martinson for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 %{
22 #include "config.h"
23 #include "wine/port.h"
24 
25 #ifdef HAVE_LIBXML2
26 #include "xslpattern.h"
27 #include <libxml/xpathInternals.h>
28 #include "wine/debug.h"
29 
30 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
31 
32 
33 static const xmlChar NameTest_mod_pre[] = "*[name()='";
34 static const xmlChar NameTest_mod_post[] = "']";
35 
36 #define U(str) BAD_CAST str
37 
38 static inline BOOL is_literal(xmlChar const* tok)
39 {
40     return (tok && tok[0] && tok[1] &&
41             tok[0]== tok[xmlStrlen(tok)-1] &&
42             (tok[0] == '\'' || tok[0] == '"'));
43 }
44 
45 static void xslpattern_error(parser_param* param, void const* scanner, char const* msg)
46 {
47     FIXME("%s:\n"
48           "  param {\n"
49           "    yyscanner=%p\n"
50           "    ctx=%p\n"
51           "    in=\"%s\"\n"
52           "    pos=%i\n"
53           "    len=%i\n"
54           "    out=\"%s\"\n"
55           "    err=%i\n"
56           "  }\n"
57           "  scanner=%p\n",
58           msg, param->yyscanner, param->ctx, param->in, param->pos,
59           param->len, param->out, ++param->err, scanner);
60 }
61 
62 %}
63 
64 %token TOK_Parent TOK_Self TOK_DblFSlash TOK_FSlash TOK_Axis TOK_Colon
65 %token TOK_OpAnd TOK_OpOr TOK_OpNot
66 %token TOK_OpEq TOK_OpIEq TOK_OpNEq TOK_OpINEq
67 %token TOK_OpLt TOK_OpILt TOK_OpGt TOK_OpIGt TOK_OpLEq TOK_OpILEq TOK_OpGEq TOK_OpIGEq
68 %token TOK_OpAll TOK_OpAny
69 %token TOK_NCName TOK_Literal TOK_Number
70 
71 %start XSLPattern
72 
73 %pure-parser
74 %parse-param {parser_param* p}
75 %parse-param {void* scanner}
76 %lex-param {yyscan_t* scanner}
77 
78 %left TOK_OpAnd TOK_OpOr
79 %left TOK_OpEq TOK_OpIEq TOK_OpNEq TOK_OpINEq
80 %left TOK_OpLt TOK_OpILt TOK_OpGt TOK_OpIGt TOK_OpLEq TOK_OpILEq TOK_OpGEq TOK_OpIGEq
81 
82 %expect 14
83 
84 %%
85 
86     XSLPattern              : Expr
87                             {
88                                 p->out = $1;
89                             }
90     ;
91 
92 /* Mostly verbatim from the w3c XML Namespaces standard.
93  * <http://www.w3.org/TR/REC-xml-names/> */
94 
95     /* [4] Qualified Names */
96     QName                   : PrefixedName
97                             | UnprefixedName
98     ;
99     PrefixedName            : TOK_NCName TOK_Colon TOK_NCName
100                             {
101                                 TRACE("Got PrefixedName: \"%s:%s\"\n", $1, $3);
102                                 $$=$1;
103                                 $$=xmlStrcat($$,U(":"));
104                                 $$=xmlStrcat($$,$3);
105                                 xmlFree($3);
106                             }
107     ;
108     UnprefixedName          : TOK_NCName
109                             {
110                                 TRACE("Got UnprefixedName: \"%s\"\n", $1);
111                                 $$=$1;
112                             }
113     ;
114 
115 /* Based on the w3c XPath standard, adapted where needed.
116  * <http://www.w3.org/TR/xpath/> */
117 
118     /* [2] Location Paths */
119     LocationPath            : RelativeLocationPath
120                             | AbsoluteLocationPath
121     ;
122     AbsoluteLocationPath    : TOK_FSlash RelativeLocationPath
123                             {
124                                 TRACE("Got AbsoluteLocationPath: \"/%s\"\n", $2);
125                                 $$=xmlStrdup(U("/"));
126                                 $$=xmlStrcat($$,$2);
127                                 xmlFree($2);
128                             }
129                             | TOK_FSlash
130                             {
131                                 TRACE("Got AbsoluteLocationPath: \"/\"\n");
132                                 $$=xmlStrdup(U("/"));
133                             }
134                             | AbbreviatedAbsoluteLocationPath
135     ;
136     RelativeLocationPath    : Step
137                             | RelativeLocationPath TOK_FSlash Step
138                             {
139                                 TRACE("Got RelativeLocationPath: \"%s/%s\"\n", $1, $3);
140                                 $$=$1;
141                                 $$=xmlStrcat($$,U("/"));
142                                 $$=xmlStrcat($$,$3);
143                                 xmlFree($3);
144                             }
145                             | AbbreviatedRelativeLocationPath
146     ;
147     /* [2.1] Location Steps */
148     Step                    : AxisSpecifier NodeTest Predicates
149                             {
150                                 TRACE("Got Step: \"%s%s%s\"\n", $1, $2, $3);
151                                 $$=$1;
152                                 $$=xmlStrcat($$,$2);
153                                 xmlFree($2);
154                                 $$=xmlStrcat($$,$3);
155                                 xmlFree($3);
156                             }
157                             | NodeTest Predicates
158                             {
159                                 TRACE("Got Step: \"%s%s\"\n", $1, $2);
160                                 $$=$1;
161                                 $$=xmlStrcat($$,$2);
162                                 xmlFree($2);
163                             }
164                             | AxisSpecifier NodeTest
165                             {
166                                 TRACE("Got Step: \"%s%s\"\n", $1, $2);
167                                 $$=$1;
168                                 $$=xmlStrcat($$,$2);
169                                 xmlFree($2);
170                             }
171                             | NodeTest
172                             | Attribute
173                             | AbbreviatedStep
174     ;
175     AxisSpecifier           : TOK_NCName TOK_Axis
176                             {
177                                 TRACE("Got AxisSpecifier: \"%s::\"\n", $1);
178                                 $$=$1;
179                                 $$=xmlStrcat($$,U("::"));
180                             }
181     ;
182     Attribute               : '@' QName
183                             {
184                                 TRACE("Got Attribute: \"@%s\"\n", $2);
185                                 $$=xmlStrdup(U("@"));
186                                 $$=xmlStrcat($$,$2);
187                                 xmlFree($2);
188                             }
189                             | '@' '*'
190                             {
191                                 TRACE("Got All attributes pattern: \"@*\"\n");
192                                 $$=xmlStrdup(U("@*"));
193                             }
194     ;
195 
196     /* [2.3] Node Tests */
197     NodeTest                : NameTest
198                             | FunctionCall
199     ;
200     NameTest                : '*'
201                             {
202                                 TRACE("Got NameTest: \"*\"\n");
203                                 $$=xmlStrdup(U("*"));
204                             }
205                             | TOK_NCName TOK_Colon '*'
206                             {
207                                 TRACE("Got NameTest: \"%s:*\"\n", $1);
208                                 $$=$1;
209                                 $$=xmlStrcat($$,U(":*"));
210                             }
211                             | TOK_NCName TOK_Colon TOK_NCName
212                             { /* PrefixedName */
213                                 xmlChar const* registeredNsURI = xmlXPathNsLookup(p->ctx, $1);
214                                 TRACE("Got PrefixedName: \"%s:%s\"\n", $1, $3);
215 
216                                 if (registeredNsURI)
217                                     $$=xmlStrdup(U(""));
218                                 else
219                                     $$=xmlStrdup(NameTest_mod_pre);
220 
221                                 $$=xmlStrcat($$,$1);
222                                 xmlFree($1);
223                                 $$=xmlStrcat($$,U(":"));
224                                 $$=xmlStrcat($$,$3);
225                                 xmlFree($3);
226 
227                                 if (!registeredNsURI)
228                                     $$=xmlStrcat($$,NameTest_mod_post);
229                             }
230                             | UnprefixedName
231                             {
232                                 $$=xmlStrdup(NameTest_mod_pre);
233                                 $$=xmlStrcat($$,$1);
234                                 xmlFree($1);
235                                 $$=xmlStrcat($$,NameTest_mod_post);
236                             }
237     /* [2.4] Predicates */
238     Predicates              : Predicates Predicate
239                             {
240                                 $$=$1;
241                                 $$=xmlStrcat($$,$2);
242                                 xmlFree($2);
243                             }
244                             | Predicate
245     ;
246     Predicate               : '[' PredicateExpr ']'
247                             {
248                                 TRACE("Got Predicate: \"[%s]\"\n", $2);
249                                 $$=xmlStrdup(U("["));
250                                 $$=xmlStrcat($$,$2);
251                                 xmlFree($2);
252                                 $$=xmlStrcat($$,U("]"));
253                             }
254     ;
255     PredicateExpr           : TOK_Number
256                             {
257                                 $$=xmlStrdup(U("index()="));
258                                 $$=xmlStrcat($$,$1);
259                                 xmlFree($1);
260                             }
261                             | BoolExpr
262                             | Attribute
263                             | TOK_NCName
264     ;
265     /* [2.5] Abbreviated Syntax */
266     AbbreviatedAbsoluteLocationPath : TOK_DblFSlash RelativeLocationPath
267                             {
268                                 TRACE("Got AbbreviatedAbsoluteLocationPath: \"//%s\"\n", $2);
269                                 $$=xmlStrdup(U("//"));
270                                 $$=xmlStrcat($$,$2);
271                                 xmlFree($2);
272                             }
273     ;
274     AbbreviatedRelativeLocationPath : RelativeLocationPath TOK_DblFSlash Step
275                             {
276                                 TRACE("Got AbbreviatedRelativeLocationPath: \"%s//%s\"\n", $1, $3);
277                                 $$=$1;
278                                 $$=xmlStrcat($$,U("//"));
279                                 $$=xmlStrcat($$,$3);
280                                 xmlFree($3);
281                             }
282     ;
283     AbbreviatedStep         : TOK_Parent
284                             {
285                                 TRACE("Got AbbreviatedStep: \"..\"\n");
286                                 $$=xmlStrdup(U(".."));
287                             }
288                             | TOK_Self
289                             {
290                                 TRACE("Got AbbreviatedStep: \".\"\n");
291                                 $$=xmlStrdup(U("."));
292                             }
293     ;
294 
295     /* [3] Expressions */
296     /* [3.1] Basics */
297     Expr                    : OrExpr
298     ;
299     BoolExpr                : FunctionCall
300                             | BoolUnaryExpr
301                             | BoolRelationalExpr
302                             | BoolEqualityExpr
303                             | BoolAndExpr
304                             | BoolOrExpr
305     ;
306     PrimaryExpr             : '(' Expr ')'
307                             {
308                                 TRACE("Got PrimaryExpr: \"(%s)\"\n", $1);
309                                 $$=xmlStrdup(U("("));
310                                 $$=xmlStrcat($$,$2);
311                                 xmlFree($2);
312                                 $$=xmlStrcat($$,U(")"));
313                             }
314                             | PathExpr '!' FunctionCall
315                             {
316                                 TRACE("Got PrimaryExpr: \"%s!%s\"\n", $1, $3);
317                                 $$=$1;
318                                 $$=xmlStrcat($$,U("/"));
319                                 $$=xmlStrcat($$,$3);
320                                 xmlFree($3);
321                             }
322                             | TOK_Literal
323                             | TOK_Number
324     ;
325     /* [3.2] Function Calls */
326     FunctionCall            : QName '(' Arguments ')'
327                             {
328                                 TRACE("Got FunctionCall: \"%s(%s)\"\n", $1, $3);
329                                 if (xmlStrEqual($1,U("ancestor")))
330                                 {
331                                     $$=$1;
332                                     $$=xmlStrcat($$,U("::"));
333                                     $$=xmlStrcat($$,$3);
334                                     xmlFree($3);
335                                 }
336                                 else if (xmlStrEqual($1,U("attribute")))
337                                 {
338                                     if (is_literal($3))
339                                     {
340                                         $$=xmlStrdup(U("@*[name()="));
341                                         xmlFree($1);
342                                         $$=xmlStrcat($$,$3);
343                                         xmlFree($3);
344                                         $$=xmlStrcat($$,U("]"));
345                                     }
346                                     else
347                                     {
348                                         /* XML_XPATH_INVALID_TYPE */
349                                         $$=xmlStrdup(U("error(1211, 'Error: attribute("));
350                                         xmlFree($1);
351                                         $$=xmlStrcat($$,$3);
352                                         xmlFree($3);
353                                         $$=xmlStrcat($$,U("): invalid argument')"));
354                                     }
355                                 }
356                                 else if (xmlStrEqual($1,U("element")))
357                                 {
358                                     if (is_literal($3))
359                                     {
360                                         $$=xmlStrdup(U("node()[nodeType()=1][name()="));
361                                         xmlFree($1);
362                                         $$=xmlStrcat($$,$3);
363                                         xmlFree($3);
364                                         $$=xmlStrcat($$,U("]"));
365                                     }
366                                     else
367                                     {
368                                         /* XML_XPATH_INVALID_TYPE */
369                                         $$=xmlStrdup(U("error(1211, 'Error: element("));
370                                         xmlFree($1);
371                                         $$=xmlStrcat($$,$3);
372                                         xmlFree($3);
373                                         $$=xmlStrcat($$,U("): invalid argument')"));
374                                     }
375                                 }
376                                 else
377                                 {
378                                     $$=$1;
379                                     $$=xmlStrcat($$,U("("));
380                                     $$=xmlStrcat($$,$3);
381                                     xmlFree($3);
382                                     $$=xmlStrcat($$,U(")"));
383                                 }
384                             }
385                             | QName '(' ')'
386                             {
387                                 TRACE("Got FunctionCall: \"%s()\"\n", $1);
388                                 /* comment() & node() work the same in XPath */
389                                 if (xmlStrEqual($1,U("attribute")))
390                                 {
391                                     $$=xmlStrdup(U("@*"));
392                                     xmlFree($1);
393                                 }
394                                 else if (xmlStrEqual($1,U("element")))
395                                 {
396                                     $$=xmlStrdup(U("node()[nodeType()=1]"));
397                                     xmlFree($1);
398                                 }
399                                 else if (xmlStrEqual($1,U("pi")))
400                                 {
401                                     $$=xmlStrdup(U("processing-instruction()"));
402                                     xmlFree($1);
403                                 }
404                                 else if (xmlStrEqual($1,U("textnode")))
405                                 {
406                                     $$=xmlStrdup(U("text()"));
407                                     xmlFree($1);
408                                 }
409                                 else
410                                 {
411                                     $$=$1;
412                                     $$=xmlStrcat($$,U("()"));
413                                 }
414                             }
415     ;
416     Arguments               : Argument ',' Arguments
417                             {
418                                 $$=$1;
419                                 $$=xmlStrcat($$,U(","));
420                                 $$=xmlStrcat($$,$3);
421                                 xmlFree($3);
422                             }
423                             | Argument
424     ;
425     Argument                : Expr
426     ;
427     /* [3.3] Node-sets */
428     UnionExpr               : PathExpr
429                             | UnionExpr '|' PathExpr
430                             {
431                                 TRACE("Got UnionExpr: \"%s|%s\"\n", $1, $3);
432                                 $$=$1;
433                                 $$=xmlStrcat($$,U("|"));
434                                 $$=xmlStrcat($$,$3);
435                                 xmlFree($3);
436                             }
437     ;
438     PathExpr                : LocationPath
439                             | FilterExpr TOK_FSlash RelativeLocationPath
440                             {
441                                 TRACE("Got PathExpr: \"%s/%s\"\n", $1, $3);
442                                 $$=$1;
443                                 $$=xmlStrcat($$,U("/"));
444                                 $$=xmlStrcat($$,$3);
445                                 xmlFree($3);
446                             }
447                             | FilterExpr TOK_DblFSlash RelativeLocationPath
448                             {
449                                 TRACE("Got PathExpr: \"%s//%s\"\n", $1, $3);
450                                 $$=$1;
451                                 $$=xmlStrcat($$,U("//"));
452                                 $$=xmlStrcat($$,$3);
453                                 xmlFree($3);
454                             }
455                             | FilterExpr
456     ;
457     FilterExpr              : PrimaryExpr
458                             | FilterExpr Predicate
459                             {
460                                 TRACE("Got FilterExpr: \"%s%s\"\n", $1, $2);
461                                 $$=$1;
462                                 $$=xmlStrcat($$,$2);
463                                 xmlFree($2);
464                             }
465     ;
466     /* [3.4] Booleans */
467     OrExpr                  : AndExpr
468                             | BoolOrExpr
469     ;
470     BoolOrExpr              : OrExpr TOK_OpOr AndExpr
471                             {
472                                 TRACE("Got OrExpr: \"%s $or$ %s\"\n", $1, $3);
473                                 $$=$1;
474                                 $$=xmlStrcat($$,U(" or "));
475                                 $$=xmlStrcat($$,$3);
476                                 xmlFree($3);
477                             }
478     ;
479     AndExpr                 : EqualityExpr
480                             | BoolAndExpr
481     ;
482     BoolAndExpr             : AndExpr TOK_OpAnd EqualityExpr
483                             {
484                                 TRACE("Got AndExpr: \"%s $and$ %s\"\n", $1, $3);
485                                 $$=$1;
486                                 $$=xmlStrcat($$,U(" and "));
487                                 $$=xmlStrcat($$,$3);
488                                 xmlFree($3);
489                             }
490     ;
491     EqualityExpr            : RelationalExpr
492                             | BoolEqualityExpr
493     ;
494     BoolEqualityExpr        : EqualityExpr TOK_OpEq RelationalExpr
495                             {
496                                 TRACE("Got EqualityExpr: \"%s $eq$ %s\"\n", $1, $3);
497                                 $$=$1;
498                                 $$=xmlStrcat($$,U("="));
499                                 $$=xmlStrcat($$,$3);
500                                 xmlFree($3);
501                             }
502                             | EqualityExpr TOK_OpIEq RelationalExpr
503                             {
504                                 TRACE("Got EqualityExpr: \"%s $ieq$ %s\"\n", $1, $3);
505                                 $$=xmlStrdup(U("OP_IEq("));
506                                 $$=xmlStrcat($$,$1);
507                                 xmlFree($1);
508                                 $$=xmlStrcat($$,U(","));
509                                 $$=xmlStrcat($$,$3);
510                                 xmlFree($3);
511                                 $$=xmlStrcat($$,U(")"));
512                             }
513                             | EqualityExpr TOK_OpNEq RelationalExpr
514                             {
515                                 TRACE("Got EqualityExpr: \"%s $ne$ %s\"\n", $1, $3);
516                                 $$=$1;
517                                 $$=xmlStrcat($$,U("!="));
518                                 $$=xmlStrcat($$,$3);
519                                 xmlFree($3);
520                             }
521                             | EqualityExpr TOK_OpINEq RelationalExpr
522                             {
523                                 TRACE("Got EqualityExpr: \"%s $ine$ %s\"\n", $1, $3);
524                                 $$=xmlStrdup(U("OP_INEq("));
525                                 $$=xmlStrcat($$,$1);
526                                 xmlFree($1);
527                                 $$=xmlStrcat($$,U(","));
528                                 $$=xmlStrcat($$,$3);
529                                 xmlFree($3);
530                                 $$=xmlStrcat($$,U(")"));
531                             }
532     ;
533     RelationalExpr          : UnaryExpr
534                             | BoolRelationalExpr
535     ;
536     BoolRelationalExpr      : RelationalExpr TOK_OpLt UnaryExpr
537                             {
538                                 TRACE("Got RelationalExpr: \"%s $lt$ %s\"\n", $1, $3);
539                                 $$=$1;
540                                 $$=xmlStrcat($$,U("<"));
541                                 $$=xmlStrcat($$,$3);
542                                 xmlFree($3);
543                             }
544                             | RelationalExpr TOK_OpILt UnaryExpr
545                             {
546                                 TRACE("Got RelationalExpr: \"%s $ilt$ %s\"\n", $1, $3);
547                                 $$=xmlStrdup(U("OP_ILt("));
548                                 $$=xmlStrcat($$,$1);
549                                 xmlFree($1);
550                                 $$=xmlStrcat($$,U(","));
551                                 $$=xmlStrcat($$,$3);
552                                 xmlFree($3);
553                                 $$=xmlStrcat($$,U(")"));
554                             }
555                             | RelationalExpr TOK_OpGt UnaryExpr
556                             {
557                                 TRACE("Got RelationalExpr: \"%s $gt$ %s\"\n", $1, $3);
558                                 $$=$1;
559                                 $$=xmlStrcat($$,U(">"));
560                                 $$=xmlStrcat($$,$3);
561                                 xmlFree($3);
562                             }
563                             | RelationalExpr TOK_OpIGt UnaryExpr
564                             {
565                                 TRACE("Got RelationalExpr: \"%s $igt$ %s\"\n", $1, $3);
566                                 $$=xmlStrdup(U("OP_IGt("));
567                                 $$=xmlStrcat($$,$1);
568                                 xmlFree($1);
569                                 $$=xmlStrcat($$,U(","));
570                                 $$=xmlStrcat($$,$3);
571                                 xmlFree($3);
572                                 $$=xmlStrcat($$,U(")"));
573                             }
574                             | RelationalExpr TOK_OpLEq UnaryExpr
575                             {
576                                 TRACE("Got RelationalExpr: \"%s $le$ %s\"\n", $1, $3);
577                                 $$=$1;
578                                 $$=xmlStrcat($$,U("<="));
579                                 $$=xmlStrcat($$,$3);
580                                 xmlFree($3);
581                             }
582                             | RelationalExpr TOK_OpILEq UnaryExpr
583                             {
584                                 TRACE("Got RelationalExpr: \"%s $ile$ %s\"\n", $1, $3);
585                                 $$=xmlStrdup(U("OP_ILEq("));
586                                 $$=xmlStrcat($$,$1);
587                                 xmlFree($1);
588                                 $$=xmlStrcat($$,U(","));
589                                 $$=xmlStrcat($$,$3);
590                                 xmlFree($3);
591                                 $$=xmlStrcat($$,U(")"));
592                             }
593                             | RelationalExpr TOK_OpGEq UnaryExpr
594                             {
595                                 TRACE("Got RelationalExpr: \"%s $ge$ %s\"\n", $1, $3);
596                                 $$=$1;
597                                 $$=xmlStrcat($$,U(">="));
598                                 $$=xmlStrcat($$,$3);
599                                 xmlFree($3);
600                             }
601                             | RelationalExpr TOK_OpIGEq UnaryExpr
602                             {
603                                 TRACE("Got RelationalExpr: \"%s $ige$ %s\"\n", $1, $3);
604                                 $$=xmlStrdup(U("OP_IGEq("));
605                                 $$=xmlStrcat($$,$1);
606                                 xmlFree($1);
607                                 $$=xmlStrcat($$,U(","));
608                                 $$=xmlStrcat($$,$3);
609                                 xmlFree($3);
610                                 $$=xmlStrcat($$,U(")"));
611                             }
612     ;
613 
614     /* [3.5] Numbers */
615     UnaryExpr               : UnionExpr
616                             | BoolUnaryExpr
617     ;
618     BoolUnaryExpr           : TOK_OpNot UnaryExpr
619                             {
620                                 TRACE("Got UnaryExpr: \"$not$ %s\"\n", $2);
621                                 $$=xmlStrdup(U(" not("));
622                                 $$=xmlStrcat($$,$2);
623                                 xmlFree($2);
624                                 $$=xmlStrcat($$,U(")"));
625                             }
626                             | TOK_OpAny Expr
627                             {
628                                 TRACE("Got UnaryExpr: \"$any$ %s\"\n", $2);
629                                 $$=xmlStrdup(U("boolean("));
630                                 $$=xmlStrcat($$,$2);
631                                 xmlFree($2);
632                                 $$=xmlStrcat($$,U(")"));
633                             }
634                             | TOK_OpAll AllExpr
635                             {
636                                 TRACE("Got UnaryExpr: \"$all$ %s\"\n", $2);
637                                 $$=xmlStrdup(U("not("));
638                                 $$=xmlStrcat($$,$2);
639                                 xmlFree($2);
640                                 $$=xmlStrcat($$,U(")"));
641                             }
642                             | TOK_OpAll
643                             {
644                                 FIXME("Unrecognized $all$ expression - ignoring\n");
645                                 $$=xmlStrdup(U(""));
646                             }
647     ;
648     AllExpr                 : PathExpr TOK_OpEq PathExpr
649                             {
650                                 $$=$1;
651                                 $$=xmlStrcat($$,U("!="));
652                                 $$=xmlStrcat($$,$3);
653                                 xmlFree($3);
654                             }
655                             | PathExpr TOK_OpNEq PathExpr
656                             {
657                                 $$=$1;
658                                 $$=xmlStrcat($$,U("="));
659                                 $$=xmlStrcat($$,$3);
660                                 xmlFree($3);
661                             }
662                             | PathExpr TOK_OpLt PathExpr
663                             {
664                                 $$=$1;
665                                 $$=xmlStrcat($$,U(">="));
666                                 $$=xmlStrcat($$,$3);
667                                 xmlFree($3);
668                             }
669                             | PathExpr TOK_OpLEq PathExpr
670                             {
671                                 $$=$1;
672                                 $$=xmlStrcat($$,U(">"));
673                                 $$=xmlStrcat($$,$3);
674                                 xmlFree($3);
675                             }
676                             | PathExpr TOK_OpGt PathExpr
677                             {
678                                 $$=$1;
679                                 $$=xmlStrcat($$,U("<="));
680                                 $$=xmlStrcat($$,$3);
681                                 xmlFree($3);
682                             }
683                             | PathExpr TOK_OpGEq PathExpr
684                             {
685                                 $$=$1;
686                                 $$=xmlStrcat($$,U("<"));
687                                 $$=xmlStrcat($$,$3);
688                                 xmlFree($3);
689                             }
690                             | PathExpr TOK_OpIEq PathExpr
691                             {
692                                 $$=xmlStrdup(U("OP_INEq("));
693                                 $$=xmlStrcat($$,$1);
694                                 xmlFree($1);
695                                 $$=xmlStrcat($$,U(","));
696                                 $$=xmlStrcat($$,$3);
697                                 xmlFree($3);
698                                 $$=xmlStrcat($$,U(")"));
699                             }
700                             | PathExpr TOK_OpINEq PathExpr
701                             {
702                                 $$=xmlStrdup(U("OP_IEq("));
703                                 $$=xmlStrcat($$,$1);
704                                 xmlFree($1);
705                                 $$=xmlStrcat($$,U(","));
706                                 $$=xmlStrcat($$,$3);
707                                 xmlFree($3);
708                                 $$=xmlStrcat($$,U(")"));
709                             }
710                             | PathExpr TOK_OpILt PathExpr
711                             {
712                                 $$=xmlStrdup(U("OP_IGEq("));
713                                 $$=xmlStrcat($$,$1);
714                                 xmlFree($1);
715                                 $$=xmlStrcat($$,U(","));
716                                 $$=xmlStrcat($$,$3);
717                                 xmlFree($3);
718                                 $$=xmlStrcat($$,U(")"));
719                             }
720                             | PathExpr TOK_OpILEq PathExpr
721                             {
722                                 $$=xmlStrdup(U("OP_IGt("));
723                                 $$=xmlStrcat($$,$1);
724                                 xmlFree($1);
725                                 $$=xmlStrcat($$,U(","));
726                                 $$=xmlStrcat($$,$3);
727                                 xmlFree($3);
728                                 $$=xmlStrcat($$,U(")"));
729                             }
730                             | PathExpr TOK_OpIGt PathExpr
731                             {
732                                 $$=xmlStrdup(U("OP_ILEq("));
733                                 $$=xmlStrcat($$,$1);
734                                 xmlFree($1);
735                                 $$=xmlStrcat($$,U(","));
736                                 $$=xmlStrcat($$,$3);
737                                 xmlFree($3);
738                                 $$=xmlStrcat($$,U(")"));
739                             }
740                             | PathExpr TOK_OpIGEq PathExpr
741                             {
742                                 $$=xmlStrdup(U("OP_ILt("));
743                                 $$=xmlStrcat($$,$1);
744                                 xmlFree($1);
745                                 $$=xmlStrcat($$,U(","));
746                                 $$=xmlStrcat($$,$3);
747                                 xmlFree($3);
748                                 $$=xmlStrcat($$,U(")"));
749                             }
750     ;
751 
752 %%
753 
754 #endif  /* HAVE_LIBXML2 */
755