1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 package org.jaxen.saxpath.base;
64
65 import java.util.LinkedList;
66
67 import org.jaxen.saxpath.Axis;
68 import org.jaxen.saxpath.Operator;
69 import org.jaxen.saxpath.SAXPathException;
70 import org.jaxen.saxpath.XPathHandler;
71 import org.jaxen.saxpath.XPathSyntaxException;
72 import org.jaxen.saxpath.helpers.DefaultXPathHandler;
73
74 /*** Implementation of SAXPath's <code>XPathReader</code> which
75 * generates callbacks to an <code>XPathHandler</code>.
76 *
77 * @author bob mcwhirter (bob@werken.com)
78 */
79 public class XPathReader implements org.jaxen.saxpath.XPathReader
80 {
81 private LinkedList tokens;
82 private XPathLexer lexer;
83
84 private XPathHandler handler;
85
86 private static XPathHandler defaultHandler = new DefaultXPathHandler();
87
88 /***
89 * Create a new <code>XPathReader</code> with a do-nothing
90 * <code>XPathHandler</code>.
91 */
92 public XPathReader()
93 {
94 setXPathHandler( defaultHandler );
95 }
96
97 public void setXPathHandler(XPathHandler handler)
98 {
99 this.handler = handler;
100 }
101
102 public XPathHandler getXPathHandler()
103 {
104 return this.handler;
105 }
106
107 public void parse(String xpath) throws SAXPathException
108 {
109 setUpParse( xpath );
110
111 getXPathHandler().startXPath();
112
113 expr();
114
115 getXPathHandler().endXPath();
116
117 if ( LA(1) != TokenTypes.EOF )
118 {
119 XPathSyntaxException ex = createSyntaxException( "Unexpected '" + LT(1).getTokenText() + "'" );
120 throw ex;
121 }
122
123 lexer = null;
124 tokens = null;
125 }
126
127 void setUpParse(String xpath)
128 {
129 this.tokens = new LinkedList();
130 this.lexer = new XPathLexer( xpath );
131 }
132
133 private void pathExpr() throws SAXPathException
134 {
135 getXPathHandler().startPathExpr();
136
137 switch ( LA(1) )
138 {
139 case TokenTypes.INTEGER:
140 case TokenTypes.DOUBLE:
141 case TokenTypes.LITERAL:
142 {
143 filterExpr();
144
145 if ( LA(1) == TokenTypes.SLASH || LA(1) == TokenTypes.DOUBLE_SLASH )
146 {
147 XPathSyntaxException ex = createSyntaxException("Node-set expected");
148 throw ex;
149 }
150
151 break;
152 }
153 case TokenTypes.LEFT_PAREN:
154 case TokenTypes.DOLLAR:
155 {
156 filterExpr();
157
158 if ( LA(1) == TokenTypes.SLASH || LA(1) == TokenTypes.DOUBLE_SLASH)
159 {
160 locationPath( false );
161 }
162 break;
163 }
164 case TokenTypes.IDENTIFIER:
165 {
166
167 if ( ( LA(2) == TokenTypes.LEFT_PAREN
168 &&
169 ! isNodeTypeName( LT(1) ) )
170 ||
171 ( LA(2) == TokenTypes.COLON
172 &&
173 LA(4) == TokenTypes.LEFT_PAREN) )
174 {
175 filterExpr();
176
177 if ( LA(1) == TokenTypes.SLASH || LA(1) == TokenTypes.DOUBLE_SLASH)
178 {
179 locationPath( false );
180 }
181 }
182 else
183 {
184 locationPath( false );
185 }
186 break;
187 }
188 case TokenTypes.DOT:
189 case TokenTypes.DOT_DOT:
190 case TokenTypes.STAR:
191 case TokenTypes.AT:
192 {
193 locationPath( false );
194 break;
195 }
196 case TokenTypes.SLASH:
197 case TokenTypes.DOUBLE_SLASH:
198 {
199 locationPath( true );
200 break;
201 }
202 default:
203 {
204 XPathSyntaxException ex = createSyntaxException( "Unexpected '" + LT(1).getTokenText() + "'" );
205 throw ex;
206 }
207 }
208
209 getXPathHandler().endPathExpr();
210 }
211
212 private void numberDouble() throws SAXPathException
213 {
214 Token token = match( TokenTypes.DOUBLE );
215
216 getXPathHandler().number( Double.parseDouble( token.getTokenText() ) );
217 }
218
219 private void numberInteger() throws SAXPathException
220 {
221 Token token = match( TokenTypes.INTEGER );
222
223 String text = token.getTokenText();
224 try {
225 getXPathHandler().number( Integer.parseInt( text ) );
226 }
227 catch (NumberFormatException ex) {
228 getXPathHandler().number( Double.parseDouble( text ) );
229 }
230
231 }
232
233 private void literal() throws SAXPathException
234 {
235 Token token = match( TokenTypes.LITERAL );
236
237 getXPathHandler().literal( token.getTokenText() );
238 }
239
240 private void functionCall() throws SAXPathException
241 {
242 String prefix = null;
243 String functionName = null;
244
245 if ( LA(2) == TokenTypes.COLON )
246 {
247 prefix = match( TokenTypes.IDENTIFIER ).getTokenText();
248 match( TokenTypes.COLON );
249 }
250 else
251 {
252 prefix = "";
253 }
254
255 functionName = match( TokenTypes.IDENTIFIER ).getTokenText();
256
257 getXPathHandler().startFunction( prefix,
258 functionName );
259
260 match ( TokenTypes.LEFT_PAREN );
261
262 arguments();
263
264 match ( TokenTypes.RIGHT_PAREN );
265
266 getXPathHandler().endFunction();
267 }
268
269 private void arguments() throws SAXPathException
270 {
271 while ( LA(1) != TokenTypes.RIGHT_PAREN )
272 {
273 expr();
274
275 if ( LA(1) == TokenTypes.COMMA )
276 {
277 match( TokenTypes.COMMA );
278 }
279 else
280 {
281 break;
282 }
283 }
284 }
285
286 private void filterExpr() throws SAXPathException
287 {
288
289 getXPathHandler().startFilterExpr();
290
291 switch ( LA(1) )
292 {
293 case TokenTypes.INTEGER:
294 {
295 numberInteger();
296 break;
297 }
298 case TokenTypes.DOUBLE:
299 {
300 numberDouble();
301 break;
302 }
303 case TokenTypes.LITERAL:
304 {
305 literal();
306 break;
307 }
308 case TokenTypes.LEFT_PAREN:
309 {
310 match( TokenTypes.LEFT_PAREN );
311 expr();
312 match( TokenTypes.RIGHT_PAREN );
313 break;
314 }
315 case TokenTypes.IDENTIFIER:
316 {
317 functionCall();
318 break;
319 }
320 case TokenTypes.DOLLAR:
321 {
322 variableReference();
323 break;
324 }
325 }
326
327 predicates();
328
329 getXPathHandler().endFilterExpr();
330 }
331
332 private void variableReference() throws SAXPathException
333 {
334 match( TokenTypes.DOLLAR );
335
336 String prefix = null;
337 String variableName = null;
338
339 if ( LA(2) == TokenTypes.COLON )
340 {
341 prefix = match( TokenTypes.IDENTIFIER ).getTokenText();
342 match( TokenTypes.COLON );
343 }
344 else
345 {
346 prefix = "";
347 }
348
349 variableName = match( TokenTypes.IDENTIFIER ).getTokenText();
350
351 getXPathHandler().variableReference( prefix,
352 variableName );
353 }
354
355 void locationPath(boolean isAbsolute) throws SAXPathException
356 {
357 switch ( LA(1) )
358 {
359 case TokenTypes.SLASH:
360 case TokenTypes.DOUBLE_SLASH:
361 {
362 if ( isAbsolute )
363 {
364 absoluteLocationPath();
365 }
366 else
367 {
368 relativeLocationPath();
369 }
370 break;
371 }
372 case TokenTypes.AT:
373 case TokenTypes.IDENTIFIER:
374 case TokenTypes.DOT:
375 case TokenTypes.DOT_DOT:
376 case TokenTypes.STAR:
377 {
378 relativeLocationPath();
379 break;
380 }
381 default:
382 {
383 XPathSyntaxException ex = createSyntaxException( "Unexpected '" + LT(1).getTokenText() + "'" );
384 throw ex;
385 }
386 }
387 }
388
389 private void absoluteLocationPath() throws SAXPathException
390 {
391 getXPathHandler().startAbsoluteLocationPath();
392
393 switch ( LA(1) )
394 {
395 case TokenTypes.SLASH:
396 {
397 match( TokenTypes.SLASH );
398
399 switch ( LA(1) )
400 {
401
402 case TokenTypes.DOT:
403 case TokenTypes.DOT_DOT:
404 case TokenTypes.AT:
405 case TokenTypes.IDENTIFIER:
406 case TokenTypes.STAR:
407 {
408 steps();
409 break;
410 }
411 }
412 break;
413 }
414 case TokenTypes.DOUBLE_SLASH:
415 {
416 getXPathHandler().startAllNodeStep( Axis.DESCENDANT_OR_SELF );
417 getXPathHandler().endAllNodeStep();
418
419 match( TokenTypes.DOUBLE_SLASH );
420 switch ( LA(1) )
421 {
422 case TokenTypes.DOT:
423 case TokenTypes.DOT_DOT:
424 case TokenTypes.AT:
425 case TokenTypes.IDENTIFIER:
426 case TokenTypes.STAR:
427 {
428 steps();
429 break;
430 }
431 default:
432 XPathSyntaxException ex = this.createSyntaxException("Location path cannot end with //");
433 throw ex;
434 }
435 break;
436 }
437 }
438
439 getXPathHandler().endAbsoluteLocationPath();
440 }
441
442 private void relativeLocationPath() throws SAXPathException
443 {
444 getXPathHandler().startRelativeLocationPath();
445
446 switch ( LA(1) )
447 {
448 case TokenTypes.SLASH:
449 {
450 match( TokenTypes.SLASH );
451 break;
452 }
453 case TokenTypes.DOUBLE_SLASH:
454 {
455 getXPathHandler().startAllNodeStep( Axis.DESCENDANT_OR_SELF );
456 getXPathHandler().endAllNodeStep();
457
458 match( TokenTypes.DOUBLE_SLASH );
459
460 break;
461 }
462 }
463
464 steps();
465
466 getXPathHandler().endRelativeLocationPath();
467 }
468
469 private void steps() throws SAXPathException
470 {
471 switch ( LA(1) )
472 {
473
474 case TokenTypes.DOT:
475 case TokenTypes.DOT_DOT:
476 case TokenTypes.AT:
477 case TokenTypes.IDENTIFIER:
478 case TokenTypes.STAR:
479 {
480 step();
481 break;
482 }
483 case TokenTypes.EOF:
484 {
485 return;
486 }
487 default:
488 {
489 XPathSyntaxException ex = createSyntaxException( "Expected one of '.', '..', '@', '*', <QName>" );
490 throw ex;
491 }
492 }
493
494 do
495 {
496 if ( ( LA(1) == TokenTypes.SLASH)
497 ||
498 ( LA(1) == TokenTypes.DOUBLE_SLASH ) )
499 {
500 switch ( LA(1) )
501 {
502 case TokenTypes.SLASH:
503 {
504 match( TokenTypes.SLASH );
505 break;
506 }
507 case TokenTypes.DOUBLE_SLASH:
508 {
509 getXPathHandler().startAllNodeStep( Axis.DESCENDANT_OR_SELF );
510 getXPathHandler().endAllNodeStep();
511
512 match( TokenTypes.DOUBLE_SLASH );
513 break;
514 }
515 }
516 }
517 else
518 {
519 return;
520 }
521
522 switch ( LA(1) )
523 {
524 case TokenTypes.DOT:
525 case TokenTypes.DOT_DOT:
526 case TokenTypes.AT:
527 case TokenTypes.IDENTIFIER:
528 case TokenTypes.STAR:
529 {
530 step();
531 break;
532 }
533 default:
534 {
535 XPathSyntaxException ex = createSyntaxException( "Expected one of '.', '..', '@', '*', <QName>" );
536 throw ex;
537 }
538 }
539
540 } while ( true );
541 }
542
543 void step() throws SAXPathException
544 {
545 int axis = 0;
546
547 switch ( LA(1) )
548 {
549 case TokenTypes.DOT:
550 case TokenTypes.DOT_DOT:
551 {
552 abbrStep();
553 return;
554 }
555 case TokenTypes.AT:
556 {
557 axis = axisSpecifier();
558 break;
559 }
560 case TokenTypes.IDENTIFIER:
561 {
562 if ( LA(2) == TokenTypes.DOUBLE_COLON )
563 {
564 axis = axisSpecifier();
565 }
566 else
567 {
568 axis = Axis.CHILD;
569 }
570 break;
571 }
572 case TokenTypes.STAR:
573 {
574 axis = Axis.CHILD;
575 break;
576 }
577 }
578
579 nodeTest( axis );
580 }
581
582 private int axisSpecifier() throws SAXPathException
583 {
584 int axis = 0;
585
586 switch ( LA(1) )
587 {
588 case TokenTypes.AT:
589 {
590 match( TokenTypes.AT );
591 axis = Axis.ATTRIBUTE;
592 break;
593 }
594 case TokenTypes.IDENTIFIER:
595 {
596 Token token = LT( 1 );
597
598 axis = Axis.lookup( token.getTokenText() );
599
600 if ( axis == Axis.INVALID_AXIS )
601 {
602 throwInvalidAxis( token.getTokenText() );
603 }
604
605 match( TokenTypes.IDENTIFIER );
606 match( TokenTypes.DOUBLE_COLON );
607
608 break;
609 }
610 }
611
612 return axis;
613 }
614
615 private void nodeTest(int axis) throws SAXPathException
616 {
617 switch ( LA(1) )
618 {
619 case TokenTypes.IDENTIFIER:
620 {
621 switch ( LA(2) )
622 {
623 case TokenTypes.LEFT_PAREN:
624 {
625 nodeTypeTest( axis );
626 break;
627 }
628 default:
629 {
630 nameTest( axis );
631 break;
632 }
633 }
634 break;
635 }
636 case TokenTypes.STAR:
637 {
638 nameTest( axis );
639 break;
640 }
641 default:
642 XPathSyntaxException ex = createSyntaxException("Expected <QName> or *");
643 throw ex;
644 }
645 }
646
647 private void nodeTypeTest(int axis) throws SAXPathException
648 {
649 Token nodeTypeToken = match( TokenTypes.IDENTIFIER );
650 String nodeType = nodeTypeToken.getTokenText();
651
652 match( TokenTypes.LEFT_PAREN );
653
654 if ( "processing-instruction".equals( nodeType ) )
655 {
656 String piName = "";
657
658 if ( LA(1) == TokenTypes.LITERAL )
659 {
660 piName = match( TokenTypes.LITERAL ).getTokenText();
661 }
662
663 match( TokenTypes.RIGHT_PAREN );
664
665 getXPathHandler().startProcessingInstructionNodeStep( axis,
666 piName );
667
668 predicates();
669
670 getXPathHandler().endProcessingInstructionNodeStep();
671 }
672 else if ( "node".equals( nodeType ) )
673 {
674 match( TokenTypes.RIGHT_PAREN );
675
676 getXPathHandler().startAllNodeStep( axis );
677
678 predicates();
679
680 getXPathHandler().endAllNodeStep();
681 }
682 else if ( "text".equals( nodeType ) )
683 {
684 match( TokenTypes.RIGHT_PAREN );
685
686 getXPathHandler().startTextNodeStep( axis );
687
688 predicates();
689
690 getXPathHandler().endTextNodeStep();
691 }
692 else if ( "comment".equals( nodeType ) )
693 {
694 match( TokenTypes.RIGHT_PAREN );
695
696 getXPathHandler().startCommentNodeStep( axis );
697
698 predicates();
699
700 getXPathHandler().endCommentNodeStep();
701 }
702 else
703 {
704 XPathSyntaxException ex = createSyntaxException( "Expected node-type" );
705 throw ex;
706 }
707 }
708
709 private void nameTest(int axis) throws SAXPathException
710 {
711 String prefix = null;
712 String localName = null;
713
714 switch ( LA(2) )
715 {
716 case TokenTypes.COLON:
717 {
718 switch ( LA(1) )
719 {
720 case TokenTypes.IDENTIFIER:
721 {
722 prefix = match( TokenTypes.IDENTIFIER ).getTokenText();
723 match( TokenTypes.COLON );
724 break;
725 }
726 }
727 break;
728 }
729 }
730
731 switch ( LA(1) )
732 {
733 case TokenTypes.IDENTIFIER:
734 {
735 localName = match( TokenTypes.IDENTIFIER ).getTokenText();
736 break;
737 }
738 case TokenTypes.STAR:
739 {
740 match( TokenTypes.STAR );
741 localName = "*";
742 break;
743 }
744 }
745
746 if ( prefix == null )
747 {
748 prefix = "";
749 }
750
751 getXPathHandler().startNameStep( axis,
752 prefix,
753 localName );
754
755 predicates();
756
757 getXPathHandler().endNameStep();
758 }
759
760 private void abbrStep() throws SAXPathException
761 {
762 switch ( LA(1) )
763 {
764 case TokenTypes.DOT:
765 {
766 match( TokenTypes.DOT );
767 getXPathHandler().startAllNodeStep( Axis.SELF );
768 predicates();
769 getXPathHandler().endAllNodeStep();
770 break;
771 }
772 case TokenTypes.DOT_DOT:
773 {
774 match( TokenTypes.DOT_DOT );
775 getXPathHandler().startAllNodeStep( Axis.PARENT );
776 predicates();
777 getXPathHandler().endAllNodeStep();
778 break;
779 }
780 }
781 }
782
783 private void predicates() throws SAXPathException
784 {
785 while (true )
786 {
787 if ( LA(1) == TokenTypes.LEFT_BRACKET )
788 {
789 predicate();
790 }
791 else
792 {
793 break;
794 }
795 }
796 }
797
798 void predicate() throws SAXPathException
799 {
800 getXPathHandler().startPredicate();
801
802 match( TokenTypes.LEFT_BRACKET );
803
804 predicateExpr();
805
806 match( TokenTypes.RIGHT_BRACKET );
807
808 getXPathHandler().endPredicate();
809 }
810
811 private void predicateExpr() throws SAXPathException
812 {
813 expr();
814 }
815
816 private void expr() throws SAXPathException
817 {
818 orExpr();
819 }
820
821 private void orExpr() throws SAXPathException
822 {
823 getXPathHandler().startOrExpr();
824
825 andExpr();
826
827 boolean create = false;
828
829 switch ( LA(1) )
830 {
831 case TokenTypes.OR:
832 {
833 create = true;
834 match( TokenTypes.OR );
835 orExpr();
836 break;
837 }
838 }
839
840 getXPathHandler().endOrExpr( create );
841 }
842
843 private void andExpr() throws SAXPathException
844 {
845 getXPathHandler().startAndExpr();
846
847 equalityExpr();
848
849 boolean create = false;
850
851 switch ( LA(1) )
852 {
853 case TokenTypes.AND:
854 {
855 create = true;
856 match( TokenTypes.AND );
857 andExpr();
858 break;
859 }
860 }
861
862 getXPathHandler().endAndExpr( create );
863 }
864
865 private void equalityExpr() throws SAXPathException
866 {
867 relationalExpr();
868
869 int la = LA(1);
870 while (la == TokenTypes.EQUALS || la == TokenTypes.NOT_EQUALS)
871 {
872 switch ( la )
873 {
874 case TokenTypes.EQUALS:
875 {
876 match( TokenTypes.EQUALS );
877 getXPathHandler().startEqualityExpr();
878 relationalExpr();
879 getXPathHandler().endEqualityExpr( Operator.EQUALS );
880 break;
881 }
882 case TokenTypes.NOT_EQUALS:
883 {
884 match( TokenTypes.NOT_EQUALS );
885 getXPathHandler().startEqualityExpr();
886 relationalExpr();
887 getXPathHandler().endEqualityExpr( Operator.NOT_EQUALS );
888 break;
889 }
890 }
891 la = LA(1);
892 }
893 }
894
895 private void relationalExpr() throws SAXPathException
896 {
897
898 additiveExpr();
899
900 int la = LA(1);
901
902
903
904
905 while (la == TokenTypes.LESS_THAN_SIGN
906 || la == TokenTypes.GREATER_THAN_SIGN
907 || la == TokenTypes.LESS_THAN_OR_EQUALS_SIGN
908 || la == TokenTypes.GREATER_THAN_OR_EQUALS_SIGN ) {
909 switch ( la )
910 {
911 case TokenTypes.LESS_THAN_SIGN:
912 {
913 match( TokenTypes.LESS_THAN_SIGN );
914 getXPathHandler().startRelationalExpr();
915 additiveExpr();
916 getXPathHandler().endRelationalExpr( Operator.LESS_THAN );
917 break;
918 }
919 case TokenTypes.GREATER_THAN_SIGN:
920 {
921 match( TokenTypes.GREATER_THAN_SIGN );
922 getXPathHandler().startRelationalExpr();
923 additiveExpr();
924 getXPathHandler().endRelationalExpr( Operator.GREATER_THAN );
925 break;
926 }
927 case TokenTypes.GREATER_THAN_OR_EQUALS_SIGN:
928 {
929 match( TokenTypes.GREATER_THAN_OR_EQUALS_SIGN );
930 getXPathHandler().startRelationalExpr();
931 additiveExpr();
932 getXPathHandler().endRelationalExpr( Operator.GREATER_THAN_EQUALS );
933 break;
934 }
935 case TokenTypes.LESS_THAN_OR_EQUALS_SIGN:
936 {
937 match( TokenTypes.LESS_THAN_OR_EQUALS_SIGN );
938 getXPathHandler().startRelationalExpr();
939 additiveExpr();
940 getXPathHandler().endRelationalExpr( Operator.LESS_THAN_EQUALS );
941 break;
942 }
943 }
944 la = LA(1);
945 }
946 }
947
948
949 private void additiveExpr() throws SAXPathException
950 {
951 multiplicativeExpr();
952
953 int la = LA(1);
954 while (la == TokenTypes.PLUS || la == TokenTypes.MINUS)
955 {
956 switch ( la )
957 {
958 case TokenTypes.PLUS:
959 {
960 match( TokenTypes.PLUS );
961 getXPathHandler().startAdditiveExpr();
962 multiplicativeExpr();
963 getXPathHandler().endAdditiveExpr( Operator.ADD );
964 break;
965 }
966 case TokenTypes.MINUS:
967 {
968 match( TokenTypes.MINUS );
969 getXPathHandler().startAdditiveExpr();
970 multiplicativeExpr();
971 getXPathHandler().endAdditiveExpr( Operator.SUBTRACT );
972 break;
973 }
974 }
975 la = LA(1);
976 }
977 }
978
979 private void multiplicativeExpr() throws SAXPathException
980 {
981 unaryExpr();
982
983 int la = LA(1);
984 while (la == TokenTypes.STAR || la == TokenTypes.DIV || la == TokenTypes.MOD)
985 {
986 switch ( la )
987 {
988 case TokenTypes.STAR:
989 {
990 match( TokenTypes.STAR );
991 getXPathHandler().startMultiplicativeExpr();
992 unaryExpr();
993 getXPathHandler().endMultiplicativeExpr( Operator.MULTIPLY );
994 break;
995 }
996 case TokenTypes.DIV:
997 {
998 match( TokenTypes.DIV );
999 getXPathHandler().startMultiplicativeExpr();
1000 unaryExpr();
1001 getXPathHandler().endMultiplicativeExpr( Operator.DIV );
1002 break;
1003 }
1004 case TokenTypes.MOD:
1005 {
1006 match( TokenTypes.MOD );
1007 getXPathHandler().startMultiplicativeExpr();
1008 unaryExpr();
1009 getXPathHandler().endMultiplicativeExpr( Operator.MOD );
1010 break;
1011 }
1012 }
1013 la = LA(1);
1014 }
1015
1016 }
1017
1018 private void unaryExpr() throws SAXPathException
1019 {
1020 switch ( LA(1) )
1021 {
1022 case TokenTypes.MINUS:
1023 {
1024 getXPathHandler().startUnaryExpr();
1025 match( TokenTypes.MINUS );
1026 unaryExpr();
1027 getXPathHandler().endUnaryExpr( Operator.NEGATIVE );
1028 break;
1029 }
1030 default:
1031 {
1032 unionExpr();
1033 break;
1034 }
1035 }
1036
1037
1038 }
1039
1040 private void unionExpr() throws SAXPathException
1041 {
1042 getXPathHandler().startUnionExpr();
1043
1044 pathExpr();
1045
1046 boolean create = false;
1047
1048 switch ( LA(1) )
1049 {
1050 case TokenTypes.PIPE:
1051 {
1052 match( TokenTypes.PIPE );
1053 create = true;
1054 expr();
1055 break;
1056 }
1057 }
1058
1059 getXPathHandler().endUnionExpr( create );
1060 }
1061
1062 private Token match(int tokenType) throws XPathSyntaxException
1063 {
1064 LT(1);
1065
1066 Token token = (Token) tokens.get( 0 );
1067
1068 if ( token.getTokenType() == tokenType )
1069 {
1070 tokens.removeFirst();
1071 return token;
1072 }
1073
1074
1075 XPathSyntaxException ex = createSyntaxException( "Expected: " + TokenTypes.getTokenText( tokenType ) );
1076 throw ex;
1077 }
1078
1079 private int LA(int position)
1080 {
1081 return LT(position).getTokenType();
1082 }
1083
1084 private Token LT(int position)
1085 {
1086 if ( tokens.size() <= ( position - 1 ) )
1087 {
1088 for ( int i = 0 ; i < position ; ++i )
1089 {
1090 tokens.add( lexer.nextToken() );
1091 }
1092 }
1093
1094 return (Token) tokens.get( position - 1 );
1095 }
1096
1097 private boolean isNodeTypeName(Token name)
1098 {
1099 String text = name.getTokenText();
1100
1101 if ( "node".equals( text )
1102 ||
1103 "comment".equals( text )
1104 ||
1105 "text".equals( text )
1106 ||
1107 "processing-instruction".equals( text ) )
1108 {
1109 return true;
1110 }
1111
1112 return false;
1113 }
1114
1115 private XPathSyntaxException createSyntaxException(String message)
1116 {
1117 String xpath = this.lexer.getXPath();
1118 int position = LT(1).getTokenBegin();
1119
1120 return new XPathSyntaxException( xpath,
1121 position,
1122 message );
1123 }
1124
1125 private void throwInvalidAxis(String invalidAxis) throws SAXPathException
1126 {
1127 String xpath = this.lexer.getXPath();
1128 int position = LT(1).getTokenBegin();
1129
1130 String message = "Expected valid axis name instead of [" + invalidAxis + "]";
1131
1132 throw new XPathSyntaxException( xpath,
1133 position,
1134 message );
1135 }
1136 }