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] == '"'));
45 static void xslpattern_error(parser_param* param, void const* scanner, char const* msg)
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
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
92 /* Mostly verbatim from the w3c XML Namespaces standard.
93 * <http://www.w3.org/TR/REC-xml-names/> */
95 /* [4] Qualified Names */
99 PrefixedName : TOK_NCName TOK_Colon TOK_NCName
101 TRACE("Got PrefixedName: \"%s:%s\"\n", $1, $3);
103 $$=xmlStrcat($$,U(":"));
108 UnprefixedName : TOK_NCName
110 TRACE("Got UnprefixedName: \"%s\"\n", $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("/"));
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);
141 $$=xmlStrcat($$,U("/"));
145 | AbbreviatedRelativeLocationPath
147 /* [2.1] Location Steps */
148 Step : AxisSpecifier NodeTest Predicates
150 TRACE("Got Step: \"%s%s%s\"\n", $1, $2, $3);
157 | NodeTest Predicates
159 TRACE("Got Step: \"%s%s\"\n", $1, $2);
164 | AxisSpecifier NodeTest
166 TRACE("Got Step: \"%s%s\"\n", $1, $2);
175 AxisSpecifier : TOK_NCName TOK_Axis
177 TRACE("Got AxisSpecifier: \"%s::\"\n", $1);
179 $$=xmlStrcat($$,U("::"));
182 Attribute : '@' QName
184 TRACE("Got Attribute: \"@%s\"\n", $2);
185 $$=xmlStrdup(U("@"));
191 /* [2.3] Node Tests */
197 TRACE("Got NameTest: \"*\"\n");
198 $$=xmlStrdup(U("*"));
200 | TOK_NCName TOK_Colon '*'
202 TRACE("Got NameTest: \"%s:*\"\n", $1);
204 $$=xmlStrcat($$,U(":*"));
206 | TOK_NCName TOK_Colon TOK_NCName
208 xmlChar const* registeredNsURI = xmlXPathNsLookup(p->ctx, $1);
209 TRACE("Got PrefixedName: \"%s:%s\"\n", $1, $3);
214 $$=xmlStrdup(NameTest_mod_pre);
218 $$=xmlStrcat($$,U(":"));
222 if (!registeredNsURI)
223 $$=xmlStrcat($$,NameTest_mod_post);
227 $$=xmlStrdup(NameTest_mod_pre);
230 $$=xmlStrcat($$,NameTest_mod_post);
232 /* [2.4] Predicates */
233 Predicates : Predicates Predicate
241 Predicate : '[' PredicateExpr ']'
243 TRACE("Got Predicate: \"[%s]\"\n", $2);
244 $$=xmlStrdup(U("["));
247 $$=xmlStrcat($$,U("]"));
250 PredicateExpr : TOK_Number
252 $$=xmlStrdup(U("index()="));
260 /* [2.5] Abbreviated Syntax */
261 AbbreviatedAbsoluteLocationPath : TOK_DblFSlash RelativeLocationPath
263 TRACE("Got AbbreviatedAbsoluteLocationPath: \"//%s\"\n", $2);
264 $$=xmlStrdup(U("//"));
269 AbbreviatedRelativeLocationPath : RelativeLocationPath TOK_DblFSlash Step
271 TRACE("Got AbbreviatedRelativeLocationPath: \"%s//%s\"\n", $1, $3);
273 $$=xmlStrcat($$,U("//"));
278 AbbreviatedStep : TOK_Parent
280 TRACE("Got AbbreviatedStep: \"..\"\n");
281 $$=xmlStrdup(U(".."));
285 TRACE("Got AbbreviatedStep: \".\"\n");
286 $$=xmlStrdup(U("."));
290 /* [3] Expressions */
294 BoolExpr : FunctionCall
301 PrimaryExpr : '(' Expr ')'
303 TRACE("Got PrimaryExpr: \"(%s)\"\n", $1);
304 $$=xmlStrdup(U("("));
307 $$=xmlStrcat($$,U(")"));
309 | PathExpr '!' FunctionCall
311 TRACE("Got PrimaryExpr: \"%s!%s\"\n", $1, $3);
313 $$=xmlStrcat($$,U("/"));
320 /* [3.2] Function Calls */
321 FunctionCall : QName '(' Arguments ')'
323 TRACE("Got FunctionCall: \"%s(%s)\"\n", $1, $3);
324 if (xmlStrEqual($1,U("ancestor")))
327 $$=xmlStrcat($$,U("::"));
331 else if (xmlStrEqual($1,U("attribute")))
335 $$=xmlStrdup(U("@*[name()="));
339 $$=xmlStrcat($$,U("]"));
343 /* XML_XPATH_INVALID_TYPE */
344 $$=xmlStrdup(U("error(1211, 'Error: attribute("));
348 $$=xmlStrcat($$,U("): invalid argument')"));
351 else if (xmlStrEqual($1,U("element")))
355 $$=xmlStrdup(U("node()[nodeType()=1][name()="));
359 $$=xmlStrcat($$,U("]"));
363 /* XML_XPATH_INVALID_TYPE */
364 $$=xmlStrdup(U("error(1211, 'Error: element("));
368 $$=xmlStrcat($$,U("): invalid argument')"));
374 $$=xmlStrcat($$,U("("));
377 $$=xmlStrcat($$,U(")"));
382 TRACE("Got FunctionCall: \"%s()\"\n", $1);
383 /* comment() & node() work the same in XPath */
384 if (xmlStrEqual($1,U("attribute")))
386 $$=xmlStrdup(U("@*"));
389 else if (xmlStrEqual($1,U("element")))
391 $$=xmlStrdup(U("node()[nodeType()=1]"));
394 else if (xmlStrEqual($1,U("pi")))
396 $$=xmlStrdup(U("processing-instruction()"));
399 else if (xmlStrEqual($1,U("textnode")))
401 $$=xmlStrdup(U("text()"));
407 $$=xmlStrcat($$,U("()"));
411 Arguments : Argument ',' Arguments
414 $$=xmlStrcat($$,U(","));
422 /* [3.3] Node-sets */
424 | UnionExpr '|' PathExpr
426 TRACE("Got UnionExpr: \"%s|%s\"\n", $1, $3);
428 $$=xmlStrcat($$,U("|"));
433 PathExpr : LocationPath
434 | FilterExpr TOK_FSlash RelativeLocationPath
436 TRACE("Got PathExpr: \"%s/%s\"\n", $1, $3);
438 $$=xmlStrcat($$,U("/"));
442 | FilterExpr TOK_DblFSlash RelativeLocationPath
444 TRACE("Got PathExpr: \"%s//%s\"\n", $1, $3);
446 $$=xmlStrcat($$,U("//"));
452 FilterExpr : PrimaryExpr
453 | FilterExpr Predicate
455 TRACE("Got FilterExpr: \"%s%s\"\n", $1, $2);
465 BoolOrExpr : OrExpr TOK_OpOr AndExpr
467 TRACE("Got OrExpr: \"%s $or$ %s\"\n", $1, $3);
469 $$=xmlStrcat($$,U(" or "));
474 AndExpr : EqualityExpr
477 BoolAndExpr : AndExpr TOK_OpAnd EqualityExpr
479 TRACE("Got AndExpr: \"%s $and$ %s\"\n", $1, $3);
481 $$=xmlStrcat($$,U(" and "));
486 EqualityExpr : RelationalExpr
489 BoolEqualityExpr : EqualityExpr TOK_OpEq RelationalExpr
491 TRACE("Got EqualityExpr: \"%s $eq$ %s\"\n", $1, $3);
493 $$=xmlStrcat($$,U("="));
497 | EqualityExpr TOK_OpIEq RelationalExpr
499 TRACE("Got EqualityExpr: \"%s $ieq$ %s\"\n", $1, $3);
500 $$=xmlStrdup(U("OP_IEq("));
503 $$=xmlStrcat($$,U(","));
506 $$=xmlStrcat($$,U(")"));
508 | EqualityExpr TOK_OpNEq RelationalExpr
510 TRACE("Got EqualityExpr: \"%s $ne$ %s\"\n", $1, $3);
512 $$=xmlStrcat($$,U("!="));
516 | EqualityExpr TOK_OpINEq RelationalExpr
518 TRACE("Got EqualityExpr: \"%s $ine$ %s\"\n", $1, $3);
519 $$=xmlStrdup(U("OP_INEq("));
522 $$=xmlStrcat($$,U(","));
525 $$=xmlStrcat($$,U(")"));
528 RelationalExpr : UnaryExpr
531 BoolRelationalExpr : RelationalExpr TOK_OpLt UnaryExpr
533 TRACE("Got RelationalExpr: \"%s $lt$ %s\"\n", $1, $3);
535 $$=xmlStrcat($$,U("<"));
539 | RelationalExpr TOK_OpILt UnaryExpr
541 TRACE("Got RelationalExpr: \"%s $ilt$ %s\"\n", $1, $3);
542 $$=xmlStrdup(U("OP_ILt("));
545 $$=xmlStrcat($$,U(","));
548 $$=xmlStrcat($$,U(")"));
550 | RelationalExpr TOK_OpGt UnaryExpr
552 TRACE("Got RelationalExpr: \"%s $gt$ %s\"\n", $1, $3);
554 $$=xmlStrcat($$,U(">"));
558 | RelationalExpr TOK_OpIGt UnaryExpr
560 TRACE("Got RelationalExpr: \"%s $igt$ %s\"\n", $1, $3);
561 $$=xmlStrdup(U("OP_IGt("));
564 $$=xmlStrcat($$,U(","));
567 $$=xmlStrcat($$,U(")"));
569 | RelationalExpr TOK_OpLEq UnaryExpr
571 TRACE("Got RelationalExpr: \"%s $le$ %s\"\n", $1, $3);
573 $$=xmlStrcat($$,U("<="));
577 | RelationalExpr TOK_OpILEq UnaryExpr
579 TRACE("Got RelationalExpr: \"%s $ile$ %s\"\n", $1, $3);
580 $$=xmlStrdup(U("OP_ILEq("));
583 $$=xmlStrcat($$,U(","));
586 $$=xmlStrcat($$,U(")"));
588 | RelationalExpr TOK_OpGEq UnaryExpr
590 TRACE("Got RelationalExpr: \"%s $ge$ %s\"\n", $1, $3);
592 $$=xmlStrcat($$,U(">="));
596 | RelationalExpr TOK_OpIGEq UnaryExpr
598 TRACE("Got RelationalExpr: \"%s $ige$ %s\"\n", $1, $3);
599 $$=xmlStrdup(U("OP_IGEq("));
602 $$=xmlStrcat($$,U(","));
605 $$=xmlStrcat($$,U(")"));
610 UnaryExpr : UnionExpr
613 BoolUnaryExpr : TOK_OpNot UnaryExpr
615 TRACE("Got UnaryExpr: \"$not$ %s\"\n", $2);
616 $$=xmlStrdup(U(" not("));
619 $$=xmlStrcat($$,U(")"));
623 TRACE("Got UnaryExpr: \"$any$ %s\"\n", $2);
624 $$=xmlStrdup(U("boolean("));
627 $$=xmlStrcat($$,U(")"));
631 TRACE("Got UnaryExpr: \"$all$ %s\"\n", $2);
632 $$=xmlStrdup(U("not("));
635 $$=xmlStrcat($$,U(")"));
639 FIXME("Unrecognized $all$ expression - ignoring\n");
643 AllExpr : PathExpr TOK_OpEq PathExpr
646 $$=xmlStrcat($$,U("!="));
650 | PathExpr TOK_OpNEq PathExpr
653 $$=xmlStrcat($$,U("="));
657 | PathExpr TOK_OpLt PathExpr
660 $$=xmlStrcat($$,U(">="));
664 | PathExpr TOK_OpLEq PathExpr
667 $$=xmlStrcat($$,U(">"));
671 | PathExpr TOK_OpGt PathExpr
674 $$=xmlStrcat($$,U("<="));
678 | PathExpr TOK_OpGEq PathExpr
681 $$=xmlStrcat($$,U("<"));
685 | PathExpr TOK_OpIEq PathExpr
687 $$=xmlStrdup(U("OP_INEq("));
690 $$=xmlStrcat($$,U(","));
693 $$=xmlStrcat($$,U(")"));
695 | PathExpr TOK_OpINEq PathExpr
697 $$=xmlStrdup(U("OP_IEq("));
700 $$=xmlStrcat($$,U(","));
703 $$=xmlStrcat($$,U(")"));
705 | PathExpr TOK_OpILt PathExpr
707 $$=xmlStrdup(U("OP_IGEq("));
710 $$=xmlStrcat($$,U(","));
713 $$=xmlStrcat($$,U(")"));
715 | PathExpr TOK_OpILEq PathExpr
717 $$=xmlStrdup(U("OP_IGt("));
720 $$=xmlStrcat($$,U(","));
723 $$=xmlStrcat($$,U(")"));
725 | PathExpr TOK_OpIGt PathExpr
727 $$=xmlStrdup(U("OP_ILEq("));
730 $$=xmlStrcat($$,U(","));
733 $$=xmlStrcat($$,U(")"));
735 | PathExpr TOK_OpIGEq PathExpr
737 $$=xmlStrdup(U("OP_ILt("));
740 $$=xmlStrcat($$,U(","));
743 $$=xmlStrcat($$,U(")"));
749 #endif /* HAVE_LIBXML2 */