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
)
54 msg
, param
->yyscanner
, param
->ctx
, param
->in
, param
->pos
,
55 param
->len
, param
->out
, ++param
->err
, scanner
);
60 %token TOK_Parent TOK_Self TOK_DblFSlash TOK_FSlash TOK_Axis TOK_Colon
61 %token TOK_OpAnd TOK_OpOr TOK_OpNot
62 %token TOK_OpEq TOK_OpIEq TOK_OpNEq TOK_OpINEq
63 %token TOK_OpLt TOK_OpILt TOK_OpGt TOK_OpIGt TOK_OpLEq TOK_OpILEq TOK_OpGEq TOK_OpIGEq
64 %token TOK_OpAll TOK_OpAny
65 %token TOK_NCName TOK_Literal TOK_Number
69 %define api.prefix
{xslpattern_
}
71 %parse
-param
{parser_param
* p
}
72 %parse
-param
{void* scanner
}
73 %lex
-param
{yyscan_t
* scanner
}
75 %left TOK_OpAnd TOK_OpOr
76 %left TOK_OpEq TOK_OpIEq TOK_OpNEq TOK_OpINEq
77 %left TOK_OpLt TOK_OpILt TOK_OpGt TOK_OpIGt TOK_OpLEq TOK_OpILEq TOK_OpGEq TOK_OpIGEq
89 /* Mostly verbatim from the w3c XML Namespaces standard.
90 * <http://www.w3.org/TR/REC-xml-names/> */
92 /* [4] Qualified Names */
96 PrefixedName
: TOK_NCName TOK_Colon TOK_NCName
98 TRACE
("Got PrefixedName: \"%s:%s\"\n", $1, $3);
100 $$
=xmlStrcat
($$
,U
(":"));
105 UnprefixedName
: TOK_NCName
107 TRACE
("Got UnprefixedName: \"%s\"\n", $1);
112 /* Based on the w3c XPath standard, adapted where needed.
113 * <http://www.w3.org/TR/xpath/> */
115 /* [2] Location Paths */
116 LocationPath
: RelativeLocationPath
117 | AbsoluteLocationPath
119 AbsoluteLocationPath
: TOK_FSlash RelativeLocationPath
121 TRACE
("Got AbsoluteLocationPath: \"/%s\"\n", $2);
122 $$
=xmlStrdup
(U
("/"));
128 TRACE
("Got AbsoluteLocationPath: \"/\"\n");
129 $$
=xmlStrdup
(U
("/"));
131 | AbbreviatedAbsoluteLocationPath
133 RelativeLocationPath
: Step
134 | RelativeLocationPath TOK_FSlash Step
136 TRACE
("Got RelativeLocationPath: \"%s/%s\"\n", $1, $3);
138 $$
=xmlStrcat
($$
,U
("/"));
142 | AbbreviatedRelativeLocationPath
144 /* [2.1] Location Steps */
145 Step
: AxisSpecifier NodeTest Predicates
147 TRACE
("Got Step: \"%s%s%s\"\n", $1, $2, $3);
154 | NodeTest Predicates
156 TRACE
("Got Step: \"%s%s\"\n", $1, $2);
161 | AxisSpecifier NodeTest
163 TRACE
("Got Step: \"%s%s\"\n", $1, $2);
172 AxisSpecifier
: TOK_NCName TOK_Axis
174 TRACE
("Got AxisSpecifier: \"%s::\"\n", $1);
176 $$
=xmlStrcat
($$
,U
("::"));
179 Attribute
: '@' QName
181 TRACE
("Got Attribute: \"@%s\"\n", $2);
182 $$
=xmlStrdup
(U
("@"));
188 TRACE
("Got All attributes pattern: \"@*\"\n");
189 $$
=xmlStrdup
(U
("@*"));
193 /* [2.3] Node Tests */
199 TRACE
("Got NameTest: \"*\"\n");
200 $$
=xmlStrdup
(U
("*"));
202 | TOK_NCName TOK_Colon
'*'
204 TRACE
("Got NameTest: \"%s:*\"\n", $1);
206 $$
=xmlStrcat
($$
,U
(":*"));
208 | TOK_NCName TOK_Colon TOK_NCName
210 xmlChar
const* registeredNsURI
= xmlXPathNsLookup
(p
->ctx
, $1);
211 TRACE
("Got PrefixedName: \"%s:%s\"\n", $1, $3);
216 $$
=xmlStrdup
(NameTest_mod_pre
);
220 $$
=xmlStrcat
($$
,U
(":"));
224 if
(!registeredNsURI
)
225 $$
=xmlStrcat
($$
,NameTest_mod_post
);
229 $$
=xmlStrdup
(NameTest_mod_pre
);
232 $$
=xmlStrcat
($$
,NameTest_mod_post
);
234 /* [2.4] Predicates */
235 Predicates
: Predicates Predicate
243 Predicate
: '[' PredicateExpr
']'
245 TRACE
("Got Predicate: \"[%s]\"\n", $2);
246 $$
=xmlStrdup
(U
("["));
249 $$
=xmlStrcat
($$
,U
("]"));
252 PredicateExpr
: TOK_Number
254 $$
=xmlStrdup
(U
("index()="));
262 /* [2.5] Abbreviated Syntax */
263 AbbreviatedAbsoluteLocationPath
: TOK_DblFSlash RelativeLocationPath
265 TRACE
("Got AbbreviatedAbsoluteLocationPath: \"//%s\"\n", $2);
266 $$
=xmlStrdup
(U
("//"));
271 AbbreviatedRelativeLocationPath
: RelativeLocationPath TOK_DblFSlash Step
273 TRACE
("Got AbbreviatedRelativeLocationPath: \"%s//%s\"\n", $1, $3);
275 $$
=xmlStrcat
($$
,U
("//"));
280 AbbreviatedStep
: TOK_Parent
282 TRACE
("Got AbbreviatedStep: \"..\"\n");
283 $$
=xmlStrdup
(U
(".."));
287 TRACE
("Got AbbreviatedStep: \".\"\n");
288 $$
=xmlStrdup
(U
("."));
292 /* [3] Expressions */
296 BoolExpr
: FunctionCall
303 PrimaryExpr
: '(' Expr
')'
305 TRACE
("Got PrimaryExpr: \"(%s)\"\n", $1);
306 $$
=xmlStrdup
(U
("("));
309 $$
=xmlStrcat
($$
,U
(")"));
311 | PathExpr
'!' FunctionCall
313 TRACE
("Got PrimaryExpr: \"%s!%s\"\n", $1, $3);
315 $$
=xmlStrcat
($$
,U
("/"));
322 /* [3.2] Function Calls */
323 FunctionCall
: QName
'(' Arguments
')'
325 TRACE
("Got FunctionCall: \"%s(%s)\"\n", $1, $3);
326 if
(xmlStrEqual
($1,U
("ancestor")))
329 $$
=xmlStrcat
($$
,U
("::"));
333 else if
(xmlStrEqual
($1,U
("attribute")))
337 $$
=xmlStrdup
(U
("@*[name()="));
341 $$
=xmlStrcat
($$
,U
("]"));
345 /* XML_XPATH_INVALID_TYPE */
346 $$
=xmlStrdup
(U
("error(1211, 'Error: attribute("));
350 $$
=xmlStrcat
($$
,U
("): invalid argument')"));
353 else if
(xmlStrEqual
($1,U
("element")))
357 $$
=xmlStrdup
(U
("node()[nodeType()=1][name()="));
361 $$
=xmlStrcat
($$
,U
("]"));
365 /* XML_XPATH_INVALID_TYPE */
366 $$
=xmlStrdup
(U
("error(1211, 'Error: element("));
370 $$
=xmlStrcat
($$
,U
("): invalid argument')"));
376 $$
=xmlStrcat
($$
,U
("("));
379 $$
=xmlStrcat
($$
,U
(")"));
384 TRACE
("Got FunctionCall: \"%s()\"\n", $1);
385 /* comment() & node() work the same in XPath */
386 if
(xmlStrEqual
($1,U
("attribute")))
388 $$
=xmlStrdup
(U
("@*"));
391 else if
(xmlStrEqual
($1,U
("element")))
393 $$
=xmlStrdup
(U
("node()[nodeType()=1]"));
396 else if
(xmlStrEqual
($1,U
("pi")))
398 $$
=xmlStrdup
(U
("processing-instruction()"));
401 else if
(xmlStrEqual
($1,U
("textnode")))
403 $$
=xmlStrdup
(U
("text()"));
409 $$
=xmlStrcat
($$
,U
("()"));
413 Arguments
: Argument
',' Arguments
416 $$
=xmlStrcat
($$
,U
(","));
424 /* [3.3] Node-sets */
426 | UnionExpr
'|' PathExpr
428 TRACE
("Got UnionExpr: \"%s|%s\"\n", $1, $3);
430 $$
=xmlStrcat
($$
,U
("|"));
435 PathExpr
: LocationPath
436 | FilterExpr TOK_FSlash RelativeLocationPath
438 TRACE
("Got PathExpr: \"%s/%s\"\n", $1, $3);
440 $$
=xmlStrcat
($$
,U
("/"));
444 | FilterExpr TOK_DblFSlash RelativeLocationPath
446 TRACE
("Got PathExpr: \"%s//%s\"\n", $1, $3);
448 $$
=xmlStrcat
($$
,U
("//"));
454 FilterExpr
: PrimaryExpr
455 | FilterExpr Predicate
457 TRACE
("Got FilterExpr: \"%s%s\"\n", $1, $2);
467 BoolOrExpr
: OrExpr TOK_OpOr AndExpr
469 TRACE
("Got OrExpr: \"%s $or$ %s\"\n", $1, $3);
471 $$
=xmlStrcat
($$
,U
(" or "));
476 AndExpr
: EqualityExpr
479 BoolAndExpr
: AndExpr TOK_OpAnd EqualityExpr
481 TRACE
("Got AndExpr: \"%s $and$ %s\"\n", $1, $3);
483 $$
=xmlStrcat
($$
,U
(" and "));
488 EqualityExpr
: RelationalExpr
491 BoolEqualityExpr
: EqualityExpr TOK_OpEq RelationalExpr
493 TRACE
("Got EqualityExpr: \"%s $eq$ %s\"\n", $1, $3);
495 $$
=xmlStrcat
($$
,U
("="));
499 | EqualityExpr TOK_OpIEq RelationalExpr
501 TRACE
("Got EqualityExpr: \"%s $ieq$ %s\"\n", $1, $3);
502 $$
=xmlStrdup
(U
("OP_IEq("));
505 $$
=xmlStrcat
($$
,U
(","));
508 $$
=xmlStrcat
($$
,U
(")"));
510 | EqualityExpr TOK_OpNEq RelationalExpr
512 TRACE
("Got EqualityExpr: \"%s $ne$ %s\"\n", $1, $3);
514 $$
=xmlStrcat
($$
,U
("!="));
518 | EqualityExpr TOK_OpINEq RelationalExpr
520 TRACE
("Got EqualityExpr: \"%s $ine$ %s\"\n", $1, $3);
521 $$
=xmlStrdup
(U
("OP_INEq("));
524 $$
=xmlStrcat
($$
,U
(","));
527 $$
=xmlStrcat
($$
,U
(")"));
530 RelationalExpr
: UnaryExpr
533 BoolRelationalExpr
: RelationalExpr TOK_OpLt UnaryExpr
535 TRACE
("Got RelationalExpr: \"%s $lt$ %s\"\n", $1, $3);
537 $$
=xmlStrcat
($$
,U
("<"));
541 | RelationalExpr TOK_OpILt UnaryExpr
543 TRACE
("Got RelationalExpr: \"%s $ilt$ %s\"\n", $1, $3);
544 $$
=xmlStrdup
(U
("OP_ILt("));
547 $$
=xmlStrcat
($$
,U
(","));
550 $$
=xmlStrcat
($$
,U
(")"));
552 | RelationalExpr TOK_OpGt UnaryExpr
554 TRACE
("Got RelationalExpr: \"%s $gt$ %s\"\n", $1, $3);
556 $$
=xmlStrcat
($$
,U
(">"));
560 | RelationalExpr TOK_OpIGt UnaryExpr
562 TRACE
("Got RelationalExpr: \"%s $igt$ %s\"\n", $1, $3);
563 $$
=xmlStrdup
(U
("OP_IGt("));
566 $$
=xmlStrcat
($$
,U
(","));
569 $$
=xmlStrcat
($$
,U
(")"));
571 | RelationalExpr TOK_OpLEq UnaryExpr
573 TRACE
("Got RelationalExpr: \"%s $le$ %s\"\n", $1, $3);
575 $$
=xmlStrcat
($$
,U
("<="));
579 | RelationalExpr TOK_OpILEq UnaryExpr
581 TRACE
("Got RelationalExpr: \"%s $ile$ %s\"\n", $1, $3);
582 $$
=xmlStrdup
(U
("OP_ILEq("));
585 $$
=xmlStrcat
($$
,U
(","));
588 $$
=xmlStrcat
($$
,U
(")"));
590 | RelationalExpr TOK_OpGEq UnaryExpr
592 TRACE
("Got RelationalExpr: \"%s $ge$ %s\"\n", $1, $3);
594 $$
=xmlStrcat
($$
,U
(">="));
598 | RelationalExpr TOK_OpIGEq UnaryExpr
600 TRACE
("Got RelationalExpr: \"%s $ige$ %s\"\n", $1, $3);
601 $$
=xmlStrdup
(U
("OP_IGEq("));
604 $$
=xmlStrcat
($$
,U
(","));
607 $$
=xmlStrcat
($$
,U
(")"));
612 UnaryExpr
: UnionExpr
615 BoolUnaryExpr
: TOK_OpNot UnaryExpr
617 TRACE
("Got UnaryExpr: \"$not$ %s\"\n", $2);
618 $$
=xmlStrdup
(U
(" not("));
621 $$
=xmlStrcat
($$
,U
(")"));
625 TRACE
("Got UnaryExpr: \"$any$ %s\"\n", $2);
626 $$
=xmlStrdup
(U
("boolean("));
629 $$
=xmlStrcat
($$
,U
(")"));
633 TRACE
("Got UnaryExpr: \"$all$ %s\"\n", $2);
634 $$
=xmlStrdup
(U
("not("));
637 $$
=xmlStrcat
($$
,U
(")"));
641 FIXME
("Unrecognized $all$ expression - ignoring\n");
645 AllExpr
: PathExpr TOK_OpEq PathExpr
648 $$
=xmlStrcat
($$
,U
("!="));
652 | PathExpr TOK_OpNEq PathExpr
655 $$
=xmlStrcat
($$
,U
("="));
659 | PathExpr TOK_OpLt PathExpr
662 $$
=xmlStrcat
($$
,U
(">="));
666 | PathExpr TOK_OpLEq PathExpr
669 $$
=xmlStrcat
($$
,U
(">"));
673 | PathExpr TOK_OpGt PathExpr
676 $$
=xmlStrcat
($$
,U
("<="));
680 | PathExpr TOK_OpGEq PathExpr
683 $$
=xmlStrcat
($$
,U
("<"));
687 | PathExpr TOK_OpIEq PathExpr
689 $$
=xmlStrdup
(U
("OP_INEq("));
692 $$
=xmlStrcat
($$
,U
(","));
695 $$
=xmlStrcat
($$
,U
(")"));
697 | PathExpr TOK_OpINEq PathExpr
699 $$
=xmlStrdup
(U
("OP_IEq("));
702 $$
=xmlStrcat
($$
,U
(","));
705 $$
=xmlStrcat
($$
,U
(")"));
707 | PathExpr TOK_OpILt PathExpr
709 $$
=xmlStrdup
(U
("OP_IGEq("));
712 $$
=xmlStrcat
($$
,U
(","));
715 $$
=xmlStrcat
($$
,U
(")"));
717 | PathExpr TOK_OpILEq PathExpr
719 $$
=xmlStrdup
(U
("OP_IGt("));
722 $$
=xmlStrcat
($$
,U
(","));
725 $$
=xmlStrcat
($$
,U
(")"));
727 | PathExpr TOK_OpIGt PathExpr
729 $$
=xmlStrdup
(U
("OP_ILEq("));
732 $$
=xmlStrcat
($$
,U
(","));
735 $$
=xmlStrcat
($$
,U
(")"));
737 | PathExpr TOK_OpIGEq PathExpr
739 $$
=xmlStrdup
(U
("OP_ILt("));
742 $$
=xmlStrcat
($$
,U
(","));
745 $$
=xmlStrcat
($$
,U
(")"));