oleaut32: Convert CustData to use standard linked lists.
[wine.git] / dlls / msxml3 / xslpattern.y
blob68c4c3c25a87358cbc9e9e6faff20e37c3403b3e
1 /*
2 * XSLPattern parser (XSLPattern => XPath)
4 * Copyright 2010 Adam Martinson for CodeWeavers
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.
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.
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
22 #include "config.h"
23 #include "wine/port.h"
25 #ifdef HAVE_LIBXML2
26 #include "xslpattern.h"
27 #include <libxml/xpathInternals.h>
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
33 static const xmlChar NameTest_mod_pre[] = "*[name()='";
34 static const xmlChar NameTest_mod_post[] = "']";
36 #define U(str) BAD_CAST str
38 static inline BOOL is_literal(xmlChar const* tok)
40 return (tok && tok[0] && tok[1] &&
41 tok[0]== tok[xmlStrlen(tok)-1] &&
42 (tok[0] == '\'' || tok[0] == '"'));
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
54 %start XSLPattern
56 %pure_parser
57 %parse-param {parser_param* p}
58 %parse-param {void* scanner}
59 %lex-param {yyscan_t* scanner}
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
65 %expect 14
69 XSLPattern : Expr
71 p->out = $1;
75 /* Mostly verbatim from the w3c XML Namespaces standard.
76 * <http://www.w3.org/TR/REC-xml-names/> */
78 /* [4] Qualified Names */
79 QName : PrefixedName
80 | UnprefixedName
82 PrefixedName : TOK_NCName TOK_Colon TOK_NCName
84 TRACE("Got PrefixedName: \"%s:%s\"\n", $1, $3);
85 $$=$1;
86 $$=xmlStrcat($$,U(":"));
87 $$=xmlStrcat($$,$3);
88 xmlFree($3);
91 UnprefixedName : TOK_NCName
93 TRACE("Got UnprefixedName: \"%s\"\n", $1);
94 $$=$1;
98 /* Based on the w3c XPath standard, adapted where needed.
99 * <http://www.w3.org/TR/xpath/> */
101 /* [2] Location Paths */
102 LocationPath : RelativeLocationPath
103 | AbsoluteLocationPath
105 AbsoluteLocationPath : TOK_FSlash RelativeLocationPath
107 TRACE("Got AbsoluteLocationPath: \"/%s\"\n", $2);
108 $$=xmlStrdup(U("/"));
109 $$=xmlStrcat($$,$2);
110 xmlFree($2);
112 | TOK_FSlash
114 TRACE("Got AbsoluteLocationPath: \"/\"\n");
115 $$=xmlStrdup(U("/"));
117 | AbbreviatedAbsoluteLocationPath
119 RelativeLocationPath : Step
120 | RelativeLocationPath TOK_FSlash Step
122 TRACE("Got RelativeLocationPath: \"%s/%s\"\n", $1, $3);
123 $$=$1;
124 $$=xmlStrcat($$,U("/"));
125 $$=xmlStrcat($$,$3);
126 xmlFree($3);
128 | AbbreviatedRelativeLocationPath
130 /* [2.1] Location Steps */
131 Step : AxisSpecifier NodeTest Predicates
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);
140 | NodeTest Predicates
142 TRACE("Got Step: \"%s%s\"\n", $1, $2);
143 $$=$1;
144 $$=xmlStrcat($$,$2);
145 xmlFree($2);
147 | AxisSpecifier NodeTest
149 TRACE("Got Step: \"%s%s\"\n", $1, $2);
150 $$=$1;
151 $$=xmlStrcat($$,$2);
152 xmlFree($2);
154 | NodeTest
155 | Attribute
156 | AbbreviatedStep
158 AxisSpecifier : TOK_NCName TOK_Axis
160 TRACE("Got AxisSpecifier: \"%s::\"\n", $1);
161 $$=$1;
162 $$=xmlStrcat($$,U("::"));
165 Attribute : '@' TOK_NCName
167 TRACE("Got Attribute: \"@%s\"\n", $2);
168 $$=xmlStrdup(U("@"));
169 $$=xmlStrcat($$,$2);
170 xmlFree($2);
174 /* [2.3] Node Tests */
175 NodeTest : NameTest
176 | FunctionCall
178 NameTest : '*'
180 TRACE("Got NameTest: \"*\"\n");
181 $$=xmlStrdup(U("*"));
183 | TOK_NCName TOK_Colon '*'
185 TRACE("Got NameTest: \"%s:*\"\n", $1);
186 $$=$1;
187 $$=xmlStrcat($$,U(":*"));
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);
194 if (registeredNsURI)
195 $$=xmlStrdup(U(""));
196 else
197 $$=xmlStrdup(NameTest_mod_pre);
199 $$=xmlStrcat($$,$1);
200 xmlFree($1);
201 $$=xmlStrcat($$,U(":"));
202 $$=xmlStrcat($$,$3);
203 xmlFree($3);
205 if (!registeredNsURI)
206 $$=xmlStrcat($$,NameTest_mod_post);
208 | UnprefixedName
210 $$=xmlStrdup(NameTest_mod_pre);
211 $$=xmlStrcat($$,$1);
212 xmlFree($1);
213 $$=xmlStrcat($$,NameTest_mod_post);
215 /* [2.4] Predicates */
216 Predicates : Predicates Predicate
218 $$=$1;
219 $$=xmlStrcat($$,$2);
220 xmlFree($2);
222 | Predicate
224 Predicate : '[' PredicateExpr ']'
226 TRACE("Got Predicate: \"[%s]\"\n", $2);
227 $$=xmlStrdup(U("["));
228 $$=xmlStrcat($$,$2);
229 xmlFree($2);
230 $$=xmlStrcat($$,U("]"));
233 PredicateExpr : TOK_Number
235 $$=xmlStrdup(U("index()="));
236 $$=xmlStrcat($$,$1);
237 xmlFree($1);
239 | BoolExpr
240 | Attribute
242 /* [2.5] Abbreviated Syntax */
243 AbbreviatedAbsoluteLocationPath : TOK_DblFSlash RelativeLocationPath
245 TRACE("Got AbbreviatedAbsoluteLocationPath: \"//%s\"\n", $2);
246 $$=xmlStrdup(U("//"));
247 $$=xmlStrcat($$,$2);
248 xmlFree($2);
251 AbbreviatedRelativeLocationPath : RelativeLocationPath TOK_DblFSlash Step
253 TRACE("Got AbbreviatedRelativeLocationPath: \"%s//%s\"\n", $1, $3);
254 $$=$1;
255 $$=xmlStrcat($$,U("//"));
256 $$=xmlStrcat($$,$3);
257 xmlFree($3);
260 AbbreviatedStep : TOK_Parent
262 TRACE("Got AbbreviatedStep: \"..\"\n");
263 $$=xmlStrdup(U(".."));
265 | TOK_Self
267 TRACE("Got AbbreviatedStep: \".\"\n");
268 $$=xmlStrdup(U("."));
272 /* [3] Expressions */
273 /* [3.1] Basics */
274 Expr : OrExpr
276 BoolExpr : FunctionCall
277 | BoolUnaryExpr
278 | BoolRelationalExpr
279 | BoolEqualityExpr
280 | BoolAndExpr
281 | BoolOrExpr
283 PrimaryExpr : '(' Expr ')'
285 TRACE("Got PrimaryExpr: \"(%s)\"\n", $1);
286 $$=xmlStrdup(U("("));
287 $$=xmlStrcat($$,$2);
288 xmlFree($2);
289 $$=xmlStrcat($$,U(")"));
291 | PathExpr '!' FunctionCall
293 TRACE("Got PrimaryExpr: \"%s!%s\"\n", $1, $3);
294 $$=$1;
295 $$=xmlStrcat($$,U("/"));
296 $$=xmlStrcat($$,$3);
297 xmlFree($3);
299 | TOK_Literal
300 | TOK_Number
302 /* [3.2] Function Calls */
303 FunctionCall : QName '(' Arguments ')'
305 TRACE("Got FunctionCall: \"%s(%s)\"\n", $1, $3);
306 if (xmlStrEqual($1,U("ancestor")))
308 $$=$1;
309 $$=xmlStrcat($$,U("::"));
310 $$=xmlStrcat($$,$3);
311 xmlFree($3);
313 else if (xmlStrEqual($1,U("attribute")))
315 if (is_literal($3))
317 $$=xmlStrdup(U("@*[name()="));
318 xmlFree($1);
319 $$=xmlStrcat($$,$3);
320 xmlFree($3);
321 $$=xmlStrcat($$,U("]"));
323 else
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')"));
333 else if (xmlStrEqual($1,U("element")))
335 if (is_literal($3))
337 $$=xmlStrdup(U("node()[nodeType()=1][name()="));
338 xmlFree($1);
339 $$=xmlStrcat($$,$3);
340 xmlFree($3);
341 $$=xmlStrcat($$,U("]"));
343 else
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')"));
353 else
355 $$=$1;
356 $$=xmlStrcat($$,U("("));
357 $$=xmlStrcat($$,$3);
358 xmlFree($3);
359 $$=xmlStrcat($$,U(")"));
362 | QName '(' ')'
364 TRACE("Got FunctionCall: \"%s()\"\n", $1);
365 /* comment() & node() work the same in XPath */
366 if (xmlStrEqual($1,U("attribute")))
368 $$=xmlStrdup(U("@*"));
369 xmlFree($1);
371 else if (xmlStrEqual($1,U("element")))
373 $$=xmlStrdup(U("node()[nodeType()=1]"));
374 xmlFree($1);
376 else if (xmlStrEqual($1,U("pi")))
378 $$=xmlStrdup(U("processing-instruction()"));
379 xmlFree($1);
381 else if (xmlStrEqual($1,U("textnode")))
383 $$=xmlStrdup(U("text()"));
384 xmlFree($1);
386 else
388 $$=$1;
389 $$=xmlStrcat($$,U("()"));
393 Arguments : Argument ',' Arguments
395 $$=$1;
396 $$=xmlStrcat($$,U(","));
397 $$=xmlStrcat($$,$3);
398 xmlFree($3);
400 | Argument
402 Argument : Expr
404 /* [3.3] Node-sets */
405 UnionExpr : PathExpr
406 | UnionExpr '|' PathExpr
408 TRACE("Got UnionExpr: \"%s|%s\"\n", $1, $3);
409 $$=$1;
410 $$=xmlStrcat($$,U("|"));
411 $$=xmlStrcat($$,$3);
412 xmlFree($3);
415 PathExpr : LocationPath
416 | FilterExpr TOK_FSlash RelativeLocationPath
418 TRACE("Got PathExpr: \"%s/%s\"\n", $1, $3);
419 $$=$1;
420 $$=xmlStrcat($$,U("/"));
421 $$=xmlStrcat($$,$3);
422 xmlFree($3);
424 | FilterExpr TOK_DblFSlash RelativeLocationPath
426 TRACE("Got PathExpr: \"%s//%s\"\n", $1, $3);
427 $$=$1;
428 $$=xmlStrcat($$,U("//"));
429 $$=xmlStrcat($$,$3);
430 xmlFree($3);
432 | FilterExpr
434 FilterExpr : PrimaryExpr
435 | FilterExpr Predicate
437 TRACE("Got FilterExpr: \"%s%s\"\n", $1, $2);
438 $$=$1;
439 $$=xmlStrcat($$,$2);
440 xmlFree($2);
443 /* [3.4] Booleans */
444 OrExpr : AndExpr
445 | BoolOrExpr
447 BoolOrExpr : OrExpr TOK_OpOr AndExpr
449 TRACE("Got OrExpr: \"%s $or$ %s\"\n", $1, $3);
450 $$=$1;
451 $$=xmlStrcat($$,U(" or "));
452 $$=xmlStrcat($$,$3);
453 xmlFree($3);
456 AndExpr : EqualityExpr
457 | BoolAndExpr
459 BoolAndExpr : AndExpr TOK_OpAnd EqualityExpr
461 TRACE("Got AndExpr: \"%s $and$ %s\"\n", $1, $3);
462 $$=$1;
463 $$=xmlStrcat($$,U(" and "));
464 $$=xmlStrcat($$,$3);
465 xmlFree($3);
468 EqualityExpr : RelationalExpr
469 | BoolEqualityExpr
471 BoolEqualityExpr : EqualityExpr TOK_OpEq RelationalExpr
473 TRACE("Got EqualityExpr: \"%s $eq$ %s\"\n", $1, $3);
474 $$=$1;
475 $$=xmlStrcat($$,U("="));
476 $$=xmlStrcat($$,$3);
477 xmlFree($3);
479 | EqualityExpr TOK_OpIEq RelationalExpr
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(")"));
490 | EqualityExpr TOK_OpNEq RelationalExpr
492 TRACE("Got EqualityExpr: \"%s $ne$ %s\"\n", $1, $3);
493 $$=$1;
494 $$=xmlStrcat($$,U("!="));
495 $$=xmlStrcat($$,$3);
496 xmlFree($3);
498 | EqualityExpr TOK_OpINEq RelationalExpr
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(")"));
510 RelationalExpr : UnaryExpr
511 | BoolRelationalExpr
513 BoolRelationalExpr : RelationalExpr TOK_OpLt UnaryExpr
515 TRACE("Got RelationalExpr: \"%s $lt$ %s\"\n", $1, $3);
516 $$=$1;
517 $$=xmlStrcat($$,U("<"));
518 $$=xmlStrcat($$,$3);
519 xmlFree($3);
521 | RelationalExpr TOK_OpILt UnaryExpr
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(")"));
532 | RelationalExpr TOK_OpGt UnaryExpr
534 TRACE("Got RelationalExpr: \"%s $gt$ %s\"\n", $1, $3);
535 $$=$1;
536 $$=xmlStrcat($$,U(">"));
537 $$=xmlStrcat($$,$3);
538 xmlFree($3);
540 | RelationalExpr TOK_OpIGt UnaryExpr
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(")"));
551 | RelationalExpr TOK_OpLEq UnaryExpr
553 TRACE("Got RelationalExpr: \"%s $le$ %s\"\n", $1, $3);
554 $$=$1;
555 $$=xmlStrcat($$,U("<="));
556 $$=xmlStrcat($$,$3);
557 xmlFree($3);
559 | RelationalExpr TOK_OpILEq UnaryExpr
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(")"));
570 | RelationalExpr TOK_OpGEq UnaryExpr
572 TRACE("Got RelationalExpr: \"%s $ge$ %s\"\n", $1, $3);
573 $$=$1;
574 $$=xmlStrcat($$,U(">="));
575 $$=xmlStrcat($$,$3);
576 xmlFree($3);
578 | RelationalExpr TOK_OpIGEq UnaryExpr
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(")"));
591 /* [3.5] Numbers */
592 UnaryExpr : UnionExpr
593 | BoolUnaryExpr
595 BoolUnaryExpr : TOK_OpNot UnaryExpr
597 TRACE("Got UnaryExpr: \"$not$ %s\"\n", $2);
598 $$=xmlStrdup(U(" not("));
599 $$=xmlStrcat($$,$2);
600 xmlFree($2);
601 $$=xmlStrcat($$,U(")"));
603 | TOK_OpAny Expr
605 TRACE("Got UnaryExpr: \"$any$ %s\"\n", $2);
606 $$=xmlStrdup(U("boolean("));
607 $$=xmlStrcat($$,$2);
608 xmlFree($2);
609 $$=xmlStrcat($$,U(")"));
611 | TOK_OpAll AllExpr
613 TRACE("Got UnaryExpr: \"$all$ %s\"\n", $2);
614 $$=xmlStrdup(U("not("));
615 $$=xmlStrcat($$,$2);
616 xmlFree($2);
617 $$=xmlStrcat($$,U(")"));
619 | TOK_OpAll
621 FIXME("Unrecognized $all$ expression - ignoring\n");
622 $$=xmlStrdup(U(""));
625 AllExpr : PathExpr TOK_OpEq PathExpr
627 $$=$1;
628 $$=xmlStrcat($$,U("!="));
629 $$=xmlStrcat($$,$3);
630 xmlFree($3);
632 | PathExpr TOK_OpNEq PathExpr
634 $$=$1;
635 $$=xmlStrcat($$,U("="));
636 $$=xmlStrcat($$,$3);
637 xmlFree($3);
639 | PathExpr TOK_OpLt PathExpr
641 $$=$1;
642 $$=xmlStrcat($$,U(">="));
643 $$=xmlStrcat($$,$3);
644 xmlFree($3);
646 | PathExpr TOK_OpLEq PathExpr
648 $$=$1;
649 $$=xmlStrcat($$,U(">"));
650 $$=xmlStrcat($$,$3);
651 xmlFree($3);
653 | PathExpr TOK_OpGt PathExpr
655 $$=$1;
656 $$=xmlStrcat($$,U("<="));
657 $$=xmlStrcat($$,$3);
658 xmlFree($3);
660 | PathExpr TOK_OpGEq PathExpr
662 $$=$1;
663 $$=xmlStrcat($$,U("<"));
664 $$=xmlStrcat($$,$3);
665 xmlFree($3);
667 | PathExpr TOK_OpIEq PathExpr
669 $$=xmlStrdup(U("OP_INEq("));
670 $$=xmlStrcat($$,$1);
671 xmlFree($1);
672 $$=xmlStrcat($$,U(","));
673 $$=xmlStrcat($$,$3);
674 xmlFree($3);
675 $$=xmlStrcat($$,U(")"));
677 | PathExpr TOK_OpINEq PathExpr
679 $$=xmlStrdup(U("OP_IEq("));
680 $$=xmlStrcat($$,$1);
681 xmlFree($1);
682 $$=xmlStrcat($$,U(","));
683 $$=xmlStrcat($$,$3);
684 xmlFree($3);
685 $$=xmlStrcat($$,U(")"));
687 | PathExpr TOK_OpILt PathExpr
689 $$=xmlStrdup(U("OP_IGEq("));
690 $$=xmlStrcat($$,$1);
691 xmlFree($1);
692 $$=xmlStrcat($$,U(","));
693 $$=xmlStrcat($$,$3);
694 xmlFree($3);
695 $$=xmlStrcat($$,U(")"));
697 | PathExpr TOK_OpILEq PathExpr
699 $$=xmlStrdup(U("OP_IGt("));
700 $$=xmlStrcat($$,$1);
701 xmlFree($1);
702 $$=xmlStrcat($$,U(","));
703 $$=xmlStrcat($$,$3);
704 xmlFree($3);
705 $$=xmlStrcat($$,U(")"));
707 | PathExpr TOK_OpIGt PathExpr
709 $$=xmlStrdup(U("OP_ILEq("));
710 $$=xmlStrcat($$,$1);
711 xmlFree($1);
712 $$=xmlStrcat($$,U(","));
713 $$=xmlStrcat($$,$3);
714 xmlFree($3);
715 $$=xmlStrcat($$,U(")"));
717 | PathExpr TOK_OpIGEq PathExpr
719 $$=xmlStrdup(U("OP_ILt("));
720 $$=xmlStrcat($$,$1);
721 xmlFree($1);
722 $$=xmlStrcat($$,U(","));
723 $$=xmlStrcat($$,$3);
724 xmlFree($3);
725 $$=xmlStrcat($$,U(")"));
731 void xslpattern_error(parser_param* param, void const* scanner, char const* msg)
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);
749 #endif /* HAVE_LIBXML2 */