urlmon: Use wine lists to store namespaces and MIME filters.
[wine] / dlls / msxml3 / xslpattern.y
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     /* [2.3] Node Tests */
192     NodeTest                : NameTest
193                             | FunctionCall
194     ;
195     NameTest                : '*'
196                             {
197                                 TRACE("Got NameTest: \"*\"\n");
198                                 $$=xmlStrdup(U("*"));
199                             }
200                             | TOK_NCName TOK_Colon '*'
201                             {
202                                 TRACE("Got NameTest: \"%s:*\"\n", $1);
203                                 $$=$1;
204                                 $$=xmlStrcat($$,U(":*"));
205                             }
206                             | TOK_NCName TOK_Colon TOK_NCName
207                             { /* PrefixedName */
208                                 xmlChar const* registeredNsURI = xmlXPathNsLookup(p->ctx, $1);
209                                 TRACE("Got PrefixedName: \"%s:%s\"\n", $1, $3);
210
211                                 if (registeredNsURI)
212                                     $$=xmlStrdup(U(""));
213                                 else
214                                     $$=xmlStrdup(NameTest_mod_pre);
215
216                                 $$=xmlStrcat($$,$1);
217                                 xmlFree($1);
218                                 $$=xmlStrcat($$,U(":"));
219                                 $$=xmlStrcat($$,$3);
220                                 xmlFree($3);
221
222                                 if (!registeredNsURI)
223                                     $$=xmlStrcat($$,NameTest_mod_post);
224                             }
225                             | UnprefixedName
226                             {
227                                 $$=xmlStrdup(NameTest_mod_pre);
228                                 $$=xmlStrcat($$,$1);
229                                 xmlFree($1);
230                                 $$=xmlStrcat($$,NameTest_mod_post);
231                             }
232     /* [2.4] Predicates */
233     Predicates              : Predicates Predicate
234                             {
235                                 $$=$1;
236                                 $$=xmlStrcat($$,$2);
237                                 xmlFree($2);
238                             }
239                             | Predicate
240     ;
241     Predicate               : '[' PredicateExpr ']'
242                             {
243                                 TRACE("Got Predicate: \"[%s]\"\n", $2);
244                                 $$=xmlStrdup(U("["));
245                                 $$=xmlStrcat($$,$2);
246                                 xmlFree($2);
247                                 $$=xmlStrcat($$,U("]"));
248                             }
249     ;
250     PredicateExpr           : TOK_Number
251                             {
252                                 $$=xmlStrdup(U("index()="));
253                                 $$=xmlStrcat($$,$1);
254                                 xmlFree($1);
255                             }
256                             | BoolExpr
257                             | Attribute
258                             | TOK_NCName
259     ;
260     /* [2.5] Abbreviated Syntax */
261     AbbreviatedAbsoluteLocationPath : TOK_DblFSlash RelativeLocationPath
262                             {
263                                 TRACE("Got AbbreviatedAbsoluteLocationPath: \"//%s\"\n", $2);
264                                 $$=xmlStrdup(U("//"));
265                                 $$=xmlStrcat($$,$2);
266                                 xmlFree($2);
267                             }
268     ;
269     AbbreviatedRelativeLocationPath : RelativeLocationPath TOK_DblFSlash Step
270                             {
271                                 TRACE("Got AbbreviatedRelativeLocationPath: \"%s//%s\"\n", $1, $3);
272                                 $$=$1;
273                                 $$=xmlStrcat($$,U("//"));
274                                 $$=xmlStrcat($$,$3);
275                                 xmlFree($3);
276                             }
277     ;
278     AbbreviatedStep         : TOK_Parent
279                             {
280                                 TRACE("Got AbbreviatedStep: \"..\"\n");
281                                 $$=xmlStrdup(U(".."));
282                             }
283                             | TOK_Self
284                             {
285                                 TRACE("Got AbbreviatedStep: \".\"\n");
286                                 $$=xmlStrdup(U("."));
287                             }
288     ;
289
290     /* [3] Expressions */
291     /* [3.1] Basics */
292     Expr                    : OrExpr
293     ;
294     BoolExpr                : FunctionCall
295                             | BoolUnaryExpr
296                             | BoolRelationalExpr
297                             | BoolEqualityExpr
298                             | BoolAndExpr
299                             | BoolOrExpr
300     ;
301     PrimaryExpr             : '(' Expr ')'
302                             {
303                                 TRACE("Got PrimaryExpr: \"(%s)\"\n", $1);
304                                 $$=xmlStrdup(U("("));
305                                 $$=xmlStrcat($$,$2);
306                                 xmlFree($2);
307                                 $$=xmlStrcat($$,U(")"));
308                             }
309                             | PathExpr '!' FunctionCall
310                             {
311                                 TRACE("Got PrimaryExpr: \"%s!%s\"\n", $1, $3);
312                                 $$=$1;
313                                 $$=xmlStrcat($$,U("/"));
314                                 $$=xmlStrcat($$,$3);
315                                 xmlFree($3);
316                             }
317                             | TOK_Literal
318                             | TOK_Number
319     ;
320     /* [3.2] Function Calls */
321     FunctionCall            : QName '(' Arguments ')'
322                             {
323                                 TRACE("Got FunctionCall: \"%s(%s)\"\n", $1, $3);
324                                 if (xmlStrEqual($1,U("ancestor")))
325                                 {
326                                     $$=$1;
327                                     $$=xmlStrcat($$,U("::"));
328                                     $$=xmlStrcat($$,$3);
329                                     xmlFree($3);
330                                 }
331                                 else if (xmlStrEqual($1,U("attribute")))
332                                 {
333                                     if (is_literal($3))
334                                     {
335                                         $$=xmlStrdup(U("@*[name()="));
336                                         xmlFree($1);
337                                         $$=xmlStrcat($$,$3);
338                                         xmlFree($3);
339                                         $$=xmlStrcat($$,U("]"));
340                                     }
341                                     else
342                                     {
343                                         /* XML_XPATH_INVALID_TYPE */
344                                         $$=xmlStrdup(U("error(1211, 'Error: attribute("));
345                                         xmlFree($1);
346                                         $$=xmlStrcat($$,$3);
347                                         xmlFree($3);
348                                         $$=xmlStrcat($$,U("): invalid argument')"));
349                                     }
350                                 }
351                                 else if (xmlStrEqual($1,U("element")))
352                                 {
353                                     if (is_literal($3))
354                                     {
355                                         $$=xmlStrdup(U("node()[nodeType()=1][name()="));
356                                         xmlFree($1);
357                                         $$=xmlStrcat($$,$3);
358                                         xmlFree($3);
359                                         $$=xmlStrcat($$,U("]"));
360                                     }
361                                     else
362                                     {
363                                         /* XML_XPATH_INVALID_TYPE */
364                                         $$=xmlStrdup(U("error(1211, 'Error: element("));
365                                         xmlFree($1);
366                                         $$=xmlStrcat($$,$3);
367                                         xmlFree($3);
368                                         $$=xmlStrcat($$,U("): invalid argument')"));
369                                     }
370                                 }
371                                 else
372                                 {
373                                     $$=$1;
374                                     $$=xmlStrcat($$,U("("));
375                                     $$=xmlStrcat($$,$3);
376                                     xmlFree($3);
377                                     $$=xmlStrcat($$,U(")"));
378                                 }
379                             }
380                             | QName '(' ')'
381                             {
382                                 TRACE("Got FunctionCall: \"%s()\"\n", $1);
383                                 /* comment() & node() work the same in XPath */
384                                 if (xmlStrEqual($1,U("attribute")))
385                                 {
386                                     $$=xmlStrdup(U("@*"));
387                                     xmlFree($1);
388                                 }
389                                 else if (xmlStrEqual($1,U("element")))
390                                 {
391                                     $$=xmlStrdup(U("node()[nodeType()=1]"));
392                                     xmlFree($1);
393                                 }
394                                 else if (xmlStrEqual($1,U("pi")))
395                                 {
396                                     $$=xmlStrdup(U("processing-instruction()"));
397                                     xmlFree($1);
398                                 }
399                                 else if (xmlStrEqual($1,U("textnode")))
400                                 {
401                                     $$=xmlStrdup(U("text()"));
402                                     xmlFree($1);
403                                 }
404                                 else
405                                 {
406                                     $$=$1;
407                                     $$=xmlStrcat($$,U("()"));
408                                 }
409                             }
410     ;
411     Arguments               : Argument ',' Arguments
412                             {
413                                 $$=$1;
414                                 $$=xmlStrcat($$,U(","));
415                                 $$=xmlStrcat($$,$3);
416                                 xmlFree($3);
417                             }
418                             | Argument
419     ;
420     Argument                : Expr
421     ;
422     /* [3.3] Node-sets */
423     UnionExpr               : PathExpr
424                             | UnionExpr '|' PathExpr
425                             {
426                                 TRACE("Got UnionExpr: \"%s|%s\"\n", $1, $3);
427                                 $$=$1;
428                                 $$=xmlStrcat($$,U("|"));
429                                 $$=xmlStrcat($$,$3);
430                                 xmlFree($3);
431                             }
432     ;
433     PathExpr                : LocationPath
434                             | FilterExpr TOK_FSlash RelativeLocationPath
435                             {
436                                 TRACE("Got PathExpr: \"%s/%s\"\n", $1, $3);
437                                 $$=$1;
438                                 $$=xmlStrcat($$,U("/"));
439                                 $$=xmlStrcat($$,$3);
440                                 xmlFree($3);
441                             }
442                             | FilterExpr TOK_DblFSlash RelativeLocationPath
443                             {
444                                 TRACE("Got PathExpr: \"%s//%s\"\n", $1, $3);
445                                 $$=$1;
446                                 $$=xmlStrcat($$,U("//"));
447                                 $$=xmlStrcat($$,$3);
448                                 xmlFree($3);
449                             }
450                             | FilterExpr
451     ;
452     FilterExpr              : PrimaryExpr
453                             | FilterExpr Predicate
454                             {
455                                 TRACE("Got FilterExpr: \"%s%s\"\n", $1, $2);
456                                 $$=$1;
457                                 $$=xmlStrcat($$,$2);
458                                 xmlFree($2);
459                             }
460     ;
461     /* [3.4] Booleans */
462     OrExpr                  : AndExpr
463                             | BoolOrExpr
464     ;
465     BoolOrExpr              : OrExpr TOK_OpOr AndExpr
466                             {
467                                 TRACE("Got OrExpr: \"%s $or$ %s\"\n", $1, $3);
468                                 $$=$1;
469                                 $$=xmlStrcat($$,U(" or "));
470                                 $$=xmlStrcat($$,$3);
471                                 xmlFree($3);
472                             }
473     ;
474     AndExpr                 : EqualityExpr
475                             | BoolAndExpr
476     ;
477     BoolAndExpr             : AndExpr TOK_OpAnd EqualityExpr
478                             {
479                                 TRACE("Got AndExpr: \"%s $and$ %s\"\n", $1, $3);
480                                 $$=$1;
481                                 $$=xmlStrcat($$,U(" and "));
482                                 $$=xmlStrcat($$,$3);
483                                 xmlFree($3);
484                             }
485     ;
486     EqualityExpr            : RelationalExpr
487                             | BoolEqualityExpr
488     ;
489     BoolEqualityExpr        : EqualityExpr TOK_OpEq RelationalExpr
490                             {
491                                 TRACE("Got EqualityExpr: \"%s $eq$ %s\"\n", $1, $3);
492                                 $$=$1;
493                                 $$=xmlStrcat($$,U("="));
494                                 $$=xmlStrcat($$,$3);
495                                 xmlFree($3);
496                             }
497                             | EqualityExpr TOK_OpIEq RelationalExpr
498                             {
499                                 TRACE("Got EqualityExpr: \"%s $ieq$ %s\"\n", $1, $3);
500                                 $$=xmlStrdup(U("OP_IEq("));
501                                 $$=xmlStrcat($$,$1);
502                                 xmlFree($1);
503                                 $$=xmlStrcat($$,U(","));
504                                 $$=xmlStrcat($$,$3);
505                                 xmlFree($3);
506                                 $$=xmlStrcat($$,U(")"));
507                             }
508                             | EqualityExpr TOK_OpNEq RelationalExpr
509                             {
510                                 TRACE("Got EqualityExpr: \"%s $ne$ %s\"\n", $1, $3);
511                                 $$=$1;
512                                 $$=xmlStrcat($$,U("!="));
513                                 $$=xmlStrcat($$,$3);
514                                 xmlFree($3);
515                             }
516                             | EqualityExpr TOK_OpINEq RelationalExpr
517                             {
518                                 TRACE("Got EqualityExpr: \"%s $ine$ %s\"\n", $1, $3);
519                                 $$=xmlStrdup(U("OP_INEq("));
520                                 $$=xmlStrcat($$,$1);
521                                 xmlFree($1);
522                                 $$=xmlStrcat($$,U(","));
523                                 $$=xmlStrcat($$,$3);
524                                 xmlFree($3);
525                                 $$=xmlStrcat($$,U(")"));
526                             }
527     ;
528     RelationalExpr          : UnaryExpr
529                             | BoolRelationalExpr
530     ;
531     BoolRelationalExpr      : RelationalExpr TOK_OpLt UnaryExpr
532                             {
533                                 TRACE("Got RelationalExpr: \"%s $lt$ %s\"\n", $1, $3);
534                                 $$=$1;
535                                 $$=xmlStrcat($$,U("<"));
536                                 $$=xmlStrcat($$,$3);
537                                 xmlFree($3);
538                             }
539                             | RelationalExpr TOK_OpILt UnaryExpr
540                             {
541                                 TRACE("Got RelationalExpr: \"%s $ilt$ %s\"\n", $1, $3);
542                                 $$=xmlStrdup(U("OP_ILt("));
543                                 $$=xmlStrcat($$,$1);
544                                 xmlFree($1);
545                                 $$=xmlStrcat($$,U(","));
546                                 $$=xmlStrcat($$,$3);
547                                 xmlFree($3);
548                                 $$=xmlStrcat($$,U(")"));
549                             }
550                             | RelationalExpr TOK_OpGt UnaryExpr
551                             {
552                                 TRACE("Got RelationalExpr: \"%s $gt$ %s\"\n", $1, $3);
553                                 $$=$1;
554                                 $$=xmlStrcat($$,U(">"));
555                                 $$=xmlStrcat($$,$3);
556                                 xmlFree($3);
557                             }
558                             | RelationalExpr TOK_OpIGt UnaryExpr
559                             {
560                                 TRACE("Got RelationalExpr: \"%s $igt$ %s\"\n", $1, $3);
561                                 $$=xmlStrdup(U("OP_IGt("));
562                                 $$=xmlStrcat($$,$1);
563                                 xmlFree($1);
564                                 $$=xmlStrcat($$,U(","));
565                                 $$=xmlStrcat($$,$3);
566                                 xmlFree($3);
567                                 $$=xmlStrcat($$,U(")"));
568                             }
569                             | RelationalExpr TOK_OpLEq UnaryExpr
570                             {
571                                 TRACE("Got RelationalExpr: \"%s $le$ %s\"\n", $1, $3);
572                                 $$=$1;
573                                 $$=xmlStrcat($$,U("<="));
574                                 $$=xmlStrcat($$,$3);
575                                 xmlFree($3);
576                             }
577                             | RelationalExpr TOK_OpILEq UnaryExpr
578                             {
579                                 TRACE("Got RelationalExpr: \"%s $ile$ %s\"\n", $1, $3);
580                                 $$=xmlStrdup(U("OP_ILEq("));
581                                 $$=xmlStrcat($$,$1);
582                                 xmlFree($1);
583                                 $$=xmlStrcat($$,U(","));
584                                 $$=xmlStrcat($$,$3);
585                                 xmlFree($3);
586                                 $$=xmlStrcat($$,U(")"));
587                             }
588                             | RelationalExpr TOK_OpGEq UnaryExpr
589                             {
590                                 TRACE("Got RelationalExpr: \"%s $ge$ %s\"\n", $1, $3);
591                                 $$=$1;
592                                 $$=xmlStrcat($$,U(">="));
593                                 $$=xmlStrcat($$,$3);
594                                 xmlFree($3);
595                             }
596                             | RelationalExpr TOK_OpIGEq UnaryExpr
597                             {
598                                 TRACE("Got RelationalExpr: \"%s $ige$ %s\"\n", $1, $3);
599                                 $$=xmlStrdup(U("OP_IGEq("));
600                                 $$=xmlStrcat($$,$1);
601                                 xmlFree($1);
602                                 $$=xmlStrcat($$,U(","));
603                                 $$=xmlStrcat($$,$3);
604                                 xmlFree($3);
605                                 $$=xmlStrcat($$,U(")"));
606                             }
607     ;
608
609     /* [3.5] Numbers */
610     UnaryExpr               : UnionExpr
611                             | BoolUnaryExpr
612     ;
613     BoolUnaryExpr           : TOK_OpNot UnaryExpr
614                             {
615                                 TRACE("Got UnaryExpr: \"$not$ %s\"\n", $2);
616                                 $$=xmlStrdup(U(" not("));
617                                 $$=xmlStrcat($$,$2);
618                                 xmlFree($2);
619                                 $$=xmlStrcat($$,U(")"));
620                             }
621                             | TOK_OpAny Expr
622                             {
623                                 TRACE("Got UnaryExpr: \"$any$ %s\"\n", $2);
624                                 $$=xmlStrdup(U("boolean("));
625                                 $$=xmlStrcat($$,$2);
626                                 xmlFree($2);
627                                 $$=xmlStrcat($$,U(")"));
628                             }
629                             | TOK_OpAll AllExpr
630                             {
631                                 TRACE("Got UnaryExpr: \"$all$ %s\"\n", $2);
632                                 $$=xmlStrdup(U("not("));
633                                 $$=xmlStrcat($$,$2);
634                                 xmlFree($2);
635                                 $$=xmlStrcat($$,U(")"));
636                             }
637                             | TOK_OpAll
638                             {
639                                 FIXME("Unrecognized $all$ expression - ignoring\n");
640                                 $$=xmlStrdup(U(""));
641                             }
642     ;
643     AllExpr                 : PathExpr TOK_OpEq PathExpr
644                             {
645                                 $$=$1;
646                                 $$=xmlStrcat($$,U("!="));
647                                 $$=xmlStrcat($$,$3);
648                                 xmlFree($3);
649                             }
650                             | PathExpr TOK_OpNEq PathExpr
651                             {
652                                 $$=$1;
653                                 $$=xmlStrcat($$,U("="));
654                                 $$=xmlStrcat($$,$3);
655                                 xmlFree($3);
656                             }
657                             | PathExpr TOK_OpLt PathExpr
658                             {
659                                 $$=$1;
660                                 $$=xmlStrcat($$,U(">="));
661                                 $$=xmlStrcat($$,$3);
662                                 xmlFree($3);
663                             }
664                             | PathExpr TOK_OpLEq PathExpr
665                             {
666                                 $$=$1;
667                                 $$=xmlStrcat($$,U(">"));
668                                 $$=xmlStrcat($$,$3);
669                                 xmlFree($3);
670                             }
671                             | PathExpr TOK_OpGt PathExpr
672                             {
673                                 $$=$1;
674                                 $$=xmlStrcat($$,U("<="));
675                                 $$=xmlStrcat($$,$3);
676                                 xmlFree($3);
677                             }
678                             | PathExpr TOK_OpGEq PathExpr
679                             {
680                                 $$=$1;
681                                 $$=xmlStrcat($$,U("<"));
682                                 $$=xmlStrcat($$,$3);
683                                 xmlFree($3);
684                             }
685                             | PathExpr TOK_OpIEq PathExpr
686                             {
687                                 $$=xmlStrdup(U("OP_INEq("));
688                                 $$=xmlStrcat($$,$1);
689                                 xmlFree($1);
690                                 $$=xmlStrcat($$,U(","));
691                                 $$=xmlStrcat($$,$3);
692                                 xmlFree($3);
693                                 $$=xmlStrcat($$,U(")"));
694                             }
695                             | PathExpr TOK_OpINEq PathExpr
696                             {
697                                 $$=xmlStrdup(U("OP_IEq("));
698                                 $$=xmlStrcat($$,$1);
699                                 xmlFree($1);
700                                 $$=xmlStrcat($$,U(","));
701                                 $$=xmlStrcat($$,$3);
702                                 xmlFree($3);
703                                 $$=xmlStrcat($$,U(")"));
704                             }
705                             | PathExpr TOK_OpILt PathExpr
706                             {
707                                 $$=xmlStrdup(U("OP_IGEq("));
708                                 $$=xmlStrcat($$,$1);
709                                 xmlFree($1);
710                                 $$=xmlStrcat($$,U(","));
711                                 $$=xmlStrcat($$,$3);
712                                 xmlFree($3);
713                                 $$=xmlStrcat($$,U(")"));
714                             }
715                             | PathExpr TOK_OpILEq PathExpr
716                             {
717                                 $$=xmlStrdup(U("OP_IGt("));
718                                 $$=xmlStrcat($$,$1);
719                                 xmlFree($1);
720                                 $$=xmlStrcat($$,U(","));
721                                 $$=xmlStrcat($$,$3);
722                                 xmlFree($3);
723                                 $$=xmlStrcat($$,U(")"));
724                             }
725                             | PathExpr TOK_OpIGt PathExpr
726                             {
727                                 $$=xmlStrdup(U("OP_ILEq("));
728                                 $$=xmlStrcat($$,$1);
729                                 xmlFree($1);
730                                 $$=xmlStrcat($$,U(","));
731                                 $$=xmlStrcat($$,$3);
732                                 xmlFree($3);
733                                 $$=xmlStrcat($$,U(")"));
734                             }
735                             | PathExpr TOK_OpIGEq PathExpr
736                             {
737                                 $$=xmlStrdup(U("OP_ILt("));
738                                 $$=xmlStrcat($$,$1);
739                                 xmlFree($1);
740                                 $$=xmlStrcat($$,U(","));
741                                 $$=xmlStrcat($$,$3);
742                                 xmlFree($3);
743                                 $$=xmlStrcat($$,U(")"));
744                             }
745     ;
746
747 %%
748
749 #endif  /* HAVE_LIBXML2 */