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
23 #include "wine/port.h"
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
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
75 /* Mostly verbatim from the w3c XML Namespaces standard.
76 * <http://www.w3.org/TR/REC-xml-names/> */
78 /* [4] Qualified Names */
82 PrefixedName : TOK_NCName TOK_Colon TOK_NCName
84 TRACE("Got PrefixedName: \"%s:%s\"\n", $1, $3);
86 $$=xmlStrcat($$,U(":"));
91 UnprefixedName : TOK_NCName
93 TRACE("Got UnprefixedName: \"%s\"\n", $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("/"));
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);
124 $$=xmlStrcat($$,U("/"));
128 | AbbreviatedRelativeLocationPath
130 /* [2.1] Location Steps */
131 Step : AxisSpecifier NodeTest Predicates
133 TRACE("Got Step: \"%s%s%s\"\n", $1, $2, $3);
140 | NodeTest Predicates
142 TRACE("Got Step: \"%s%s\"\n", $1, $2);
147 | AxisSpecifier NodeTest
149 TRACE("Got Step: \"%s%s\"\n", $1, $2);
158 AxisSpecifier : TOK_NCName TOK_Axis
160 TRACE("Got AxisSpecifier: \"%s::\"\n", $1);
162 $$=xmlStrcat($$,U("::"));
165 Attribute : '@' TOK_NCName
167 TRACE("Got Attribute: \"@%s\"\n", $2);
168 $$=xmlStrdup(U("@"));
174 /* [2.3] Node Tests */
180 TRACE("Got NameTest: \"*\"\n");
181 $$=xmlStrdup(U("*"));
183 | TOK_NCName TOK_Colon '*'
185 TRACE("Got NameTest: \"%s:*\"\n", $1);
187 $$=xmlStrcat($$,U(":*"));
189 | TOK_NCName TOK_Colon TOK_NCName
191 xmlChar const* registeredNsURI = xmlXPathNsLookup(p->ctx, $1);
192 TRACE("Got PrefixedName: \"%s:%s\"\n", $1, $3);
197 $$=xmlStrdup(NameTest_mod_pre);
201 $$=xmlStrcat($$,U(":"));
205 if (!registeredNsURI)
206 $$=xmlStrcat($$,NameTest_mod_post);
210 $$=xmlStrdup(NameTest_mod_pre);
213 $$=xmlStrcat($$,NameTest_mod_post);
215 /* [2.4] Predicates */
216 Predicates : Predicates Predicate
224 Predicate : '[' PredicateExpr ']'
226 TRACE("Got Predicate: \"[%s]\"\n", $2);
227 $$=xmlStrdup(U("["));
230 $$=xmlStrcat($$,U("]"));
233 PredicateExpr : TOK_Number
235 $$=xmlStrdup(U("index()="));
242 /* [2.5] Abbreviated Syntax */
243 AbbreviatedAbsoluteLocationPath : TOK_DblFSlash RelativeLocationPath
245 TRACE("Got AbbreviatedAbsoluteLocationPath: \"//%s\"\n", $2);
246 $$=xmlStrdup(U("//"));
251 AbbreviatedRelativeLocationPath : RelativeLocationPath TOK_DblFSlash Step
253 TRACE("Got AbbreviatedRelativeLocationPath: \"%s//%s\"\n", $1, $3);
255 $$=xmlStrcat($$,U("//"));
260 AbbreviatedStep : TOK_Parent
262 TRACE("Got AbbreviatedStep: \"..\"\n");
263 $$=xmlStrdup(U(".."));
267 TRACE("Got AbbreviatedStep: \".\"\n");
268 $$=xmlStrdup(U("."));
272 /* [3] Expressions */
276 BoolExpr : FunctionCall
283 PrimaryExpr : '(' Expr ')'
285 TRACE("Got PrimaryExpr: \"(%s)\"\n", $1);
286 $$=xmlStrdup(U("("));
289 $$=xmlStrcat($$,U(")"));
291 | PathExpr '!' FunctionCall
293 TRACE("Got PrimaryExpr: \"%s!%s\"\n", $1, $3);
295 $$=xmlStrcat($$,U("/"));
302 /* [3.2] Function Calls */
303 FunctionCall : QName '(' Arguments ')'
305 TRACE("Got FunctionCall: \"%s(%s)\"\n", $1, $3);
306 if (xmlStrEqual($1,U("ancestor")))
309 $$=xmlStrcat($$,U("::"));
313 else if (xmlStrEqual($1,U("attribute")))
317 $$=xmlStrdup(U("@*[name()="));
321 $$=xmlStrcat($$,U("]"));
325 /* XML_XPATH_INVALID_TYPE */
326 $$=xmlStrdup(U("error(1211, 'Error: attribute("));
330 $$=xmlStrcat($$,U("): invalid argument')"));
333 else if (xmlStrEqual($1,U("element")))
337 $$=xmlStrdup(U("node()[nodeType()=1][name()="));
341 $$=xmlStrcat($$,U("]"));
345 /* XML_XPATH_INVALID_TYPE */
346 $$=xmlStrdup(U("error(1211, 'Error: element("));
350 $$=xmlStrcat($$,U("): invalid argument')"));
356 $$=xmlStrcat($$,U("("));
359 $$=xmlStrcat($$,U(")"));
364 TRACE("Got FunctionCall: \"%s()\"\n", $1);
365 /* comment() & node() work the same in XPath */
366 if (xmlStrEqual($1,U("attribute")))
368 $$=xmlStrdup(U("@*"));
371 else if (xmlStrEqual($1,U("element")))
373 $$=xmlStrdup(U("node()[nodeType()=1]"));
376 else if (xmlStrEqual($1,U("pi")))
378 $$=xmlStrdup(U("processing-instruction()"));
381 else if (xmlStrEqual($1,U("textnode")))
383 $$=xmlStrdup(U("text()"));
389 $$=xmlStrcat($$,U("()"));
393 Arguments : Argument ',' Arguments
396 $$=xmlStrcat($$,U(","));
404 /* [3.3] Node-sets */
406 | UnionExpr '|' PathExpr
408 TRACE("Got UnionExpr: \"%s|%s\"\n", $1, $3);
410 $$=xmlStrcat($$,U("|"));
415 PathExpr : LocationPath
416 | FilterExpr TOK_FSlash RelativeLocationPath
418 TRACE("Got PathExpr: \"%s/%s\"\n", $1, $3);
420 $$=xmlStrcat($$,U("/"));
424 | FilterExpr TOK_DblFSlash RelativeLocationPath
426 TRACE("Got PathExpr: \"%s//%s\"\n", $1, $3);
428 $$=xmlStrcat($$,U("//"));
434 FilterExpr : PrimaryExpr
435 | FilterExpr Predicate
437 TRACE("Got FilterExpr: \"%s%s\"\n", $1, $2);
447 BoolOrExpr : OrExpr TOK_OpOr AndExpr
449 TRACE("Got OrExpr: \"%s $or$ %s\"\n", $1, $3);
451 $$=xmlStrcat($$,U(" or "));
456 AndExpr : EqualityExpr
459 BoolAndExpr : AndExpr TOK_OpAnd EqualityExpr
461 TRACE("Got AndExpr: \"%s $and$ %s\"\n", $1, $3);
463 $$=xmlStrcat($$,U(" and "));
468 EqualityExpr : RelationalExpr
471 BoolEqualityExpr : EqualityExpr TOK_OpEq RelationalExpr
473 TRACE("Got EqualityExpr: \"%s $eq$ %s\"\n", $1, $3);
475 $$=xmlStrcat($$,U("="));
479 | EqualityExpr TOK_OpIEq RelationalExpr
481 TRACE("Got EqualityExpr: \"%s $ieq$ %s\"\n", $1, $3);
482 $$=xmlStrdup(U("OP_IEq("));
485 $$=xmlStrcat($$,U(","));
488 $$=xmlStrcat($$,U(")"));
490 | EqualityExpr TOK_OpNEq RelationalExpr
492 TRACE("Got EqualityExpr: \"%s $ne$ %s\"\n", $1, $3);
494 $$=xmlStrcat($$,U("!="));
498 | EqualityExpr TOK_OpINEq RelationalExpr
500 TRACE("Got EqualityExpr: \"%s $ine$ %s\"\n", $1, $3);
501 $$=xmlStrdup(U("OP_INEq("));
504 $$=xmlStrcat($$,U(","));
507 $$=xmlStrcat($$,U(")"));
510 RelationalExpr : UnaryExpr
513 BoolRelationalExpr : RelationalExpr TOK_OpLt UnaryExpr
515 TRACE("Got RelationalExpr: \"%s $lt$ %s\"\n", $1, $3);
517 $$=xmlStrcat($$,U("<"));
521 | RelationalExpr TOK_OpILt UnaryExpr
523 TRACE("Got RelationalExpr: \"%s $ilt$ %s\"\n", $1, $3);
524 $$=xmlStrdup(U("OP_ILt("));
527 $$=xmlStrcat($$,U(","));
530 $$=xmlStrcat($$,U(")"));
532 | RelationalExpr TOK_OpGt UnaryExpr
534 TRACE("Got RelationalExpr: \"%s $gt$ %s\"\n", $1, $3);
536 $$=xmlStrcat($$,U(">"));
540 | RelationalExpr TOK_OpIGt UnaryExpr
542 TRACE("Got RelationalExpr: \"%s $igt$ %s\"\n", $1, $3);
543 $$=xmlStrdup(U("OP_IGt("));
546 $$=xmlStrcat($$,U(","));
549 $$=xmlStrcat($$,U(")"));
551 | RelationalExpr TOK_OpLEq UnaryExpr
553 TRACE("Got RelationalExpr: \"%s $le$ %s\"\n", $1, $3);
555 $$=xmlStrcat($$,U("<="));
559 | RelationalExpr TOK_OpILEq UnaryExpr
561 TRACE("Got RelationalExpr: \"%s $ile$ %s\"\n", $1, $3);
562 $$=xmlStrdup(U("OP_ILEq("));
565 $$=xmlStrcat($$,U(","));
568 $$=xmlStrcat($$,U(")"));
570 | RelationalExpr TOK_OpGEq UnaryExpr
572 TRACE("Got RelationalExpr: \"%s $ge$ %s\"\n", $1, $3);
574 $$=xmlStrcat($$,U(">="));
578 | RelationalExpr TOK_OpIGEq UnaryExpr
580 TRACE("Got RelationalExpr: \"%s $ige$ %s\"\n", $1, $3);
581 $$=xmlStrdup(U("OP_IGEq("));
584 $$=xmlStrcat($$,U(","));
587 $$=xmlStrcat($$,U(")"));
592 UnaryExpr : UnionExpr
595 BoolUnaryExpr : TOK_OpNot UnaryExpr
597 TRACE("Got UnaryExpr: \"$not$ %s\"\n", $2);
598 $$=xmlStrdup(U(" not("));
601 $$=xmlStrcat($$,U(")"));
605 TRACE("Got UnaryExpr: \"$any$ %s\"\n", $2);
606 $$=xmlStrdup(U("boolean("));
609 $$=xmlStrcat($$,U(")"));
613 TRACE("Got UnaryExpr: \"$all$ %s\"\n", $2);
614 $$=xmlStrdup(U("not("));
617 $$=xmlStrcat($$,U(")"));
621 FIXME("Unrecognized $all$ expression - ignoring\n");
625 AllExpr : PathExpr TOK_OpEq PathExpr
628 $$=xmlStrcat($$,U("!="));
632 | PathExpr TOK_OpNEq PathExpr
635 $$=xmlStrcat($$,U("="));
639 | PathExpr TOK_OpLt PathExpr
642 $$=xmlStrcat($$,U(">="));
646 | PathExpr TOK_OpLEq PathExpr
649 $$=xmlStrcat($$,U(">"));
653 | PathExpr TOK_OpGt PathExpr
656 $$=xmlStrcat($$,U("<="));
660 | PathExpr TOK_OpGEq PathExpr
663 $$=xmlStrcat($$,U("<"));
667 | PathExpr TOK_OpIEq PathExpr
669 $$=xmlStrdup(U("OP_INEq("));
672 $$=xmlStrcat($$,U(","));
675 $$=xmlStrcat($$,U(")"));
677 | PathExpr TOK_OpINEq PathExpr
679 $$=xmlStrdup(U("OP_IEq("));
682 $$=xmlStrcat($$,U(","));
685 $$=xmlStrcat($$,U(")"));
687 | PathExpr TOK_OpILt PathExpr
689 $$=xmlStrdup(U("OP_IGEq("));
692 $$=xmlStrcat($$,U(","));
695 $$=xmlStrcat($$,U(")"));
697 | PathExpr TOK_OpILEq PathExpr
699 $$=xmlStrdup(U("OP_IGt("));
702 $$=xmlStrcat($$,U(","));
705 $$=xmlStrcat($$,U(")"));
707 | PathExpr TOK_OpIGt PathExpr
709 $$=xmlStrdup(U("OP_ILEq("));
712 $$=xmlStrcat($$,U(","));
715 $$=xmlStrcat($$,U(")"));
717 | PathExpr TOK_OpIGEq PathExpr
719 $$=xmlStrdup(U("OP_ILt("));
722 $$=xmlStrcat($$,U(","));
725 $$=xmlStrcat($$,U(")"));
731 void xslpattern_error(parser_param* param, void const* scanner, char const* msg)
744 msg, param->yyscanner, param->ctx, param->in, param->pos,
745 param->len, param->out, ++param->err, scanner);
749 #endif /* HAVE_LIBXML2 */