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