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