2 /* XPathParser.y - An XPath 1.0 parser.
3 Copyright (C) 2004 The Free Software Foundation
5 This file is part of GNU Classpath.
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING. If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library. Thus, the terms and
24 conditions of the GNU General Public License cover the whole
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module. An independent module is a module which is not derived from
34 or based on this library. If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so. If you do not wish to do so, delete this
37 exception statement from your version. */
40 package gnu.xml.xpath
;
42 import java.util.ArrayList
;
43 import java.util.Collections
;
44 import java.util.List
;
46 import javax.xml.namespace.NamespaceContext
;
47 import javax.xml.namespace.QName
;
48 import javax.xml.xpath.XPathFunctionResolver
;
49 import javax.xml.xpath.XPathVariableResolver
;
50 import org.w3c.dom.Node
;
53 * An XPath 1.0 parser.
55 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
57 public class XPathParser
60 NamespaceContext namespaceContext
;
61 XPathVariableResolver variableResolver
;
62 XPathFunctionResolver functionResolver
;
64 QName getQName
(String name
)
66 QName qName
= QName.valueOf
(name
);
67 if
(namespaceContext
!= null
)
69 String prefix
= qName.getPrefix
();
70 String uri
= qName.getNamespaceURI
();
71 if
(prefix
!= null
&& (uri
== null || uri.length
() == 0))
73 uri
= namespaceContext.getNamespaceURI
(prefix
);
74 String localName
= qName.getLocalPart
();
75 qName
= new QName
(uri
, localName
, prefix
);
81 Expr lookupFunction
(String name
, List args
)
83 int arity
= args.size
();
84 if
("position".equals
(name
) && arity
== 0)
86 return new PositionFunction
();
88 else if
("last".equals
(name
) && arity
== 0)
90 return new LastFunction
();
92 else if
("string".equals
(name
) && (arity
== 1 || arity
== 0))
94 return new StringFunction
(args
);
96 else if
("number".equals
(name
) && (arity
== 1 || arity
== 0))
98 return new NumberFunction
(args
);
100 else if
("boolean".equals
(name
) && arity
== 1)
102 return new BooleanFunction
(args
);
104 else if
("count".equals
(name
) && arity
== 1)
106 return new CountFunction
(args
);
108 else if
("not".equals
(name
) && arity
== 1)
110 return new NotFunction
(args
);
112 else if
("id".equals
(name
) && arity
== 1)
114 return new IdFunction
(args
);
116 else if
("concat".equals
(name
) && arity
> 1)
118 return new ConcatFunction
(args
);
120 else if
("true".equals
(name
) && arity
== 0)
122 return new TrueFunction
();
124 else if
("false".equals
(name
) && arity
== 0)
126 return new FalseFunction
();
128 else if
("name".equals
(name
) && (arity
== 1 || arity
== 0))
130 return new NameFunction
(args
);
132 else if
("local-name".equals
(name
) && (arity
== 1 || arity
== 0))
134 return new LocalNameFunction
(args
);
136 else if
("namespace-uri".equals
(name
) && (arity
== 1 || arity
== 0))
138 return new NamespaceUriFunction
(args
);
140 else if
("starts-with".equals
(name
) && arity
== 2)
142 return new StartsWithFunction
(args
);
144 else if
("contains".equals
(name
) && arity
== 2)
146 return new ContainsFunction
(args
);
148 else if
("string-length".equals
(name
) && (arity
== 1 || arity
== 0))
150 return new StringLengthFunction
(args
);
152 else if
("translate".equals
(name
) && arity
== 3)
154 return new TranslateFunction
(args
);
156 else if
("normalize-space".equals
(name
) && (arity
== 1 || arity
== 0))
158 return new NormalizeSpaceFunction
(args
);
160 else if
("substring".equals
(name
) && (arity
== 2 || arity
== 3))
162 return new SubstringFunction
(args
);
164 else if
("substring-before".equals
(name
) && arity
== 2)
166 return new SubstringBeforeFunction
(args
);
168 else if
("substring-after".equals
(name
) && arity
== 2)
170 return new SubstringAfterFunction
(args
);
172 else if
("lang".equals
(name
) && arity
== 1)
174 return new LangFunction
(args
);
176 else if
("sum".equals
(name
) && arity
== 1)
178 return new SumFunction
(args
);
180 else if
("floor".equals
(name
) && arity
== 1)
182 return new FloorFunction
(args
);
184 else if
("ceiling".equals
(name
) && arity
== 1)
186 return new CeilingFunction
(args
);
188 else if
("round".equals
(name
) && arity
== 1)
190 return new RoundFunction
(args
);
192 else if
(functionResolver
!= null
)
194 QName qName
= QName.valueOf
(name
);
195 Object function
= functionResolver.resolveFunction
(qName
, arity
);
196 if
(function
!= null
&&
197 function instanceof Function
&&
198 function instanceof Expr
)
200 Function f
= (Function
) function
;
201 f.setArguments
(args
);
202 return
(Expr
) function
;
205 return new FunctionCall
(functionResolver
, name
, args
);
221 %token DOUBLE_SLASH
// '//'
234 %token DOUBLE_COLON
// '::'
236 %token DOUBLE_DOT
// '..'
239 %token ANCESTOR_OR_SELF
243 %token DESCENDANT_OR_SELF
245 %token FOLLOWING_SIBLING
249 %token PRECEDING_SIBLING
256 %token PROCESSING_INSTRUCTION
271 relative_location_path
272 | absolute_location_path
275 absolute_location_path:
280 | SLASH relative_location_path
283 if
($2 instanceof Steps
)
290 steps.path.addFirst
($2);
292 steps.path.addFirst
(new Root
());
294 //$$ = new Step(new Root(), (Path) $2);
296 | DOUBLE_SLASH relative_location_path
298 Test nt
= new NodeTypeTest
((short) 0);
299 Selector s
= new Selector
(Selector.DESCENDANT_OR_SELF
,
300 Collections.singletonList
(nt
));
302 if
($2 instanceof Steps
)
309 steps.path.addFirst
($2);
311 steps.path.addFirst
(s
);
312 steps.path.addFirst
(new Root
());
314 //Step step = new Step(s, (Path) $2);
315 //$$ = new Step(new Root(), step);
319 relative_location_path:
321 | relative_location_path SLASH step
324 if
($1 instanceof Steps
)
331 steps.path.addFirst
($1);
333 steps.path.addLast
($3);
335 //$$ = new Step((Expr) $1, (Path) $3);
337 | relative_location_path DOUBLE_SLASH step
339 Test nt
= new NodeTypeTest
((short) 0);
340 Selector s
= new Selector
(Selector.DESCENDANT_OR_SELF
,
341 Collections.singletonList
(nt
));
343 if
($1 instanceof Steps
)
350 steps.path.addFirst
($1);
352 steps.path.addLast
(s
);
353 steps.path.addLast
($3);
355 //Step step = new Step(s, (Path) $3);
356 //$$ = new Step((Expr) $1, step);
363 $$
= new Selector
(Selector.CHILD
, (List
) $1);
367 $$
= new Selector
(Selector.ATTRIBUTE
, (List
) $2);
369 | axis_name DOUBLE_COLON step_node_test
371 $$
= new Selector
(((Integer
) $1).intValue
(), (List
) $3);
375 $$
= new Selector
(Selector.SELF
, Collections.EMPTY_LIST
);
379 $$
= new Selector
(Selector.PARENT
, Collections.EMPTY_LIST
);
386 List list
= new ArrayList
();
390 | step_node_test predicate
392 List list
= (List
)$1;
401 List list = new ArrayList ();
405 | predicate predicate_list
407 List list = (List) $3;
416 $$
= new Integer
(Selector.ANCESTOR
);
420 $$
= new Integer
(Selector.ANCESTOR_OR_SELF
);
424 $$
= new Integer
(Selector.ATTRIBUTE
);
428 $$
= new Integer
(Selector.CHILD
);
432 $$
= new Integer
(Selector.DESCENDANT
);
436 $$
= new Integer
(Selector.DESCENDANT_OR_SELF
);
440 $$
= new Integer
(Selector.FOLLOWING
);
444 $$
= new Integer
(Selector.FOLLOWING_SIBLING
);
448 $$
= new Integer
(Selector.NAMESPACE
);
452 $$
= new Integer
(Selector.PARENT
);
456 $$
= new Integer
(Selector.PRECEDING
);
460 $$
= new Integer
(Selector.PRECEDING_SIBLING
);
464 $$
= new Integer
(Selector.SELF
);
470 /*| PROCESSING_INSTRUCTION LP LITERAL RP*/
471 | PROCESSING_INSTRUCTION LITERAL RP
473 $$
= new NodeTypeTest
(Node.PROCESSING_INSTRUCTION_NODE
, (String
) $2);
475 /*| node_type LP RP*/
478 $$
= new NodeTypeTest
(((Short
) $1).shortValue
());
485 $$
= new Predicate
((Expr
) $2);
493 $$
= new ParenthesizedExpr
((Expr
) $2);
497 $$
= new Constant
($1);
501 $$
= new Constant
($1);
509 $$
= lookupFunction
((String
) $1, Collections.EMPTY_LIST
);
511 | function_name LP argument_list RP
513 $$
= lookupFunction
((String
) $1, (List
) $3);
520 List list
= new ArrayList
();
524 | expr COMMA argument_list
526 List list
= (List
) $3;
534 | union_expr PIPE path_expr
536 $$
= new UnionExpr
((Expr
) $1, (Expr
) $3);
543 | filter_expr SLASH relative_location_path
546 if
($3 instanceof Steps
)
553 steps.path.addFirst
($3);
555 steps.path.addFirst
($1);
557 //$$ = new Step ((Expr) $1, (Path) $3);
559 | filter_expr DOUBLE_SLASH relative_location_path
561 Test nt
= new NodeTypeTest
((short) 0);
562 Selector s
= new Selector
(Selector.DESCENDANT_OR_SELF
,
563 Collections.singletonList
(nt
));
565 if
($3 instanceof Steps
)
572 steps.path.addFirst
($3);
574 steps.path.addFirst
(s
);
575 steps.path.addFirst
($1);
577 //Step step = new Step (s, (Path) $3);
578 //$$ = new Step ((Expr) $1, step);
584 | filter_expr predicate
586 Predicate filter
= (Predicate
) $2;
587 Selector s
= new Selector
(Selector.SELF
,
588 Collections.singletonList
(filter
));
590 if
($1 instanceof Steps
)
597 steps.path.addFirst
($1);
599 steps.path.addLast
(s
);
601 //$$ = new Step ((Expr) $1, s);
607 | or_expr OR and_expr
609 $$
= new OrExpr
((Expr
) $1, (Expr
) $3);
615 | and_expr AND equality_expr
617 $$
= new AndExpr
((Expr
) $1, (Expr
) $3);
623 | equality_expr EQ relational_expr
625 $$
= new EqualityExpr
((Expr
) $1, (Expr
) $3, false
);
627 | equality_expr NE relational_expr
629 $$
= new EqualityExpr
((Expr
) $1, (Expr
) $3, true
);
635 | relational_expr LT additive_expr
637 $$
= new RelationalExpr
((Expr
) $1, (Expr
) $3, true
, false
);
639 | relational_expr GT additive_expr
641 $$
= new RelationalExpr
((Expr
) $1, (Expr
) $3, false
, false
);
643 | relational_expr LTE additive_expr
645 $$
= new RelationalExpr
((Expr
) $1, (Expr
) $3, true
, true
);
647 | relational_expr GTE additive_expr
649 $$
= new RelationalExpr
((Expr
) $1, (Expr
) $3, false
, true
);
655 | additive_expr PLUS multiplicative_expr
657 $$
= new ArithmeticExpr
((Expr
) $1, (Expr
) $3, ArithmeticExpr.ADD
);
659 | additive_expr MINUS multiplicative_expr
661 $$
= new ArithmeticExpr
((Expr
) $1, (Expr
) $3, ArithmeticExpr.SUBTRACT
);
667 | multiplicative_expr STAR unary_expr
669 $$
= new ArithmeticExpr
((Expr
) $1, (Expr
) $3, ArithmeticExpr.MULTIPLY
);
671 | multiplicative_expr DIV unary_expr
673 $$
= new ArithmeticExpr
((Expr
) $1, (Expr
) $3, ArithmeticExpr.DIVIDE
);
675 | multiplicative_expr MOD unary_expr
677 $$
= new ArithmeticExpr
((Expr
) $1, (Expr
) $3, ArithmeticExpr.MODULO
);
683 | MINUS unary_expr %prec UNARY
685 $$
= new NegativeExpr
((Expr
) $2);
692 $$
= new Double
((String
) $1 + ".0");
696 $$
= new Double
((String
) $1 + ".0");
700 $$
= new Double
((String
) $1 + "." + (String
) $3);
704 $$
= new Double
("0." + (String
) $2);
712 switch (((Short) $1).shortValue ())
714 case Node.COMMENT_NODE:
720 case Node.PROCESSING_INSTRUCTION_NODE:
721 $$ = "processing-instruction";
733 String name
= (String
) $2;
734 $$
= new VariableReference
(variableResolver
, getQName
(name
));
741 $$
= new NameTest
(null
, true
, true
);
745 QName qName
= getQName
((String
) $1);
746 $$
= new NameTest
(qName
, true
, false
);
750 QName qName
= getQName
((String
) $1);
751 $$
= new NameTest
(qName
, false
, false
);
759 $$
= (String
) $1 + ':' + (String
) $3;
766 $$
= new Short
(Node.COMMENT_NODE
);
770 $$
= new Short
(Node.TEXT_NODE
);
772 | PROCESSING_INSTRUCTION
774 $$
= new Short
(Node.PROCESSING_INSTRUCTION_NODE
);
778 $$
= new Short
((short) 0);