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