msi/tests: Properly preserve pending file renames.
[wine/multimedia.git] / dlls / msxml3 / xslpattern.y
blob5187761d93a3c007a1205703d86e0482cdbd5c24
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] == '"'));
45 static void xslpattern_error(parser_param* param, void const* scanner, char const* msg)
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);
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
71 %start XSLPattern
73 %pure_parser
74 %parse-param {parser_param* p}
75 %parse-param {void* scanner}
76 %lex-param {yyscan_t* scanner}
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
82 %expect 14
86 XSLPattern : Expr
88 p->out = $1;
92 /* Mostly verbatim from the w3c XML Namespaces standard.
93 * <http://www.w3.org/TR/REC-xml-names/> */
95 /* [4] Qualified Names */
96 QName : PrefixedName
97 | UnprefixedName
99 PrefixedName : TOK_NCName TOK_Colon TOK_NCName
101 TRACE("Got PrefixedName: \"%s:%s\"\n", $1, $3);
102 $$=$1;
103 $$=xmlStrcat($$,U(":"));
104 $$=xmlStrcat($$,$3);
105 xmlFree($3);
108 UnprefixedName : TOK_NCName
110 TRACE("Got UnprefixedName: \"%s\"\n", $1);
111 $$=$1;
115 /* Based on the w3c XPath standard, adapted where needed.
116 * <http://www.w3.org/TR/xpath/> */
118 /* [2] Location Paths */
119 LocationPath : RelativeLocationPath
120 | AbsoluteLocationPath
122 AbsoluteLocationPath : TOK_FSlash RelativeLocationPath
124 TRACE("Got AbsoluteLocationPath: \"/%s\"\n", $2);
125 $$=xmlStrdup(U("/"));
126 $$=xmlStrcat($$,$2);
127 xmlFree($2);
129 | TOK_FSlash
131 TRACE("Got AbsoluteLocationPath: \"/\"\n");
132 $$=xmlStrdup(U("/"));
134 | AbbreviatedAbsoluteLocationPath
136 RelativeLocationPath : Step
137 | RelativeLocationPath TOK_FSlash Step
139 TRACE("Got RelativeLocationPath: \"%s/%s\"\n", $1, $3);
140 $$=$1;
141 $$=xmlStrcat($$,U("/"));
142 $$=xmlStrcat($$,$3);
143 xmlFree($3);
145 | AbbreviatedRelativeLocationPath
147 /* [2.1] Location Steps */
148 Step : AxisSpecifier NodeTest Predicates
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);
157 | NodeTest Predicates
159 TRACE("Got Step: \"%s%s\"\n", $1, $2);
160 $$=$1;
161 $$=xmlStrcat($$,$2);
162 xmlFree($2);
164 | AxisSpecifier NodeTest
166 TRACE("Got Step: \"%s%s\"\n", $1, $2);
167 $$=$1;
168 $$=xmlStrcat($$,$2);
169 xmlFree($2);
171 | NodeTest
172 | Attribute
173 | AbbreviatedStep
175 AxisSpecifier : TOK_NCName TOK_Axis
177 TRACE("Got AxisSpecifier: \"%s::\"\n", $1);
178 $$=$1;
179 $$=xmlStrcat($$,U("::"));
182 Attribute : '@' TOK_NCName
184 TRACE("Got Attribute: \"@%s\"\n", $2);
185 $$=xmlStrdup(U("@"));
186 $$=xmlStrcat($$,$2);
187 xmlFree($2);
191 /* [2.3] Node Tests */
192 NodeTest : NameTest
193 | FunctionCall
195 NameTest : '*'
197 TRACE("Got NameTest: \"*\"\n");
198 $$=xmlStrdup(U("*"));
200 | TOK_NCName TOK_Colon '*'
202 TRACE("Got NameTest: \"%s:*\"\n", $1);
203 $$=$1;
204 $$=xmlStrcat($$,U(":*"));
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);
211 if (registeredNsURI)
212 $$=xmlStrdup(U(""));
213 else
214 $$=xmlStrdup(NameTest_mod_pre);
216 $$=xmlStrcat($$,$1);
217 xmlFree($1);
218 $$=xmlStrcat($$,U(":"));
219 $$=xmlStrcat($$,$3);
220 xmlFree($3);
222 if (!registeredNsURI)
223 $$=xmlStrcat($$,NameTest_mod_post);
225 | UnprefixedName
227 $$=xmlStrdup(NameTest_mod_pre);
228 $$=xmlStrcat($$,$1);
229 xmlFree($1);
230 $$=xmlStrcat($$,NameTest_mod_post);
232 /* [2.4] Predicates */
233 Predicates : Predicates Predicate
235 $$=$1;
236 $$=xmlStrcat($$,$2);
237 xmlFree($2);
239 | Predicate
241 Predicate : '[' PredicateExpr ']'
243 TRACE("Got Predicate: \"[%s]\"\n", $2);
244 $$=xmlStrdup(U("["));
245 $$=xmlStrcat($$,$2);
246 xmlFree($2);
247 $$=xmlStrcat($$,U("]"));
250 PredicateExpr : TOK_Number
252 $$=xmlStrdup(U("index()="));
253 $$=xmlStrcat($$,$1);
254 xmlFree($1);
256 | BoolExpr
257 | Attribute
259 /* [2.5] Abbreviated Syntax */
260 AbbreviatedAbsoluteLocationPath : TOK_DblFSlash RelativeLocationPath
262 TRACE("Got AbbreviatedAbsoluteLocationPath: \"//%s\"\n", $2);
263 $$=xmlStrdup(U("//"));
264 $$=xmlStrcat($$,$2);
265 xmlFree($2);
268 AbbreviatedRelativeLocationPath : RelativeLocationPath TOK_DblFSlash Step
270 TRACE("Got AbbreviatedRelativeLocationPath: \"%s//%s\"\n", $1, $3);
271 $$=$1;
272 $$=xmlStrcat($$,U("//"));
273 $$=xmlStrcat($$,$3);
274 xmlFree($3);
277 AbbreviatedStep : TOK_Parent
279 TRACE("Got AbbreviatedStep: \"..\"\n");
280 $$=xmlStrdup(U(".."));
282 | TOK_Self
284 TRACE("Got AbbreviatedStep: \".\"\n");
285 $$=xmlStrdup(U("."));
289 /* [3] Expressions */
290 /* [3.1] Basics */
291 Expr : OrExpr
293 BoolExpr : FunctionCall
294 | BoolUnaryExpr
295 | BoolRelationalExpr
296 | BoolEqualityExpr
297 | BoolAndExpr
298 | BoolOrExpr
300 PrimaryExpr : '(' Expr ')'
302 TRACE("Got PrimaryExpr: \"(%s)\"\n", $1);
303 $$=xmlStrdup(U("("));
304 $$=xmlStrcat($$,$2);
305 xmlFree($2);
306 $$=xmlStrcat($$,U(")"));
308 | PathExpr '!' FunctionCall
310 TRACE("Got PrimaryExpr: \"%s!%s\"\n", $1, $3);
311 $$=$1;
312 $$=xmlStrcat($$,U("/"));
313 $$=xmlStrcat($$,$3);
314 xmlFree($3);
316 | TOK_Literal
317 | TOK_Number
319 /* [3.2] Function Calls */
320 FunctionCall : QName '(' Arguments ')'
322 TRACE("Got FunctionCall: \"%s(%s)\"\n", $1, $3);
323 if (xmlStrEqual($1,U("ancestor")))
325 $$=$1;
326 $$=xmlStrcat($$,U("::"));
327 $$=xmlStrcat($$,$3);
328 xmlFree($3);
330 else if (xmlStrEqual($1,U("attribute")))
332 if (is_literal($3))
334 $$=xmlStrdup(U("@*[name()="));
335 xmlFree($1);
336 $$=xmlStrcat($$,$3);
337 xmlFree($3);
338 $$=xmlStrcat($$,U("]"));
340 else
342 /* XML_XPATH_INVALID_TYPE */
343 $$=xmlStrdup(U("error(1211, 'Error: attribute("));
344 xmlFree($1);
345 $$=xmlStrcat($$,$3);
346 xmlFree($3);
347 $$=xmlStrcat($$,U("): invalid argument')"));
350 else if (xmlStrEqual($1,U("element")))
352 if (is_literal($3))
354 $$=xmlStrdup(U("node()[nodeType()=1][name()="));
355 xmlFree($1);
356 $$=xmlStrcat($$,$3);
357 xmlFree($3);
358 $$=xmlStrcat($$,U("]"));
360 else
362 /* XML_XPATH_INVALID_TYPE */
363 $$=xmlStrdup(U("error(1211, 'Error: element("));
364 xmlFree($1);
365 $$=xmlStrcat($$,$3);
366 xmlFree($3);
367 $$=xmlStrcat($$,U("): invalid argument')"));
370 else
372 $$=$1;
373 $$=xmlStrcat($$,U("("));
374 $$=xmlStrcat($$,$3);
375 xmlFree($3);
376 $$=xmlStrcat($$,U(")"));
379 | QName '(' ')'
381 TRACE("Got FunctionCall: \"%s()\"\n", $1);
382 /* comment() & node() work the same in XPath */
383 if (xmlStrEqual($1,U("attribute")))
385 $$=xmlStrdup(U("@*"));
386 xmlFree($1);
388 else if (xmlStrEqual($1,U("element")))
390 $$=xmlStrdup(U("node()[nodeType()=1]"));
391 xmlFree($1);
393 else if (xmlStrEqual($1,U("pi")))
395 $$=xmlStrdup(U("processing-instruction()"));
396 xmlFree($1);
398 else if (xmlStrEqual($1,U("textnode")))
400 $$=xmlStrdup(U("text()"));
401 xmlFree($1);
403 else
405 $$=$1;
406 $$=xmlStrcat($$,U("()"));
410 Arguments : Argument ',' Arguments
412 $$=$1;
413 $$=xmlStrcat($$,U(","));
414 $$=xmlStrcat($$,$3);
415 xmlFree($3);
417 | Argument
419 Argument : Expr
421 /* [3.3] Node-sets */
422 UnionExpr : PathExpr
423 | UnionExpr '|' PathExpr
425 TRACE("Got UnionExpr: \"%s|%s\"\n", $1, $3);
426 $$=$1;
427 $$=xmlStrcat($$,U("|"));
428 $$=xmlStrcat($$,$3);
429 xmlFree($3);
432 PathExpr : LocationPath
433 | FilterExpr TOK_FSlash RelativeLocationPath
435 TRACE("Got PathExpr: \"%s/%s\"\n", $1, $3);
436 $$=$1;
437 $$=xmlStrcat($$,U("/"));
438 $$=xmlStrcat($$,$3);
439 xmlFree($3);
441 | FilterExpr TOK_DblFSlash RelativeLocationPath
443 TRACE("Got PathExpr: \"%s//%s\"\n", $1, $3);
444 $$=$1;
445 $$=xmlStrcat($$,U("//"));
446 $$=xmlStrcat($$,$3);
447 xmlFree($3);
449 | FilterExpr
451 FilterExpr : PrimaryExpr
452 | FilterExpr Predicate
454 TRACE("Got FilterExpr: \"%s%s\"\n", $1, $2);
455 $$=$1;
456 $$=xmlStrcat($$,$2);
457 xmlFree($2);
460 /* [3.4] Booleans */
461 OrExpr : AndExpr
462 | BoolOrExpr
464 BoolOrExpr : OrExpr TOK_OpOr AndExpr
466 TRACE("Got OrExpr: \"%s $or$ %s\"\n", $1, $3);
467 $$=$1;
468 $$=xmlStrcat($$,U(" or "));
469 $$=xmlStrcat($$,$3);
470 xmlFree($3);
473 AndExpr : EqualityExpr
474 | BoolAndExpr
476 BoolAndExpr : AndExpr TOK_OpAnd EqualityExpr
478 TRACE("Got AndExpr: \"%s $and$ %s\"\n", $1, $3);
479 $$=$1;
480 $$=xmlStrcat($$,U(" and "));
481 $$=xmlStrcat($$,$3);
482 xmlFree($3);
485 EqualityExpr : RelationalExpr
486 | BoolEqualityExpr
488 BoolEqualityExpr : EqualityExpr TOK_OpEq RelationalExpr
490 TRACE("Got EqualityExpr: \"%s $eq$ %s\"\n", $1, $3);
491 $$=$1;
492 $$=xmlStrcat($$,U("="));
493 $$=xmlStrcat($$,$3);
494 xmlFree($3);
496 | EqualityExpr TOK_OpIEq RelationalExpr
498 TRACE("Got EqualityExpr: \"%s $ieq$ %s\"\n", $1, $3);
499 $$=xmlStrdup(U("OP_IEq("));
500 $$=xmlStrcat($$,$1);
501 xmlFree($1);
502 $$=xmlStrcat($$,U(","));
503 $$=xmlStrcat($$,$3);
504 xmlFree($3);
505 $$=xmlStrcat($$,U(")"));
507 | EqualityExpr TOK_OpNEq RelationalExpr
509 TRACE("Got EqualityExpr: \"%s $ne$ %s\"\n", $1, $3);
510 $$=$1;
511 $$=xmlStrcat($$,U("!="));
512 $$=xmlStrcat($$,$3);
513 xmlFree($3);
515 | EqualityExpr TOK_OpINEq RelationalExpr
517 TRACE("Got EqualityExpr: \"%s $ine$ %s\"\n", $1, $3);
518 $$=xmlStrdup(U("OP_INEq("));
519 $$=xmlStrcat($$,$1);
520 xmlFree($1);
521 $$=xmlStrcat($$,U(","));
522 $$=xmlStrcat($$,$3);
523 xmlFree($3);
524 $$=xmlStrcat($$,U(")"));
527 RelationalExpr : UnaryExpr
528 | BoolRelationalExpr
530 BoolRelationalExpr : RelationalExpr TOK_OpLt UnaryExpr
532 TRACE("Got RelationalExpr: \"%s $lt$ %s\"\n", $1, $3);
533 $$=$1;
534 $$=xmlStrcat($$,U("<"));
535 $$=xmlStrcat($$,$3);
536 xmlFree($3);
538 | RelationalExpr TOK_OpILt UnaryExpr
540 TRACE("Got RelationalExpr: \"%s $ilt$ %s\"\n", $1, $3);
541 $$=xmlStrdup(U("OP_ILt("));
542 $$=xmlStrcat($$,$1);
543 xmlFree($1);
544 $$=xmlStrcat($$,U(","));
545 $$=xmlStrcat($$,$3);
546 xmlFree($3);
547 $$=xmlStrcat($$,U(")"));
549 | RelationalExpr TOK_OpGt UnaryExpr
551 TRACE("Got RelationalExpr: \"%s $gt$ %s\"\n", $1, $3);
552 $$=$1;
553 $$=xmlStrcat($$,U(">"));
554 $$=xmlStrcat($$,$3);
555 xmlFree($3);
557 | RelationalExpr TOK_OpIGt UnaryExpr
559 TRACE("Got RelationalExpr: \"%s $igt$ %s\"\n", $1, $3);
560 $$=xmlStrdup(U("OP_IGt("));
561 $$=xmlStrcat($$,$1);
562 xmlFree($1);
563 $$=xmlStrcat($$,U(","));
564 $$=xmlStrcat($$,$3);
565 xmlFree($3);
566 $$=xmlStrcat($$,U(")"));
568 | RelationalExpr TOK_OpLEq UnaryExpr
570 TRACE("Got RelationalExpr: \"%s $le$ %s\"\n", $1, $3);
571 $$=$1;
572 $$=xmlStrcat($$,U("<="));
573 $$=xmlStrcat($$,$3);
574 xmlFree($3);
576 | RelationalExpr TOK_OpILEq UnaryExpr
578 TRACE("Got RelationalExpr: \"%s $ile$ %s\"\n", $1, $3);
579 $$=xmlStrdup(U("OP_ILEq("));
580 $$=xmlStrcat($$,$1);
581 xmlFree($1);
582 $$=xmlStrcat($$,U(","));
583 $$=xmlStrcat($$,$3);
584 xmlFree($3);
585 $$=xmlStrcat($$,U(")"));
587 | RelationalExpr TOK_OpGEq UnaryExpr
589 TRACE("Got RelationalExpr: \"%s $ge$ %s\"\n", $1, $3);
590 $$=$1;
591 $$=xmlStrcat($$,U(">="));
592 $$=xmlStrcat($$,$3);
593 xmlFree($3);
595 | RelationalExpr TOK_OpIGEq UnaryExpr
597 TRACE("Got RelationalExpr: \"%s $ige$ %s\"\n", $1, $3);
598 $$=xmlStrdup(U("OP_IGEq("));
599 $$=xmlStrcat($$,$1);
600 xmlFree($1);
601 $$=xmlStrcat($$,U(","));
602 $$=xmlStrcat($$,$3);
603 xmlFree($3);
604 $$=xmlStrcat($$,U(")"));
608 /* [3.5] Numbers */
609 UnaryExpr : UnionExpr
610 | BoolUnaryExpr
612 BoolUnaryExpr : TOK_OpNot UnaryExpr
614 TRACE("Got UnaryExpr: \"$not$ %s\"\n", $2);
615 $$=xmlStrdup(U(" not("));
616 $$=xmlStrcat($$,$2);
617 xmlFree($2);
618 $$=xmlStrcat($$,U(")"));
620 | TOK_OpAny Expr
622 TRACE("Got UnaryExpr: \"$any$ %s\"\n", $2);
623 $$=xmlStrdup(U("boolean("));
624 $$=xmlStrcat($$,$2);
625 xmlFree($2);
626 $$=xmlStrcat($$,U(")"));
628 | TOK_OpAll AllExpr
630 TRACE("Got UnaryExpr: \"$all$ %s\"\n", $2);
631 $$=xmlStrdup(U("not("));
632 $$=xmlStrcat($$,$2);
633 xmlFree($2);
634 $$=xmlStrcat($$,U(")"));
636 | TOK_OpAll
638 FIXME("Unrecognized $all$ expression - ignoring\n");
639 $$=xmlStrdup(U(""));
642 AllExpr : PathExpr TOK_OpEq PathExpr
644 $$=$1;
645 $$=xmlStrcat($$,U("!="));
646 $$=xmlStrcat($$,$3);
647 xmlFree($3);
649 | PathExpr TOK_OpNEq PathExpr
651 $$=$1;
652 $$=xmlStrcat($$,U("="));
653 $$=xmlStrcat($$,$3);
654 xmlFree($3);
656 | PathExpr TOK_OpLt PathExpr
658 $$=$1;
659 $$=xmlStrcat($$,U(">="));
660 $$=xmlStrcat($$,$3);
661 xmlFree($3);
663 | PathExpr TOK_OpLEq PathExpr
665 $$=$1;
666 $$=xmlStrcat($$,U(">"));
667 $$=xmlStrcat($$,$3);
668 xmlFree($3);
670 | PathExpr TOK_OpGt PathExpr
672 $$=$1;
673 $$=xmlStrcat($$,U("<="));
674 $$=xmlStrcat($$,$3);
675 xmlFree($3);
677 | PathExpr TOK_OpGEq PathExpr
679 $$=$1;
680 $$=xmlStrcat($$,U("<"));
681 $$=xmlStrcat($$,$3);
682 xmlFree($3);
684 | PathExpr TOK_OpIEq PathExpr
686 $$=xmlStrdup(U("OP_INEq("));
687 $$=xmlStrcat($$,$1);
688 xmlFree($1);
689 $$=xmlStrcat($$,U(","));
690 $$=xmlStrcat($$,$3);
691 xmlFree($3);
692 $$=xmlStrcat($$,U(")"));
694 | PathExpr TOK_OpINEq PathExpr
696 $$=xmlStrdup(U("OP_IEq("));
697 $$=xmlStrcat($$,$1);
698 xmlFree($1);
699 $$=xmlStrcat($$,U(","));
700 $$=xmlStrcat($$,$3);
701 xmlFree($3);
702 $$=xmlStrcat($$,U(")"));
704 | PathExpr TOK_OpILt PathExpr
706 $$=xmlStrdup(U("OP_IGEq("));
707 $$=xmlStrcat($$,$1);
708 xmlFree($1);
709 $$=xmlStrcat($$,U(","));
710 $$=xmlStrcat($$,$3);
711 xmlFree($3);
712 $$=xmlStrcat($$,U(")"));
714 | PathExpr TOK_OpILEq PathExpr
716 $$=xmlStrdup(U("OP_IGt("));
717 $$=xmlStrcat($$,$1);
718 xmlFree($1);
719 $$=xmlStrcat($$,U(","));
720 $$=xmlStrcat($$,$3);
721 xmlFree($3);
722 $$=xmlStrcat($$,U(")"));
724 | PathExpr TOK_OpIGt PathExpr
726 $$=xmlStrdup(U("OP_ILEq("));
727 $$=xmlStrcat($$,$1);
728 xmlFree($1);
729 $$=xmlStrcat($$,U(","));
730 $$=xmlStrcat($$,$3);
731 xmlFree($3);
732 $$=xmlStrcat($$,U(")"));
734 | PathExpr TOK_OpIGEq PathExpr
736 $$=xmlStrdup(U("OP_ILt("));
737 $$=xmlStrcat($$,$1);
738 xmlFree($1);
739 $$=xmlStrcat($$,U(","));
740 $$=xmlStrcat($$,$3);
741 xmlFree($3);
742 $$=xmlStrcat($$,U(")"));
748 #endif /* HAVE_LIBXML2 */