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>
29 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
32 static const xmlChar NameTest_mod_pre[] = "*[name()='";
33 static const xmlChar NameTest_mod_post[] = "']";
35 #define U(str) BAD_CAST str
37 static inline BOOL is_literal(xmlChar const* tok)
39 return (tok && tok[0] && tok[1] &&
40 tok[0]== tok[xmlStrlen(tok)-1] &&
41 (tok[0] == '\'' || tok[0] == '"'));
46 %token TOK_Parent TOK_Self TOK_DblFSlash TOK_FSlash TOK_Axis TOK_Colon
47 %token TOK_OpAnd TOK_OpOr TOK_OpNot
48 %token TOK_OpEq TOK_OpIEq TOK_OpNEq TOK_OpINEq
49 %token TOK_OpLt TOK_OpILt TOK_OpGt TOK_OpIGt TOK_OpLEq TOK_OpILEq TOK_OpGEq TOK_OpIGEq
50 %token TOK_OpAll TOK_OpAny
51 %token TOK_NCName TOK_Literal TOK_Number
56 %parse-param {parser_param* p}
57 %parse-param {void* scanner}
58 %lex-param {yyscan_t* scanner}
60 %left TOK_OpAnd TOK_OpOr
61 %left TOK_OpEq TOK_OpIEq TOK_OpNEq TOK_OpINEq
62 %left TOK_OpLt TOK_OpILt TOK_OpGt TOK_OpIGt TOK_OpLEq TOK_OpILEq TOK_OpGEq TOK_OpIGEq
74 /* Mostly verbatim from the w3c XML Namespaces standard.
75 * <http://www.w3.org/TR/REC-xml-names/> */
77 /* [4] Qualified Names */
81 PrefixedName : TOK_NCName TOK_Colon TOK_NCName
83 TRACE("Got PrefixedName: \"%s:%s\"\n", $1, $3);
85 $$=xmlStrcat($$,U(":"));
90 UnprefixedName : TOK_NCName
92 TRACE("Got UnprefixedName: \"%s\"\n", $1);
97 /* Based on the w3c XPath standard, adapted where needed.
98 * <http://www.w3.org/TR/xpath/> */
100 /* [2] Location Paths */
101 LocationPath : RelativeLocationPath
102 | AbsoluteLocationPath
104 AbsoluteLocationPath : TOK_FSlash RelativeLocationPath
106 TRACE("Got AbsoluteLocationPath: \"/%s\"\n", $2);
107 $$=xmlStrdup(U("/"));
113 TRACE("Got AbsoluteLocationPath: \"/\"\n");
114 $$=xmlStrdup(U("/"));
116 | AbbreviatedAbsoluteLocationPath
118 RelativeLocationPath : Step
119 | RelativeLocationPath TOK_FSlash Step
121 TRACE("Got RelativeLocationPath: \"%s/%s\"\n", $1, $3);
123 $$=xmlStrcat($$,U("/"));
127 | AbbreviatedRelativeLocationPath
129 /* [2.1] Location Steps */
130 Step : AxisSpecifier NodeTest Predicates
132 TRACE("Got Step: \"%s%s%s\"\n", $1, $2, $3);
139 | NodeTest Predicates
141 TRACE("Got Step: \"%s%s\"\n", $1, $2);
146 | AxisSpecifier NodeTest
148 TRACE("Got Step: \"%s%s\"\n", $1, $2);
157 AxisSpecifier : TOK_NCName TOK_Axis
159 TRACE("Got AxisSpecifier: \"%s::\"\n", $1);
161 $$=xmlStrcat($$,U("::"));
164 Attribute : '@' TOK_NCName
166 TRACE("Got Attribute: \"@%s\"\n", $2);
167 $$=xmlStrdup(U("@"));
173 /* [2.3] Node Tests */
179 TRACE("Got NameTest: \"*\"\n");
180 $$=xmlStrdup(U("*"));
182 | TOK_NCName TOK_Colon '*'
184 TRACE("Got NameTest: \"%s:*\"\n", $1);
186 $$=xmlStrcat($$,U(":*"));
188 | TOK_NCName TOK_Colon TOK_NCName
190 xmlChar const* registeredNsURI = xmlXPathNsLookup(p->ctx, $1);
191 TRACE("Got PrefixedName: \"%s:%s\"\n", $1, $3);
196 $$=xmlStrdup(NameTest_mod_pre);
200 $$=xmlStrcat($$,U(":"));
204 if (!registeredNsURI)
205 $$=xmlStrcat($$,NameTest_mod_post);
209 $$=xmlStrdup(NameTest_mod_pre);
212 $$=xmlStrcat($$,NameTest_mod_post);
214 /* [2.4] Predicates */
215 Predicates : Predicates Predicate
223 Predicate : '[' PredicateExpr ']'
225 TRACE("Got Predicate: \"[%s]\"\n", $2);
226 $$=xmlStrdup(U("["));
229 $$=xmlStrcat($$,U("]"));
232 PredicateExpr : TOK_Number
234 $$=xmlStrdup(U("index()="));
241 /* [2.5] Abbreviated Syntax */
242 AbbreviatedAbsoluteLocationPath : TOK_DblFSlash RelativeLocationPath
244 TRACE("Got AbbreviatedAbsoluteLocationPath: \"//%s\"\n", $2);
245 $$=xmlStrdup(U("//"));
250 AbbreviatedRelativeLocationPath : RelativeLocationPath TOK_DblFSlash Step
252 TRACE("Got AbbreviatedRelativeLocationPath: \"%s//%s\"\n", $1, $3);
254 $$=xmlStrcat($$,U("//"));
259 AbbreviatedStep : TOK_Parent
261 TRACE("Got AbbreviatedStep: \"..\"\n");
262 $$=xmlStrdup(U(".."));
266 TRACE("Got AbbreviatedStep: \".\"\n");
267 $$=xmlStrdup(U("."));
271 /* [3] Expressions */
275 BoolExpr : FunctionCall
282 PrimaryExpr : '(' Expr ')'
284 TRACE("Got PrimaryExpr: \"(%s)\"\n", $1);
285 $$=xmlStrdup(U("("));
288 $$=xmlStrcat($$,U(")"));
290 | PathExpr '!' FunctionCall
292 TRACE("Got PrimaryExpr: \"%s!%s\"\n", $1, $3);
294 $$=xmlStrcat($$,U("/"));
301 /* [3.2] Function Calls */
302 FunctionCall : QName '(' Arguments ')'
304 TRACE("Got FunctionCall: \"%s(%s)\"\n", $1, $3);
305 if (xmlStrEqual($1,U("ancestor")))
308 $$=xmlStrcat($$,U("::"));
312 else if (xmlStrEqual($1,U("attribute")))
316 $$=xmlStrdup(U("@*[name()="));
320 $$=xmlStrcat($$,U("]"));
324 /* XML_XPATH_INVALID_TYPE */
325 $$=xmlStrdup(U("error(1211, 'Error: attribute("));
329 $$=xmlStrcat($$,U("): invalid argument')"));
332 else if (xmlStrEqual($1,U("element")))
336 $$=xmlStrdup(U("node()[nodeType()=1][name()="));
340 $$=xmlStrcat($$,U("]"));
344 /* XML_XPATH_INVALID_TYPE */
345 $$=xmlStrdup(U("error(1211, 'Error: element("));
349 $$=xmlStrcat($$,U("): invalid argument')"));
355 $$=xmlStrcat($$,U("("));
358 $$=xmlStrcat($$,U(")"));
363 TRACE("Got FunctionCall: \"%s()\"\n", $1);
364 /* comment() & node() work the same in XPath */
365 if (xmlStrEqual($1,U("attribute")))
367 $$=xmlStrdup(U("@*"));
370 else if (xmlStrEqual($1,U("element")))
372 $$=xmlStrdup(U("node()[nodeType()=1]"));
375 else if (xmlStrEqual($1,U("pi")))
377 $$=xmlStrdup(U("processing-instruction()"));
380 else if (xmlStrEqual($1,U("textnode")))
382 $$=xmlStrdup(U("text()"));
388 $$=xmlStrcat($$,U("()"));
392 Arguments : Argument ',' Arguments
395 $$=xmlStrcat($$,U(","));
403 /* [3.3] Node-sets */
405 | UnionExpr '|' PathExpr
407 TRACE("Got UnionExpr: \"%s|%s\"\n", $1, $3);
409 $$=xmlStrcat($$,U("|"));
414 PathExpr : LocationPath
415 | FilterExpr TOK_FSlash RelativeLocationPath
417 TRACE("Got PathExpr: \"%s/%s\"\n", $1, $3);
419 $$=xmlStrcat($$,U("/"));
423 | FilterExpr TOK_DblFSlash RelativeLocationPath
425 TRACE("Got PathExpr: \"%s//%s\"\n", $1, $3);
427 $$=xmlStrcat($$,U("//"));
433 FilterExpr : PrimaryExpr
434 | FilterExpr Predicate
436 TRACE("Got FilterExpr: \"%s%s\"\n", $1, $2);
446 BoolOrExpr : OrExpr TOK_OpOr AndExpr
448 TRACE("Got OrExpr: \"%s $or$ %s\"\n", $1, $3);
450 $$=xmlStrcat($$,U(" or "));
455 AndExpr : EqualityExpr
458 BoolAndExpr : AndExpr TOK_OpAnd EqualityExpr
460 TRACE("Got AndExpr: \"%s $and$ %s\"\n", $1, $3);
462 $$=xmlStrcat($$,U(" and "));
467 EqualityExpr : RelationalExpr
470 BoolEqualityExpr : EqualityExpr TOK_OpEq RelationalExpr
472 TRACE("Got EqualityExpr: \"%s $eq$ %s\"\n", $1, $3);
474 $$=xmlStrcat($$,U("="));
478 | EqualityExpr TOK_OpIEq RelationalExpr
480 TRACE("Got EqualityExpr: \"%s $ieq$ %s\"\n", $1, $3);
481 $$=xmlStrdup(U("OP_IEq("));
484 $$=xmlStrcat($$,U(","));
487 $$=xmlStrcat($$,U(")"));
489 | EqualityExpr TOK_OpNEq RelationalExpr
491 TRACE("Got EqualityExpr: \"%s $ne$ %s\"\n", $1, $3);
493 $$=xmlStrcat($$,U("!="));
497 | EqualityExpr TOK_OpINEq RelationalExpr
499 TRACE("Got EqualityExpr: \"%s $ine$ %s\"\n", $1, $3);
500 $$=xmlStrdup(U("OP_INEq("));
503 $$=xmlStrcat($$,U(","));
506 $$=xmlStrcat($$,U(")"));
509 RelationalExpr : UnaryExpr
512 BoolRelationalExpr : RelationalExpr TOK_OpLt UnaryExpr
514 TRACE("Got RelationalExpr: \"%s $lt$ %s\"\n", $1, $3);
516 $$=xmlStrcat($$,U("<"));
520 | RelationalExpr TOK_OpILt UnaryExpr
522 TRACE("Got RelationalExpr: \"%s $ilt$ %s\"\n", $1, $3);
523 $$=xmlStrdup(U("OP_ILt("));
526 $$=xmlStrcat($$,U(","));
529 $$=xmlStrcat($$,U(")"));
531 | RelationalExpr TOK_OpGt UnaryExpr
533 TRACE("Got RelationalExpr: \"%s $gt$ %s\"\n", $1, $3);
535 $$=xmlStrcat($$,U(">"));
539 | RelationalExpr TOK_OpIGt UnaryExpr
541 TRACE("Got RelationalExpr: \"%s $igt$ %s\"\n", $1, $3);
542 $$=xmlStrdup(U("OP_IGt("));
545 $$=xmlStrcat($$,U(","));
548 $$=xmlStrcat($$,U(")"));
550 | RelationalExpr TOK_OpLEq UnaryExpr
552 TRACE("Got RelationalExpr: \"%s $le$ %s\"\n", $1, $3);
554 $$=xmlStrcat($$,U("<="));
558 | RelationalExpr TOK_OpILEq UnaryExpr
560 TRACE("Got RelationalExpr: \"%s $ile$ %s\"\n", $1, $3);
561 $$=xmlStrdup(U("OP_ILEq("));
564 $$=xmlStrcat($$,U(","));
567 $$=xmlStrcat($$,U(")"));
569 | RelationalExpr TOK_OpGEq UnaryExpr
571 TRACE("Got RelationalExpr: \"%s $ge$ %s\"\n", $1, $3);
573 $$=xmlStrcat($$,U(">="));
577 | RelationalExpr TOK_OpIGEq UnaryExpr
579 TRACE("Got RelationalExpr: \"%s $ige$ %s\"\n", $1, $3);
580 $$=xmlStrdup(U("OP_IGEq("));
583 $$=xmlStrcat($$,U(","));
586 $$=xmlStrcat($$,U(")"));
591 UnaryExpr : UnionExpr
594 BoolUnaryExpr : TOK_OpNot UnaryExpr
596 TRACE("Got UnaryExpr: \"$not$ %s\"\n", $2);
597 $$=xmlStrdup(U(" not("));
600 $$=xmlStrcat($$,U(")"));
604 TRACE("Got UnaryExpr: \"$any$ %s\"\n", $2);
605 $$=xmlStrdup(U("boolean("));
608 $$=xmlStrcat($$,U(")"));
612 TRACE("Got UnaryExpr: \"$all$ %s\"\n", $2);
613 $$=xmlStrdup(U("not("));
616 $$=xmlStrcat($$,U(")"));
620 FIXME("Unrecognized $all$ expression - ignoring\n");
624 AllExpr : PathExpr TOK_OpEq PathExpr
627 $$=xmlStrcat($$,U("!="));
631 | PathExpr TOK_OpNEq PathExpr
634 $$=xmlStrcat($$,U("="));
638 | PathExpr TOK_OpLt PathExpr
641 $$=xmlStrcat($$,U(">="));
645 | PathExpr TOK_OpLEq PathExpr
648 $$=xmlStrcat($$,U(">"));
652 | PathExpr TOK_OpGt PathExpr
655 $$=xmlStrcat($$,U("<="));
659 | PathExpr TOK_OpGEq PathExpr
662 $$=xmlStrcat($$,U("<"));
666 | PathExpr TOK_OpIEq PathExpr
668 $$=xmlStrdup(U("OP_INEq("));
671 $$=xmlStrcat($$,U(","));
674 $$=xmlStrcat($$,U(")"));
676 | PathExpr TOK_OpINEq PathExpr
678 $$=xmlStrdup(U("OP_IEq("));
681 $$=xmlStrcat($$,U(","));
684 $$=xmlStrcat($$,U(")"));
686 | PathExpr TOK_OpILt PathExpr
688 $$=xmlStrdup(U("OP_IGEq("));
691 $$=xmlStrcat($$,U(","));
694 $$=xmlStrcat($$,U(")"));
696 | PathExpr TOK_OpILEq PathExpr
698 $$=xmlStrdup(U("OP_IGt("));
701 $$=xmlStrcat($$,U(","));
704 $$=xmlStrcat($$,U(")"));
706 | PathExpr TOK_OpIGt PathExpr
708 $$=xmlStrdup(U("OP_ILEq("));
711 $$=xmlStrcat($$,U(","));
714 $$=xmlStrcat($$,U(")"));
716 | PathExpr TOK_OpIGEq PathExpr
718 $$=xmlStrdup(U("OP_ILt("));
721 $$=xmlStrcat($$,U(","));
724 $$=xmlStrcat($$,U(")"));
730 void xslpattern_error(parser_param* param, void const* scanner, char const* msg)
743 msg, param->yyscanner, param->ctx, param->in, param->pos,
744 param->len, param->out, ++param->err, scanner);
748 #endif /* HAVE_LIBXML2 */