Coverage Report - org.jaxen.saxpath.base.XPathReader

Classes in this Package Line Coverage Branch Coverage Complexity
XPathReader
97% 
100% 
4.214

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