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 "xslpattern.h"
23 #include <libxml/xpathInternals.h>
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL
(msxml
);
29 static const xmlChar NameTest_mod_pre
[] = "*[name()='";
30 static const xmlChar NameTest_mod_post
[] = "']";
32 #define U(str) BAD_CAST str
34 static inline BOOL is_literal
(xmlChar
const* tok
)
36 return
(tok
&& tok
[0] && tok
[1] &&
37 tok
[0]== tok
[xmlStrlen
(tok
)-1] &&
38 (tok
[0] == '\'' || tok
[0] == '"'));
41 static void xslpattern_error
(parser_param
* param
, void const* scanner
, char const* msg
)
55 msg
, param
->yyscanner
, param
->ctx
, param
->in
, param
->pos
,
56 param
->len
, param
->out
, param
->err
, scanner
);
61 %token TOK_Parent TOK_Self TOK_DblFSlash TOK_FSlash TOK_Axis TOK_Colon
62 %token TOK_OpAnd TOK_OpOr TOK_OpNot
63 %token TOK_OpEq TOK_OpIEq TOK_OpNEq TOK_OpINEq
64 %token TOK_OpLt TOK_OpILt TOK_OpGt TOK_OpIGt TOK_OpLEq TOK_OpILEq TOK_OpGEq TOK_OpIGEq
65 %token TOK_OpAll TOK_OpAny
66 %token TOK_NCName TOK_Literal TOK_Number
70 %define api.prefix
{xslpattern_
}
72 %parse
-param
{parser_param
* p
}
73 %parse
-param
{void* scanner
}
74 %lex
-param
{yyscan_t
* scanner
}
76 %left TOK_OpAnd TOK_OpOr
77 %left TOK_OpEq TOK_OpIEq TOK_OpNEq TOK_OpINEq
78 %left TOK_OpLt TOK_OpILt TOK_OpGt TOK_OpIGt TOK_OpLEq TOK_OpILEq TOK_OpGEq TOK_OpIGEq
90 /* Mostly verbatim from the w3c XML Namespaces standard.
91 * <http://www.w3.org/TR/REC-xml-names/> */
93 /* [4] Qualified Names */
97 PrefixedName
: TOK_NCName TOK_Colon TOK_NCName
99 TRACE
("Got PrefixedName: \"%s:%s\"\n", $1, $3);
101 $$
=xmlStrcat
($$
,U
(":"));
106 UnprefixedName
: TOK_NCName
108 TRACE
("Got UnprefixedName: \"%s\"\n", $1);
113 /* Based on the w3c XPath standard, adapted where needed.
114 * <http://www.w3.org/TR/xpath/> */
116 /* [2] Location Paths */
117 LocationPath
: RelativeLocationPath
118 | AbsoluteLocationPath
120 AbsoluteLocationPath
: TOK_FSlash RelativeLocationPath
122 TRACE
("Got AbsoluteLocationPath: \"/%s\"\n", $2);
123 $$
=xmlStrdup
(U
("/"));
129 TRACE
("Got AbsoluteLocationPath: \"/\"\n");
130 $$
=xmlStrdup
(U
("/"));
132 | AbbreviatedAbsoluteLocationPath
134 RelativeLocationPath
: Step
135 | RelativeLocationPath TOK_FSlash Step
137 TRACE
("Got RelativeLocationPath: \"%s/%s\"\n", $1, $3);
139 $$
=xmlStrcat
($$
,U
("/"));
143 | AbbreviatedRelativeLocationPath
145 /* [2.1] Location Steps */
146 Step
: AxisSpecifier NodeTest Predicates
148 TRACE
("Got Step: \"%s%s%s\"\n", $1, $2, $3);
155 | NodeTest Predicates
157 TRACE
("Got Step: \"%s%s\"\n", $1, $2);
162 | AxisSpecifier NodeTest
164 TRACE
("Got Step: \"%s%s\"\n", $1, $2);
173 AxisSpecifier
: TOK_NCName TOK_Axis
175 TRACE
("Got AxisSpecifier: \"%s::\"\n", $1);
177 $$
=xmlStrcat
($$
,U
("::"));
180 Attribute
: '@' QName
182 TRACE
("Got Attribute: \"@%s\"\n", $2);
183 $$
=xmlStrdup
(U
("@"));
189 TRACE
("Got All attributes pattern: \"@*\"\n");
190 $$
=xmlStrdup
(U
("@*"));
194 /* [2.3] Node Tests */
200 TRACE
("Got NameTest: \"*\"\n");
201 $$
=xmlStrdup
(U
("*"));
203 | TOK_NCName TOK_Colon
'*'
205 TRACE
("Got NameTest: \"%s:*\"\n", $1);
207 $$
=xmlStrcat
($$
,U
(":*"));
209 | TOK_NCName TOK_Colon TOK_NCName
211 xmlChar
const* registeredNsURI
= xmlXPathNsLookup
(p
->ctx
, $1);
212 TRACE
("Got PrefixedName: \"%s:%s\"\n", $1, $3);
217 $$
=xmlStrdup
(NameTest_mod_pre
);
221 $$
=xmlStrcat
($$
,U
(":"));
225 if
(!registeredNsURI
)
226 $$
=xmlStrcat
($$
,NameTest_mod_post
);
230 $$
=xmlStrdup
(NameTest_mod_pre
);
233 $$
=xmlStrcat
($$
,NameTest_mod_post
);
235 /* [2.4] Predicates */
236 Predicates
: Predicates Predicate
244 Predicate
: '[' PredicateExpr
']'
246 TRACE
("Got Predicate: \"[%s]\"\n", $2);
247 $$
=xmlStrdup
(U
("["));
250 $$
=xmlStrcat
($$
,U
("]"));
253 PredicateExpr
: TOK_Number
255 $$
=xmlStrdup
(U
("index()="));
263 /* [2.5] Abbreviated Syntax */
264 AbbreviatedAbsoluteLocationPath
: TOK_DblFSlash RelativeLocationPath
266 TRACE
("Got AbbreviatedAbsoluteLocationPath: \"//%s\"\n", $2);
267 $$
=xmlStrdup
(U
("//"));
272 AbbreviatedRelativeLocationPath
: RelativeLocationPath TOK_DblFSlash Step
274 TRACE
("Got AbbreviatedRelativeLocationPath: \"%s//%s\"\n", $1, $3);
276 $$
=xmlStrcat
($$
,U
("//"));
281 AbbreviatedStep
: TOK_Parent
283 TRACE
("Got AbbreviatedStep: \"..\"\n");
284 $$
=xmlStrdup
(U
(".."));
288 TRACE
("Got AbbreviatedStep: \".\"\n");
289 $$
=xmlStrdup
(U
("."));
293 /* [3] Expressions */
297 BoolExpr
: FunctionCall
304 PrimaryExpr
: '(' Expr
')'
306 TRACE
("Got PrimaryExpr: \"(%s)\"\n", $1);
307 $$
=xmlStrdup
(U
("("));
310 $$
=xmlStrcat
($$
,U
(")"));
312 | PathExpr
'!' FunctionCall
314 TRACE
("Got PrimaryExpr: \"%s!%s\"\n", $1, $3);
316 $$
=xmlStrcat
($$
,U
("/"));
323 /* [3.2] Function Calls */
324 FunctionCall
: QName
'(' Arguments
')'
326 TRACE
("Got FunctionCall: \"%s(%s)\"\n", $1, $3);
327 if
(xmlStrEqual
($1,U
("ancestor")))
330 $$
=xmlStrcat
($$
,U
("::"));
334 else if
(xmlStrEqual
($1,U
("attribute")))
338 $$
=xmlStrdup
(U
("@*[name()="));
342 $$
=xmlStrcat
($$
,U
("]"));
346 /* XML_XPATH_INVALID_TYPE */
347 $$
=xmlStrdup
(U
("error(1211, 'Error: attribute("));
351 $$
=xmlStrcat
($$
,U
("): invalid argument')"));
354 else if
(xmlStrEqual
($1,U
("element")))
358 $$
=xmlStrdup
(U
("node()[nodeType()=1][name()="));
362 $$
=xmlStrcat
($$
,U
("]"));
366 /* XML_XPATH_INVALID_TYPE */
367 $$
=xmlStrdup
(U
("error(1211, 'Error: element("));
371 $$
=xmlStrcat
($$
,U
("): invalid argument')"));
377 $$
=xmlStrcat
($$
,U
("("));
380 $$
=xmlStrcat
($$
,U
(")"));
385 TRACE
("Got FunctionCall: \"%s()\"\n", $1);
386 /* comment() & node() work the same in XPath */
387 if
(xmlStrEqual
($1,U
("attribute")))
389 $$
=xmlStrdup
(U
("@*"));
392 else if
(xmlStrEqual
($1,U
("element")))
394 $$
=xmlStrdup
(U
("node()[nodeType()=1]"));
397 else if
(xmlStrEqual
($1,U
("pi")))
399 $$
=xmlStrdup
(U
("processing-instruction()"));
402 else if
(xmlStrEqual
($1,U
("textnode")))
404 $$
=xmlStrdup
(U
("text()"));
410 $$
=xmlStrcat
($$
,U
("()"));
414 Arguments
: Argument
',' Arguments
417 $$
=xmlStrcat
($$
,U
(","));
425 /* [3.3] Node-sets */
427 | UnionExpr
'|' PathExpr
429 TRACE
("Got UnionExpr: \"%s|%s\"\n", $1, $3);
431 $$
=xmlStrcat
($$
,U
("|"));
436 PathExpr
: LocationPath
437 | FilterExpr TOK_FSlash RelativeLocationPath
439 TRACE
("Got PathExpr: \"%s/%s\"\n", $1, $3);
441 $$
=xmlStrcat
($$
,U
("/"));
445 | FilterExpr TOK_DblFSlash RelativeLocationPath
447 TRACE
("Got PathExpr: \"%s//%s\"\n", $1, $3);
449 $$
=xmlStrcat
($$
,U
("//"));
455 FilterExpr
: PrimaryExpr
456 | FilterExpr Predicate
458 TRACE
("Got FilterExpr: \"%s%s\"\n", $1, $2);
468 BoolOrExpr
: OrExpr TOK_OpOr AndExpr
470 TRACE
("Got OrExpr: \"%s $or$ %s\"\n", $1, $3);
472 $$
=xmlStrcat
($$
,U
(" or "));
477 AndExpr
: EqualityExpr
480 BoolAndExpr
: AndExpr TOK_OpAnd EqualityExpr
482 TRACE
("Got AndExpr: \"%s $and$ %s\"\n", $1, $3);
484 $$
=xmlStrcat
($$
,U
(" and "));
489 EqualityExpr
: RelationalExpr
492 BoolEqualityExpr
: EqualityExpr TOK_OpEq RelationalExpr
494 TRACE
("Got EqualityExpr: \"%s $eq$ %s\"\n", $1, $3);
496 $$
=xmlStrcat
($$
,U
("="));
500 | EqualityExpr TOK_OpIEq RelationalExpr
502 TRACE
("Got EqualityExpr: \"%s $ieq$ %s\"\n", $1, $3);
503 $$
=xmlStrdup
(U
("OP_IEq("));
506 $$
=xmlStrcat
($$
,U
(","));
509 $$
=xmlStrcat
($$
,U
(")"));
511 | EqualityExpr TOK_OpNEq RelationalExpr
513 TRACE
("Got EqualityExpr: \"%s $ne$ %s\"\n", $1, $3);
515 $$
=xmlStrcat
($$
,U
("!="));
519 | EqualityExpr TOK_OpINEq RelationalExpr
521 TRACE
("Got EqualityExpr: \"%s $ine$ %s\"\n", $1, $3);
522 $$
=xmlStrdup
(U
("OP_INEq("));
525 $$
=xmlStrcat
($$
,U
(","));
528 $$
=xmlStrcat
($$
,U
(")"));
531 RelationalExpr
: UnaryExpr
534 BoolRelationalExpr
: RelationalExpr TOK_OpLt UnaryExpr
536 TRACE
("Got RelationalExpr: \"%s $lt$ %s\"\n", $1, $3);
538 $$
=xmlStrcat
($$
,U
("<"));
542 | RelationalExpr TOK_OpILt UnaryExpr
544 TRACE
("Got RelationalExpr: \"%s $ilt$ %s\"\n", $1, $3);
545 $$
=xmlStrdup
(U
("OP_ILt("));
548 $$
=xmlStrcat
($$
,U
(","));
551 $$
=xmlStrcat
($$
,U
(")"));
553 | RelationalExpr TOK_OpGt UnaryExpr
555 TRACE
("Got RelationalExpr: \"%s $gt$ %s\"\n", $1, $3);
557 $$
=xmlStrcat
($$
,U
(">"));
561 | RelationalExpr TOK_OpIGt UnaryExpr
563 TRACE
("Got RelationalExpr: \"%s $igt$ %s\"\n", $1, $3);
564 $$
=xmlStrdup
(U
("OP_IGt("));
567 $$
=xmlStrcat
($$
,U
(","));
570 $$
=xmlStrcat
($$
,U
(")"));
572 | RelationalExpr TOK_OpLEq UnaryExpr
574 TRACE
("Got RelationalExpr: \"%s $le$ %s\"\n", $1, $3);
576 $$
=xmlStrcat
($$
,U
("<="));
580 | RelationalExpr TOK_OpILEq UnaryExpr
582 TRACE
("Got RelationalExpr: \"%s $ile$ %s\"\n", $1, $3);
583 $$
=xmlStrdup
(U
("OP_ILEq("));
586 $$
=xmlStrcat
($$
,U
(","));
589 $$
=xmlStrcat
($$
,U
(")"));
591 | RelationalExpr TOK_OpGEq UnaryExpr
593 TRACE
("Got RelationalExpr: \"%s $ge$ %s\"\n", $1, $3);
595 $$
=xmlStrcat
($$
,U
(">="));
599 | RelationalExpr TOK_OpIGEq UnaryExpr
601 TRACE
("Got RelationalExpr: \"%s $ige$ %s\"\n", $1, $3);
602 $$
=xmlStrdup
(U
("OP_IGEq("));
605 $$
=xmlStrcat
($$
,U
(","));
608 $$
=xmlStrcat
($$
,U
(")"));
613 UnaryExpr
: UnionExpr
616 BoolUnaryExpr
: TOK_OpNot UnaryExpr
618 TRACE
("Got UnaryExpr: \"$not$ %s\"\n", $2);
619 $$
=xmlStrdup
(U
(" not("));
622 $$
=xmlStrcat
($$
,U
(")"));
626 TRACE
("Got UnaryExpr: \"$any$ %s\"\n", $2);
627 $$
=xmlStrdup
(U
("boolean("));
630 $$
=xmlStrcat
($$
,U
(")"));
634 TRACE
("Got UnaryExpr: \"$all$ %s\"\n", $2);
635 $$
=xmlStrdup
(U
("not("));
638 $$
=xmlStrcat
($$
,U
(")"));
642 FIXME
("Unrecognized $all$ expression - ignoring\n");
646 AllExpr
: PathExpr TOK_OpEq PathExpr
649 $$
=xmlStrcat
($$
,U
("!="));
653 | PathExpr TOK_OpNEq PathExpr
656 $$
=xmlStrcat
($$
,U
("="));
660 | PathExpr TOK_OpLt PathExpr
663 $$
=xmlStrcat
($$
,U
(">="));
667 | PathExpr TOK_OpLEq PathExpr
670 $$
=xmlStrcat
($$
,U
(">"));
674 | PathExpr TOK_OpGt PathExpr
677 $$
=xmlStrcat
($$
,U
("<="));
681 | PathExpr TOK_OpGEq PathExpr
684 $$
=xmlStrcat
($$
,U
("<"));
688 | PathExpr TOK_OpIEq PathExpr
690 $$
=xmlStrdup
(U
("OP_INEq("));
693 $$
=xmlStrcat
($$
,U
(","));
696 $$
=xmlStrcat
($$
,U
(")"));
698 | PathExpr TOK_OpINEq PathExpr
700 $$
=xmlStrdup
(U
("OP_IEq("));
703 $$
=xmlStrcat
($$
,U
(","));
706 $$
=xmlStrcat
($$
,U
(")"));
708 | PathExpr TOK_OpILt PathExpr
710 $$
=xmlStrdup
(U
("OP_IGEq("));
713 $$
=xmlStrcat
($$
,U
(","));
716 $$
=xmlStrcat
($$
,U
(")"));
718 | PathExpr TOK_OpILEq PathExpr
720 $$
=xmlStrdup
(U
("OP_IGt("));
723 $$
=xmlStrcat
($$
,U
(","));
726 $$
=xmlStrcat
($$
,U
(")"));
728 | PathExpr TOK_OpIGt PathExpr
730 $$
=xmlStrdup
(U
("OP_ILEq("));
733 $$
=xmlStrcat
($$
,U
(","));
736 $$
=xmlStrcat
($$
,U
(")"));
738 | PathExpr TOK_OpIGEq PathExpr
740 $$
=xmlStrdup
(U
("OP_ILt("));
743 $$
=xmlStrcat
($$
,U
(","));
746 $$
=xmlStrcat
($$
,U
(")"));