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 TRACE
("Got All attributes pattern: \"@*\"\n");
192 $$
=xmlStrdup
(U
("@*"));
196 /* [2.3] Node Tests */
202 TRACE
("Got NameTest: \"*\"\n");
203 $$
=xmlStrdup
(U
("*"));
205 | TOK_NCName TOK_Colon
'*'
207 TRACE
("Got NameTest: \"%s:*\"\n", $1);
209 $$
=xmlStrcat
($$
,U
(":*"));
211 | TOK_NCName TOK_Colon TOK_NCName
213 xmlChar
const* registeredNsURI
= xmlXPathNsLookup
(p
->ctx
, $1);
214 TRACE
("Got PrefixedName: \"%s:%s\"\n", $1, $3);
219 $$
=xmlStrdup
(NameTest_mod_pre
);
223 $$
=xmlStrcat
($$
,U
(":"));
227 if
(!registeredNsURI
)
228 $$
=xmlStrcat
($$
,NameTest_mod_post
);
232 $$
=xmlStrdup
(NameTest_mod_pre
);
235 $$
=xmlStrcat
($$
,NameTest_mod_post
);
237 /* [2.4] Predicates */
238 Predicates
: Predicates Predicate
246 Predicate
: '[' PredicateExpr
']'
248 TRACE
("Got Predicate: \"[%s]\"\n", $2);
249 $$
=xmlStrdup
(U
("["));
252 $$
=xmlStrcat
($$
,U
("]"));
255 PredicateExpr
: TOK_Number
257 $$
=xmlStrdup
(U
("index()="));
265 /* [2.5] Abbreviated Syntax */
266 AbbreviatedAbsoluteLocationPath
: TOK_DblFSlash RelativeLocationPath
268 TRACE
("Got AbbreviatedAbsoluteLocationPath: \"//%s\"\n", $2);
269 $$
=xmlStrdup
(U
("//"));
274 AbbreviatedRelativeLocationPath
: RelativeLocationPath TOK_DblFSlash Step
276 TRACE
("Got AbbreviatedRelativeLocationPath: \"%s//%s\"\n", $1, $3);
278 $$
=xmlStrcat
($$
,U
("//"));
283 AbbreviatedStep
: TOK_Parent
285 TRACE
("Got AbbreviatedStep: \"..\"\n");
286 $$
=xmlStrdup
(U
(".."));
290 TRACE
("Got AbbreviatedStep: \".\"\n");
291 $$
=xmlStrdup
(U
("."));
295 /* [3] Expressions */
299 BoolExpr
: FunctionCall
306 PrimaryExpr
: '(' Expr
')'
308 TRACE
("Got PrimaryExpr: \"(%s)\"\n", $1);
309 $$
=xmlStrdup
(U
("("));
312 $$
=xmlStrcat
($$
,U
(")"));
314 | PathExpr
'!' FunctionCall
316 TRACE
("Got PrimaryExpr: \"%s!%s\"\n", $1, $3);
318 $$
=xmlStrcat
($$
,U
("/"));
325 /* [3.2] Function Calls */
326 FunctionCall
: QName
'(' Arguments
')'
328 TRACE
("Got FunctionCall: \"%s(%s)\"\n", $1, $3);
329 if
(xmlStrEqual
($1,U
("ancestor")))
332 $$
=xmlStrcat
($$
,U
("::"));
336 else if
(xmlStrEqual
($1,U
("attribute")))
340 $$
=xmlStrdup
(U
("@*[name()="));
344 $$
=xmlStrcat
($$
,U
("]"));
348 /* XML_XPATH_INVALID_TYPE */
349 $$
=xmlStrdup
(U
("error(1211, 'Error: attribute("));
353 $$
=xmlStrcat
($$
,U
("): invalid argument')"));
356 else if
(xmlStrEqual
($1,U
("element")))
360 $$
=xmlStrdup
(U
("node()[nodeType()=1][name()="));
364 $$
=xmlStrcat
($$
,U
("]"));
368 /* XML_XPATH_INVALID_TYPE */
369 $$
=xmlStrdup
(U
("error(1211, 'Error: element("));
373 $$
=xmlStrcat
($$
,U
("): invalid argument')"));
379 $$
=xmlStrcat
($$
,U
("("));
382 $$
=xmlStrcat
($$
,U
(")"));
387 TRACE
("Got FunctionCall: \"%s()\"\n", $1);
388 /* comment() & node() work the same in XPath */
389 if
(xmlStrEqual
($1,U
("attribute")))
391 $$
=xmlStrdup
(U
("@*"));
394 else if
(xmlStrEqual
($1,U
("element")))
396 $$
=xmlStrdup
(U
("node()[nodeType()=1]"));
399 else if
(xmlStrEqual
($1,U
("pi")))
401 $$
=xmlStrdup
(U
("processing-instruction()"));
404 else if
(xmlStrEqual
($1,U
("textnode")))
406 $$
=xmlStrdup
(U
("text()"));
412 $$
=xmlStrcat
($$
,U
("()"));
416 Arguments
: Argument
',' Arguments
419 $$
=xmlStrcat
($$
,U
(","));
427 /* [3.3] Node-sets */
429 | UnionExpr
'|' PathExpr
431 TRACE
("Got UnionExpr: \"%s|%s\"\n", $1, $3);
433 $$
=xmlStrcat
($$
,U
("|"));
438 PathExpr
: LocationPath
439 | FilterExpr TOK_FSlash RelativeLocationPath
441 TRACE
("Got PathExpr: \"%s/%s\"\n", $1, $3);
443 $$
=xmlStrcat
($$
,U
("/"));
447 | FilterExpr TOK_DblFSlash RelativeLocationPath
449 TRACE
("Got PathExpr: \"%s//%s\"\n", $1, $3);
451 $$
=xmlStrcat
($$
,U
("//"));
457 FilterExpr
: PrimaryExpr
458 | FilterExpr Predicate
460 TRACE
("Got FilterExpr: \"%s%s\"\n", $1, $2);
470 BoolOrExpr
: OrExpr TOK_OpOr AndExpr
472 TRACE
("Got OrExpr: \"%s $or$ %s\"\n", $1, $3);
474 $$
=xmlStrcat
($$
,U
(" or "));
479 AndExpr
: EqualityExpr
482 BoolAndExpr
: AndExpr TOK_OpAnd EqualityExpr
484 TRACE
("Got AndExpr: \"%s $and$ %s\"\n", $1, $3);
486 $$
=xmlStrcat
($$
,U
(" and "));
491 EqualityExpr
: RelationalExpr
494 BoolEqualityExpr
: EqualityExpr TOK_OpEq RelationalExpr
496 TRACE
("Got EqualityExpr: \"%s $eq$ %s\"\n", $1, $3);
498 $$
=xmlStrcat
($$
,U
("="));
502 | EqualityExpr TOK_OpIEq RelationalExpr
504 TRACE
("Got EqualityExpr: \"%s $ieq$ %s\"\n", $1, $3);
505 $$
=xmlStrdup
(U
("OP_IEq("));
508 $$
=xmlStrcat
($$
,U
(","));
511 $$
=xmlStrcat
($$
,U
(")"));
513 | EqualityExpr TOK_OpNEq RelationalExpr
515 TRACE
("Got EqualityExpr: \"%s $ne$ %s\"\n", $1, $3);
517 $$
=xmlStrcat
($$
,U
("!="));
521 | EqualityExpr TOK_OpINEq RelationalExpr
523 TRACE
("Got EqualityExpr: \"%s $ine$ %s\"\n", $1, $3);
524 $$
=xmlStrdup
(U
("OP_INEq("));
527 $$
=xmlStrcat
($$
,U
(","));
530 $$
=xmlStrcat
($$
,U
(")"));
533 RelationalExpr
: UnaryExpr
536 BoolRelationalExpr
: RelationalExpr TOK_OpLt UnaryExpr
538 TRACE
("Got RelationalExpr: \"%s $lt$ %s\"\n", $1, $3);
540 $$
=xmlStrcat
($$
,U
("<"));
544 | RelationalExpr TOK_OpILt UnaryExpr
546 TRACE
("Got RelationalExpr: \"%s $ilt$ %s\"\n", $1, $3);
547 $$
=xmlStrdup
(U
("OP_ILt("));
550 $$
=xmlStrcat
($$
,U
(","));
553 $$
=xmlStrcat
($$
,U
(")"));
555 | RelationalExpr TOK_OpGt UnaryExpr
557 TRACE
("Got RelationalExpr: \"%s $gt$ %s\"\n", $1, $3);
559 $$
=xmlStrcat
($$
,U
(">"));
563 | RelationalExpr TOK_OpIGt UnaryExpr
565 TRACE
("Got RelationalExpr: \"%s $igt$ %s\"\n", $1, $3);
566 $$
=xmlStrdup
(U
("OP_IGt("));
569 $$
=xmlStrcat
($$
,U
(","));
572 $$
=xmlStrcat
($$
,U
(")"));
574 | RelationalExpr TOK_OpLEq UnaryExpr
576 TRACE
("Got RelationalExpr: \"%s $le$ %s\"\n", $1, $3);
578 $$
=xmlStrcat
($$
,U
("<="));
582 | RelationalExpr TOK_OpILEq UnaryExpr
584 TRACE
("Got RelationalExpr: \"%s $ile$ %s\"\n", $1, $3);
585 $$
=xmlStrdup
(U
("OP_ILEq("));
588 $$
=xmlStrcat
($$
,U
(","));
591 $$
=xmlStrcat
($$
,U
(")"));
593 | RelationalExpr TOK_OpGEq UnaryExpr
595 TRACE
("Got RelationalExpr: \"%s $ge$ %s\"\n", $1, $3);
597 $$
=xmlStrcat
($$
,U
(">="));
601 | RelationalExpr TOK_OpIGEq UnaryExpr
603 TRACE
("Got RelationalExpr: \"%s $ige$ %s\"\n", $1, $3);
604 $$
=xmlStrdup
(U
("OP_IGEq("));
607 $$
=xmlStrcat
($$
,U
(","));
610 $$
=xmlStrcat
($$
,U
(")"));
615 UnaryExpr
: UnionExpr
618 BoolUnaryExpr
: TOK_OpNot UnaryExpr
620 TRACE
("Got UnaryExpr: \"$not$ %s\"\n", $2);
621 $$
=xmlStrdup
(U
(" not("));
624 $$
=xmlStrcat
($$
,U
(")"));
628 TRACE
("Got UnaryExpr: \"$any$ %s\"\n", $2);
629 $$
=xmlStrdup
(U
("boolean("));
632 $$
=xmlStrcat
($$
,U
(")"));
636 TRACE
("Got UnaryExpr: \"$all$ %s\"\n", $2);
637 $$
=xmlStrdup
(U
("not("));
640 $$
=xmlStrcat
($$
,U
(")"));
644 FIXME
("Unrecognized $all$ expression - ignoring\n");
648 AllExpr
: PathExpr TOK_OpEq PathExpr
651 $$
=xmlStrcat
($$
,U
("!="));
655 | PathExpr TOK_OpNEq PathExpr
658 $$
=xmlStrcat
($$
,U
("="));
662 | PathExpr TOK_OpLt PathExpr
665 $$
=xmlStrcat
($$
,U
(">="));
669 | PathExpr TOK_OpLEq PathExpr
672 $$
=xmlStrcat
($$
,U
(">"));
676 | PathExpr TOK_OpGt PathExpr
679 $$
=xmlStrcat
($$
,U
("<="));
683 | PathExpr TOK_OpGEq PathExpr
686 $$
=xmlStrcat
($$
,U
("<"));
690 | PathExpr TOK_OpIEq PathExpr
692 $$
=xmlStrdup
(U
("OP_INEq("));
695 $$
=xmlStrcat
($$
,U
(","));
698 $$
=xmlStrcat
($$
,U
(")"));
700 | PathExpr TOK_OpINEq PathExpr
702 $$
=xmlStrdup
(U
("OP_IEq("));
705 $$
=xmlStrcat
($$
,U
(","));
708 $$
=xmlStrcat
($$
,U
(")"));
710 | PathExpr TOK_OpILt PathExpr
712 $$
=xmlStrdup
(U
("OP_IGEq("));
715 $$
=xmlStrcat
($$
,U
(","));
718 $$
=xmlStrcat
($$
,U
(")"));
720 | PathExpr TOK_OpILEq PathExpr
722 $$
=xmlStrdup
(U
("OP_IGt("));
725 $$
=xmlStrcat
($$
,U
(","));
728 $$
=xmlStrcat
($$
,U
(")"));
730 | PathExpr TOK_OpIGt PathExpr
732 $$
=xmlStrdup
(U
("OP_ILEq("));
735 $$
=xmlStrcat
($$
,U
(","));
738 $$
=xmlStrcat
($$
,U
(")"));
740 | PathExpr TOK_OpIGEq PathExpr
742 $$
=xmlStrdup
(U
("OP_ILt("));
745 $$
=xmlStrcat
($$
,U
(","));
748 $$
=xmlStrcat
($$
,U
(")"));
754 #endif /* HAVE_LIBXML2 */