KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jaxen > saxpath > base > XPathReader


1 /*
2  * $Header: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/saxpath/base/XPathReader.java,v 1.25 2005/06/16 13:30:12 elharo Exp $
3  * $Revision: 1.25 $
4  * $Date: 2005/06/16 13:30:12 $
5  *
6  * ====================================================================
7  *
8  * Copyright (C) 2000-2002 bob mcwhirter & James Strachan.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright
16  * notice, this list of conditions, and the following disclaimer.
17  *
18  * 2. Redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions, and the disclaimer that follows
20  * these conditions in the documentation and/or other materials
21  * provided with the distribution.
22  *
23  * 3. The name "Jaxen" must not be used to endorse or promote products
24  * derived from this software without prior written permission. For
25  * written permission, please contact license@jaxen.org.
26  *
27  * 4. Products derived from this software may not be called "Jaxen", nor
28  * may "Jaxen" appear in their name, without prior written permission
29  * from the Jaxen Project Management (pm@jaxen.org).
30  *
31  * In addition, we request (but do not require) that you include in the
32  * end-user documentation provided with the redistribution and/or in the
33  * software itself an acknowledgement equivalent to the following:
34  * "This product includes software developed by the
35  * Jaxen Project (http://www.jaxen.org/)."
36  * Alternatively, the acknowledgment may be graphical using the logos
37  * available at http://www.jaxen.org/
38  *
39  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED TokenTypes.OR IMPLIED
40  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42  * DISCLAIMED. IN NO EVENT SHALL THE Jaxen AUTHORS TokenTypes.OR THE PROJECT
43  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, TokenTypes.OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS TokenTypes.OR SERVICES; LOSS OF
46  * USE, DATA, TokenTypes.OR PROFITS; TokenTypes.OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
47  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
48  * TokenTypes.OR TORT (INCLUDING NEGLIGENCE TokenTypes.OR OTHERWISE) ARISING IN ANY WAY OUT
49  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * ====================================================================
53  * This software consists of voluntary contributions made by many
54  * individuals on behalf of the Jaxen Project and was originally
55  * created by bob mcwhirter <bob@werken.com> and
56  * James Strachan <jstrachan@apache.org>. For more information on the
57  * Jaxen Project, please see <http://www.jaxen.org/>.
58  *
59  * $Id: XPathReader.java,v 1.25 2005/06/16 13:30:12 elharo Exp $
60  */

61
62
63 package org.jaxen.saxpath.base;
64
65 import java.util.LinkedList JavaDoc;
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 JavaDoc 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 JavaDoc 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 JavaDoc xpath)
127     {
128         this.tokens = new LinkedList JavaDoc();
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 JavaDoc text = token.getTokenText();
222         try {
223             getXPathHandler().number( Integer.parseInt( text ) );
224         }
225         catch (NumberFormatException JavaDoc 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 JavaDoc prefix = null;
241         String JavaDoc 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 JavaDoc prefix = null;
335         String JavaDoc 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 JavaDoc nodeType = nodeTypeToken.getTokenText();
646
647         match( TokenTypes.LEFT_PAREN );
648
649         if ( "processing-instruction".equals( nodeType ) )
650         {
651             String JavaDoc 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 JavaDoc prefix = null;
706         String JavaDoc 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         // Very important: TokenTypes.LESS_THAN != Operator.LESS_THAN
896
// TokenTypes.GREATER_THAN != Operator.GREATER_THAN
897
// TokenTypes.GREATER_THAN_EQUALS != Operator.GREATER_THAN_EQUALS
898
// TokenTypes.LESS_THAN_EQUALS != Operator.LESS_THAN_EQUALS
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 JavaDoc 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 JavaDoc message)
1108    {
1109        String JavaDoc 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 JavaDoc invalidAxis) throws SAXPathException
1118    {
1119        String JavaDoc xpath = this.lexer.getXPath();
1120        int position = LT(1).getTokenBegin();
1121
1122        String JavaDoc 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}
1134
Popular Tags