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