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 */