libjava/ChangeLog:
[official-gcc.git] / libjava / classpath / gnu / xml / xpath / XPathParser.y
bloba6d3fd130b0b9a159018942d9cb0807570b7fe53
1 %{
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)
10 any later version.
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
20 02110-1301 USA.
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
25 combination.
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;
45 import java.util.Map;
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;
52 /**
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);
78 return qName;
81 Expr lookupFunction(String name, List<Expr> 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);
210 %token LITERAL
211 %token DIGITS
212 %token NAME
214 %token LP // '('
215 %token RP // ')'
216 %token LB // '['
217 %token RB // ']'
218 %token COMMA // ','
219 %token PIPE // '|'
220 %token SLASH // '/'
221 %token DOUBLE_SLASH // '//'
222 %token EQ // '='
223 %token NE // '!='
224 %token GT // '>'
225 %token LT // '<'
226 %token GTE // '>='
227 %token LTE // '<='
228 %token PLUS // '+'
229 %token MINUS // '-'
230 %token AT // '@'
231 %token STAR // '*'
232 %token DOLLAR // '$'
233 %token COLON // ':'
234 %token DOUBLE_COLON // '::'
235 %token DOT // '.'
236 %token DOUBLE_DOT // '..'
238 %token ANCESTOR
239 %token ANCESTOR_OR_SELF
240 %token ATTRIBUTE
241 %token CHILD
242 %token DESCENDANT
243 %token DESCENDANT_OR_SELF
244 %token FOLLOWING
245 %token FOLLOWING_SIBLING
246 %token NAMESPACE
247 %token PARENT
248 %token PRECEDING
249 %token PRECEDING_SIBLING
250 %token SELF
251 %token DIV
252 %token MOD
253 %token OR
254 %token AND
255 %token COMMENT
256 %token PROCESSING_INSTRUCTION
257 %token TEXT
258 %token NODE
260 %right UNARY
262 %start expr
266 expr:
267 or_expr
270 location_path:
271 relative_location_path
272 | absolute_location_path
275 absolute_location_path:
276 SLASH
278 $$ = new Root();
280 | SLASH relative_location_path
282 Steps steps;
283 if ($2 instanceof Steps)
285 steps = (Steps) $2;
287 else
289 steps = new Steps();
290 steps.path.addFirst((Expr) $2);
292 steps.path.addFirst(new Root());
293 $$ = steps;
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));
301 Steps steps;
302 if ($2 instanceof Steps)
304 steps = (Steps) $2;
306 else
308 steps = new Steps();
309 steps.path.addFirst((Expr) $2);
311 steps.path.addFirst(s);
312 steps.path.addFirst(new Root());
313 $$ = steps;
314 //Step step = new Step(s, (Path) $2);
315 //$$ = new Step(new Root(), step);
319 relative_location_path:
320 step
321 | relative_location_path SLASH step
323 Steps steps;
324 if ($1 instanceof Steps)
326 steps = (Steps) $1;
328 else
330 steps = new Steps();
331 steps.path.addFirst((Expr) $1);
333 steps.path.addLast((Expr) $3);
334 $$ = steps;
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));
342 Steps steps;
343 if ($1 instanceof Steps)
345 steps = (Steps) $1;
347 else
349 steps = new Steps();
350 steps.path.addFirst((Expr) $1);
352 steps.path.addLast(s);
353 steps.path.addLast((Expr) $3);
354 $$ = steps;
355 //Step step = new Step(s, (Path) $3);
356 //$$ = new Step((Expr) $1, step);
360 step:
361 step_node_test
363 @SuppressWarnings("unchecked") List<Test> tests = (List<Test>) $1;
364 $$ = new Selector (Selector.CHILD, tests);
366 | AT step_node_test
368 @SuppressWarnings("unchecked") List<Test> tests = (List<Test>) $2;
369 $$ = new Selector (Selector.ATTRIBUTE, tests);
371 | axis_name DOUBLE_COLON step_node_test
373 @SuppressWarnings("unchecked") List<Test> tests = (List<Test>) $3;
374 $$ = new Selector (((Integer) $1).intValue (), tests);
376 | DOT
378 List<Test> emptyList = Collections.emptyList();
379 $$ = new Selector (Selector.SELF, emptyList);
381 | DOUBLE_DOT
383 List<Test> emptyList = Collections.emptyList();
384 $$ = new Selector (Selector.PARENT, emptyList);
388 step_node_test:
389 node_test
391 List<Test> list = new ArrayList<Test>();
392 list.add((Test) $1);
393 $$ = list;
395 | step_node_test predicate
397 /* This is safe as we create this in one of the other cases */
398 @SuppressWarnings("unchecked") List<Test> tests = (List<Test>)$1;
399 tests.add((Test) $2);
400 $$ = list;
404 /*predicate_list:
405 predicate
407 List list = new ArrayList ();
408 list.add ($1);
409 $$ = list;
411 | predicate predicate_list
413 List list = (List) $3;
414 list.add (0, $1);
415 $$ = list;
419 axis_name:
420 ANCESTOR
422 $$ = new Integer(Selector.ANCESTOR);
424 | ANCESTOR_OR_SELF
426 $$ = new Integer(Selector.ANCESTOR_OR_SELF);
428 | ATTRIBUTE
430 $$ = new Integer(Selector.ATTRIBUTE);
432 | CHILD
434 $$ = new Integer(Selector.CHILD);
436 | DESCENDANT
438 $$ = new Integer(Selector.DESCENDANT);
440 | DESCENDANT_OR_SELF
442 $$ = new Integer(Selector.DESCENDANT_OR_SELF);
444 | FOLLOWING
446 $$ = new Integer(Selector.FOLLOWING);
448 | FOLLOWING_SIBLING
450 $$ = new Integer(Selector.FOLLOWING_SIBLING);
452 | NAMESPACE
454 $$ = new Integer(Selector.NAMESPACE);
456 | PARENT
458 $$ = new Integer(Selector.PARENT);
460 | PRECEDING
462 $$ = new Integer(Selector.PRECEDING);
464 | PRECEDING_SIBLING
466 $$ = new Integer(Selector.PRECEDING_SIBLING);
468 | SELF
470 $$ = new Integer(Selector.SELF);
474 node_test:
475 name_test
476 /*| PROCESSING_INSTRUCTION LP LITERAL RP*/
477 | PROCESSING_INSTRUCTION LITERAL RP
479 $$ = new NodeTypeTest(Node.PROCESSING_INSTRUCTION_NODE, (String) $2);
481 /*| node_type LP RP*/
482 | node_type RP
484 $$ = new NodeTypeTest(((Short) $1).shortValue());
488 predicate:
489 LB expr RB
491 $$ = new Predicate((Expr) $2);
495 primary_expr:
496 variable_reference
497 | LP expr RP
499 $$ = new ParenthesizedExpr((Expr) $2);
501 | LITERAL
503 $$ = new Constant($1);
505 | number
507 $$ = new Constant($1);
509 | function_call
512 function_call:
513 function_name LP RP
515 List<Expr> emptyList = Collections.emptyList();
516 $$ = lookupFunction((String) $1, emptyList);
518 | function_name LP argument_list RP
520 /* This is safe as we create this below */
521 @SuppressWarnings("unchecked") List<Expr> exprs = (List<Expr>) $3;
522 $$ = lookupFunction((String) $1, (List) exprs);
526 argument_list:
527 expr
529 List<Expr> list = new ArrayList<Expr>();
530 list.add((Expr) $1);
531 $$ = list;
533 | expr COMMA argument_list
535 /* This is safe as we create this above */
536 @SuppressWarnings("unchecked") List<Expr> list = (List<Expr>) $3;
537 list.add(0, (Expr) $1);
538 $$ = list;
542 union_expr:
543 path_expr
544 | union_expr PIPE path_expr
546 $$ = new UnionExpr((Expr) $1, (Expr) $3);
550 path_expr:
551 location_path
552 | filter_expr
553 | filter_expr SLASH relative_location_path
555 Steps steps;
556 if ($3 instanceof Steps)
558 steps = (Steps) $3;
560 else
562 steps = new Steps();
563 steps.path.addFirst((Expr) $3);
565 steps.path.addFirst((Expr) $1);
566 $$ = steps;
567 //$$ = new Step ((Expr) $1, (Path) $3);
569 | filter_expr DOUBLE_SLASH relative_location_path
571 Test nt = new NodeTypeTest((short) 0);
572 Selector s = new Selector(Selector.DESCENDANT_OR_SELF,
573 Collections.singletonList(nt));
574 Steps steps;
575 if ($3 instanceof Steps)
577 steps = (Steps) $3;
579 else
581 steps = new Steps();
582 steps.path.addFirst($3);
584 steps.path.addFirst(s);
585 steps.path.addFirst((Expr) $1);
586 $$ = steps;
587 //Step step = new Step (s, (Path) $3);
588 //$$ = new Step ((Expr) $1, step);
592 filter_expr:
593 primary_expr
594 | filter_expr predicate
596 Predicate filter = (Predicate) $2;
597 Selector s = new Selector(Selector.SELF,
598 Collections.singletonList(filter));
599 Steps steps;
600 if ($1 instanceof Steps)
602 steps = (Steps) $1;
604 else
606 steps = new Steps();
607 steps.path.addFirst((Expr) $1);
609 steps.path.addLast(s);
610 $$ = steps;
611 //$$ = new Step ((Expr) $1, s);
615 or_expr:
616 and_expr
617 | or_expr OR and_expr
619 $$ = new OrExpr((Expr) $1, (Expr) $3);
623 and_expr:
624 equality_expr
625 | and_expr AND equality_expr
627 $$ = new AndExpr((Expr) $1, (Expr) $3);
631 equality_expr:
632 relational_expr
633 | equality_expr EQ relational_expr
635 $$ = new EqualityExpr((Expr) $1, (Expr) $3, false);
637 | equality_expr NE relational_expr
639 $$ = new EqualityExpr((Expr) $1, (Expr) $3, true);
643 relational_expr:
644 additive_expr
645 | relational_expr LT additive_expr
647 $$ = new RelationalExpr((Expr) $1, (Expr) $3, true, false);
649 | relational_expr GT additive_expr
651 $$ = new RelationalExpr((Expr) $1, (Expr) $3, false, false);
653 | relational_expr LTE additive_expr
655 $$ = new RelationalExpr((Expr) $1, (Expr) $3, true, true);
657 | relational_expr GTE additive_expr
659 $$ = new RelationalExpr((Expr) $1, (Expr) $3, false, true);
663 additive_expr:
664 multiplicative_expr
665 | additive_expr PLUS multiplicative_expr
667 $$ = new ArithmeticExpr((Expr) $1, (Expr) $3, ArithmeticExpr.ADD);
669 | additive_expr MINUS multiplicative_expr
671 $$ = new ArithmeticExpr((Expr) $1, (Expr) $3, ArithmeticExpr.SUBTRACT);
675 multiplicative_expr:
676 unary_expr
677 | multiplicative_expr STAR unary_expr
679 $$ = new ArithmeticExpr((Expr) $1, (Expr) $3, ArithmeticExpr.MULTIPLY);
681 | multiplicative_expr DIV unary_expr
683 $$ = new ArithmeticExpr((Expr) $1, (Expr) $3, ArithmeticExpr.DIVIDE);
685 | multiplicative_expr MOD unary_expr
687 $$ = new ArithmeticExpr((Expr) $1, (Expr) $3, ArithmeticExpr.MODULO);
691 unary_expr:
692 union_expr
693 | MINUS unary_expr %prec UNARY
695 $$ = new NegativeExpr((Expr) $2);
699 number:
700 DIGITS
702 $$ = new Double((String) $1 + ".0");
704 | DIGITS DOT
706 $$ = new Double((String) $1 + ".0");
708 | DIGITS DOT DIGITS
710 $$ = new Double((String) $1 + "." + (String) $3);
712 | DOT DIGITS
714 $$ = new Double("0." + (String) $2);
718 function_name:
719 qname
720 /* | node_type
722 switch (((Short) $1).shortValue ())
724 case Node.COMMENT_NODE:
725 $$ = "comment";
726 break;
727 case Node.TEXT_NODE:
728 $$ = "text";
729 break;
730 case Node.PROCESSING_INSTRUCTION_NODE:
731 $$ = "processing-instruction";
732 break;
733 default:
734 $$ = "node";
735 break;
740 variable_reference:
741 DOLLAR qname
743 String name = (String) $2;
744 $$ = new VariableReference(variableResolver, getQName(name));
748 name_test:
749 STAR
751 $$ = new NameTest(null, true, true);
753 | NAME COLON STAR
755 QName qName = getQName((String) $1);
756 $$ = new NameTest(qName, true, false);
758 | qname
760 QName qName = getQName((String) $1);
761 $$ = new NameTest(qName, false, false);
765 qname:
766 NAME
767 | NAME COLON NAME
769 $$ = (String) $1 + ':' + (String) $3;
773 node_type:
774 COMMENT
776 $$ = new Short(Node.COMMENT_NODE);
778 | TEXT
780 $$ = new Short(Node.TEXT_NODE);
782 | PROCESSING_INSTRUCTION
784 $$ = new Short(Node.PROCESSING_INSTRUCTION_NODE);
786 | NODE
788 $$ = new Short((short) 0);