Clover coverage report - groovy - 1.0-beta-6
Coverage timestamp: Thu Jul 15 2004 13:18:22 BST
file stats: LOC: 468   Methods: 28
NCLOC: 206   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
LexerBase.java 0% 0% 0% 0%
coverage
 1   
 package org.codehaus.groovy.syntax.lexer;
 2   
 
 3   
 import org.codehaus.groovy.syntax.ReadException;
 4   
 import org.codehaus.groovy.syntax.Types;
 5   
 import org.codehaus.groovy.syntax.Token;
 6   
 import org.codehaus.groovy.GroovyBugError;
 7   
 
 8   
 
 9   
 /**
 10   
  *  A base class for all other lexers.
 11   
  *
 12   
  *  @author Bob Mcwhirter
 13   
  *  @author James Strachan
 14   
  *  @author John Wilson
 15   
  *  @author Chris Poirier
 16   
  */
 17   
 
 18   
 public class LexerBase implements Lexer
 19   
 {
 20   
 
 21   
     protected int startLine;                 // the start line of the current token
 22   
     protected int startColumn;               // the start column of the current token
 23   
 
 24   
     protected Lexer delegate = null;         // another lexer currently satisfying our requests
 25   
     protected Lexer source   = null;         // a lexer we are obtaining data from
 26   
 
 27   
 
 28   
 
 29   
    /**
 30   
     *  Initializes the <code>LexerBase</code>.
 31   
     */
 32   
 
 33  0
     public LexerBase( )
 34   
     {
 35   
     }
 36   
 
 37   
 
 38   
 
 39   
    /**
 40   
     *  Gets the lexer that is actually doing the <code>nextToken()</code>
 41   
     *  work, if it isn't us.
 42   
     */
 43   
 
 44  0
     public Lexer getDelegate()
 45   
     {
 46  0
         return delegate;
 47   
     }
 48   
 
 49   
 
 50   
 
 51   
    /**
 52   
     *  Gets the lexer from which this lexer is obtaining characters.
 53   
     */
 54   
 
 55  0
     public Lexer getSource()
 56   
     {
 57  0
         return source;
 58   
     }
 59   
 
 60   
 
 61   
 
 62   
    /**
 63   
     *  Finds and returns (consuming) the next token from the underlying stream.
 64   
     *  Returns null when out of tokens.  This implementation correctly handles
 65   
     *  delegation, and subclasses implement undelegatedNextToken(), which will
 66   
     *  be called by this routine when appropriate.
 67   
     */
 68   
 
 69  0
     public Token nextToken() throws ReadException, LexerException
 70   
     {
 71   
         //
 72   
         // If we are delegated, use it until it returns null.
 73   
 
 74  0
         if( delegate != null )
 75   
         {
 76  0
             Token next = delegate.nextToken();
 77   
 
 78  0
             if( next == null )
 79   
             {
 80  0
                 undelegate();
 81   
             }
 82   
             else
 83   
             {
 84  0
                 return next;
 85   
             }
 86   
 
 87   
         }
 88   
 
 89  0
         mark();
 90  0
         return undelegatedNextToken();
 91   
     }
 92   
 
 93   
 
 94   
 
 95   
    /**
 96   
     *  Does undelegated nextToken() operations.  You supply your
 97   
     *  lexer-specific nextToken() code by overriding this method.
 98   
     */
 99   
 
 100  0
     protected Token undelegatedNextToken() throws ReadException, LexerException
 101   
     {
 102  0
         return null;
 103   
     }
 104   
 
 105   
 
 106   
 
 107   
 
 108   
   //---------------------------------------------------------------------------
 109   
   // SPECIAL HANDLERS
 110   
 
 111   
 
 112   
    /**
 113   
     *  Process an end-of-line marker and returns a NEWLINE token.
 114   
     *  Returns null if not at an end-of-line.
 115   
     */
 116   
 
 117  0
     protected Token tokenizeEOL() throws LexerException, ReadException
 118   
     {
 119  0
         Token token = null;
 120   
 
 121  0
         char c = la();
 122  0
         switch( c )
 123   
         {
 124   
             case '\r':
 125   
             case '\n':
 126  0
                 token = symbol( Types.NEWLINE );
 127   
 
 128  0
                 consume();
 129  0
                 if (c == '\r' && la() == '\n')
 130   
                 {
 131  0
                     consume();
 132   
                 }
 133   
         }
 134   
 
 135  0
         return token;
 136   
     }
 137   
 
 138   
 
 139   
 
 140   
    /**
 141   
     *  Reads an end-of-line marker and writes the text into the
 142   
     *  specified buffer, if supplied.
 143   
     */
 144   
 
 145  0
     protected boolean readEOL( StringBuffer destination ) throws LexerException, ReadException
 146   
     {
 147  0
         boolean read = false;
 148   
 
 149  0
         char c = la();
 150  0
         switch( c )
 151   
         {
 152   
             case '\r':
 153   
             case '\n':
 154  0
                 if( destination == null )
 155   
                 {
 156  0
                     consume();
 157  0
                     if (c == '\r' && la() == '\n')
 158   
                     {
 159  0
                         consume();
 160   
                     }
 161   
                 }
 162   
                 else
 163   
                 {
 164  0
                     destination.append( consume() );
 165  0
                     if (c == '\r' && la() == '\n')
 166   
                     {
 167  0
                         destination.append( consume() );
 168   
                     }
 169   
                 }
 170   
 
 171  0
                 read = true;
 172   
         }
 173   
 
 174  0
         return read;
 175   
     }
 176   
 
 177   
 
 178   
 
 179   
    /**
 180   
     *  Synonym for <code>readEOL(null)</code>.
 181   
     */
 182   
 
 183  0
     protected void readEOL() throws LexerException, ReadException
 184   
     {
 185  0
         readEOL( null );
 186   
     }
 187   
 
 188   
 
 189   
 
 190   
 
 191   
 
 192   
   //---------------------------------------------------------------------------
 193   
   // DELEGATION
 194   
 
 195   
 
 196   
    /**
 197   
     *  Resets a lexer for reuse.
 198   
     */
 199   
 
 200  0
     public void reset()
 201   
     {
 202  0
         delegate = null;
 203  0
         source   = null;
 204   
     }
 205   
 
 206   
 
 207   
 
 208   
    /**
 209   
     *  Delegates our duties to another Lexer.
 210   
     */
 211   
 
 212  0
     public void delegate( Lexer to )
 213   
     {
 214  0
         this.delegate = to;
 215  0
         to.setSource( this );
 216   
     }
 217   
 
 218   
 
 219   
 
 220   
    /**
 221   
     *  Retakes responsibility for our duties.
 222   
     */
 223   
 
 224  0
     public void undelegate()
 225   
     {
 226  0
         if( delegate != null )
 227   
         {
 228  0
             delegate.unsetSource( );
 229  0
             delegate = null;
 230   
         }
 231   
     }
 232   
 
 233   
 
 234   
 
 235   
    /**
 236   
     *  Sets the source lexer.
 237   
     */
 238   
 
 239  0
     public void setSource( Lexer source )
 240   
     {
 241  0
         if( source == null )
 242   
         {
 243  0
             throw new GroovyBugError( "use unsetSource() to remove a source from a lexer" );
 244   
         }
 245  0
         this.source = source;
 246   
     }
 247   
 
 248   
 
 249   
 
 250   
    /**
 251   
     *  Unsets the source lexer.
 252   
     */
 253   
 
 254  0
     public void unsetSource()
 255   
     {
 256  0
         this.source = null;
 257   
     }
 258   
 
 259   
 
 260   
 
 261   
    /**
 262   
     *  Returns true if we are delegated to another lexer.
 263   
     */
 264   
 
 265  0
     public boolean isDelegated()
 266   
     {
 267  0
         return delegate != null;
 268   
     }
 269   
 
 270   
 
 271   
 
 272   
    /**
 273   
     *  Returns true if we are obtaining our characters
 274   
     *  from another lexer.
 275   
     */
 276   
 
 277  0
     public boolean isExternallySourced()
 278   
     {
 279  0
         return source != null;
 280   
     }
 281   
 
 282   
 
 283   
 
 284   
 
 285   
   //---------------------------------------------------------------------------
 286   
   // ERROR HANDLING
 287   
 
 288   
 
 289   
    /**
 290   
     *  Creates and throws a new <code>UnexpectedCharacterException</code>.
 291   
     */
 292   
 
 293  0
     protected void unexpected( char c, int offset, String message ) throws UnexpectedCharacterException
 294   
     {
 295  0
         throw new UnexpectedCharacterException( getStartLine(), getStartColumn() + offset, c, message );
 296   
     }
 297   
 
 298   
 
 299   
 
 300   
    /**
 301   
     *  Creates and throws a new <code>UnexpectedCharacterException</code>.
 302   
     */
 303   
 
 304  0
     protected void unexpected( char c, char[] expected, int offset ) throws UnexpectedCharacterException
 305   
     {
 306  0
         throw new UnexpectedCharacterException( getStartLine(), getStartColumn() + offset, c, expected );
 307   
     }
 308   
 
 309   
 
 310   
 
 311   
    /**
 312   
     *  Synonym for <code>unexpected( c, null, offset )</code>.
 313   
     */
 314   
 
 315  0
     protected void unexpected( char c, int offset ) throws UnexpectedCharacterException
 316   
     {
 317  0
         unexpected( c, null, offset );
 318   
     }
 319   
 
 320   
 
 321   
 
 322   
 
 323   
   //---------------------------------------------------------------------------
 324   
   // SUPPORT ROUTINES
 325   
 
 326   
 
 327   
    /**
 328   
     *  Creates a new symbol token, and allows you to alter the starting
 329   
     *  column.
 330   
     */
 331   
 
 332  0
     protected Token symbol( int type, int columnOffset )
 333   
     {
 334  0
         return Token.newSymbol( type, getStartLine(), getStartColumn() - columnOffset );
 335   
     }
 336   
 
 337   
 
 338   
 
 339   
    /**
 340   
     *  Creates a new symbol token.
 341   
     */
 342   
 
 343  0
     protected Token symbol( int type )
 344   
     {
 345  0
         return Token.newSymbol( type, getStartLine(), getStartColumn() );
 346   
     }
 347   
 
 348   
 
 349   
 
 350   
 
 351   
   //---------------------------------------------------------------------------
 352   
   // STREAM ROUTINES
 353   
 
 354   
 
 355   
    /**
 356   
     *  Returns the current line number.
 357   
     */
 358   
 
 359  0
     public int getLine()
 360   
     {
 361  0
         if( source != null )
 362   
         {
 363  0
             return source.getLine();
 364   
         }
 365   
 
 366  0
         return -1;
 367   
     }
 368   
 
 369   
 
 370   
 
 371   
    /**
 372   
     *  Returns the current column within that line.
 373   
     */
 374   
 
 375  0
     public int getColumn()
 376   
     {
 377  0
         if( source != null )
 378   
         {
 379  0
             return source.getColumn();
 380   
         }
 381   
 
 382  0
         return -1;
 383   
     }
 384   
 
 385   
 
 386   
 
 387   
    /**
 388   
     *  Saves information about the current position, for tracking token extents.
 389   
     */
 390   
 
 391  0
     protected void mark()
 392   
     {
 393  0
         startLine   = getLine();
 394  0
         startColumn = getColumn();
 395   
     }
 396   
 
 397   
 
 398   
 
 399   
    /**
 400   
     *  Returns the starting line of the current token.
 401   
     */
 402   
 
 403  0
     protected int getStartLine()
 404   
     {
 405  0
         return this.startLine;
 406   
     }
 407   
 
 408   
 
 409   
 
 410   
    /**
 411   
     *  Returns the starting column of the current token.
 412   
     */
 413   
 
 414  0
     protected int getStartColumn()
 415   
     {
 416  0
         return this.startColumn;
 417   
     }
 418   
 
 419   
 
 420   
 
 421   
    /**
 422   
     *  Returns the next character, without consuming it.
 423   
     */
 424   
 
 425  0
     public char la() throws LexerException, ReadException
 426   
     {
 427  0
         return la(1);
 428   
     }
 429   
 
 430   
 
 431   
 
 432   
    /**
 433   
     *  Returns the next <code>k</code>th character, without consuming any.
 434   
     */
 435   
 
 436  0
     public char la(int k) throws LexerException, ReadException
 437   
     {
 438  0
         if( source != null )
 439   
         {
 440  0
             return source.la(k);
 441   
         }
 442   
         else
 443   
         {
 444  0
             return CharStream.EOS;
 445   
         }
 446   
     }
 447   
 
 448   
 
 449   
 
 450   
    /**
 451   
     *  Eats a character from the input stream.
 452   
     */
 453   
 
 454  0
     public char consume() throws LexerException, ReadException
 455   
     {
 456  0
         if( source != null )
 457   
         {
 458  0
             return source.consume();
 459   
         }
 460   
         else
 461   
         {
 462  0
             return CharStream.EOS;
 463   
         }
 464   
     }
 465   
 
 466   
 
 467   
 }
 468