001 /* 002 $Id: Token.java 4032 2006-08-30 07:18:49Z mguillem $ 003 004 Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved. 005 006 Redistribution and use of this software and associated documentation 007 ("Software"), with or without modification, are permitted provided 008 that the following conditions are met: 009 010 1. Redistributions of source code must retain copyright 011 statements and notices. Redistributions must also contain a 012 copy of this document. 013 014 2. Redistributions in binary form must reproduce the 015 above copyright notice, this list of conditions and the 016 following disclaimer in the documentation and/or other 017 materials provided with the distribution. 018 019 3. The name "groovy" must not be used to endorse or promote 020 products derived from this Software without prior written 021 permission of The Codehaus. For written permission, 022 please contact info@codehaus.org. 023 024 4. Products derived from this Software may not be called "groovy" 025 nor may "groovy" appear in their names without prior written 026 permission of The Codehaus. "groovy" is a registered 027 trademark of The Codehaus. 028 029 5. Due credit should be given to The Codehaus - 030 http://groovy.codehaus.org/ 031 032 THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS 033 ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT 034 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 035 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 036 THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 037 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 038 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 039 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 040 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 041 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 042 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 043 OF THE POSSIBILITY OF SUCH DAMAGE. 044 045 */ 046 047 package org.codehaus.groovy.syntax; 048 049 import org.codehaus.groovy.GroovyBugError; 050 051 052 /** 053 * A <code>CSTNode</code> produced by the <code>Lexer</code>. 054 * 055 * @see antlr.Parser 056 * @see antlr.Token 057 * @see Reduction 058 * @see Types 059 * 060 * @author <a href="mailto:bob@werken.com">bob mcwhirter</a> 061 * @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a> 062 * 063 * @version $Id: Token.java 4032 2006-08-30 07:18:49Z mguillem $ 064 */ 065 066 public class Token extends CSTNode 067 { 068 public static final Token NULL = new Token(); 069 public static final Token EOF = new Token( Types.EOF, "", -1, -1 ); 070 071 072 //--------------------------------------------------------------------------- 073 // TOKEN INITIALIZATION AND SUCH 074 075 private int type = Types.UNKNOWN; // the actual type identified by the lexer 076 private int meaning = Types.UNKNOWN; // an interpretation applied to the token after the fact 077 078 private String text = ""; // the text of the token 079 private int startLine = -1; // the source line on which the token begins 080 private int startColumn = -1; // the source column on which the token begins 081 082 083 /** 084 * Initializes the Token with the specified information. 085 */ 086 087 public Token( int type, String text, int startLine, int startColumn ) 088 { 089 this.type = type; 090 this.meaning = type; 091 this.text = text; 092 this.startLine = startLine; 093 this.startColumn = startColumn; 094 } 095 096 097 /** 098 * Initializes the NULL Token. 099 */ 100 101 private Token() { } 102 103 104 105 /** 106 * Returns a copy of this Token. 107 */ 108 109 public Token dup() 110 { 111 Token token = new Token( this.type, this.text, this.startLine, this.startColumn ); 112 token.setMeaning( this.meaning ); 113 114 return token; 115 } 116 117 118 119 120 //--------------------------------------------------------------------------- 121 // NODE IDENTIFICATION AND MEANING 122 123 124 /** 125 * Returns the meaning of this node. If the node isEmpty(), returns 126 * the type of Token.NULL. 127 */ 128 129 public int getMeaning() 130 { 131 return meaning; 132 } 133 134 135 136 /** 137 * Sets the meaning for this node (and it's root Token). Not 138 * valid if the node isEmpty(). Returns this token, for 139 * convenience. 140 */ 141 142 public CSTNode setMeaning( int meaning ) 143 { 144 this.meaning = meaning; 145 return this; 146 } 147 148 149 150 /** 151 * Returns the actual type of the node. If the node isEmpty(), returns 152 * the type of Token.NULL. 153 */ 154 155 public int getType() 156 { 157 return type; 158 } 159 160 161 162 163 //--------------------------------------------------------------------------- 164 // MEMBER ACCESS 165 166 167 /** 168 * Returns the number of elements in the node (including root). 169 */ 170 171 public int size() 172 { 173 return 1; 174 } 175 176 177 178 /** 179 * Returns the specified element, or null. 180 */ 181 182 public CSTNode get( int index ) 183 { 184 if( index > 0 ) 185 { 186 throw new GroovyBugError( "attempt to access Token element other than root" ); 187 } 188 189 return this; 190 } 191 192 193 194 /** 195 * Returns the root of the node. By convention, all nodes have 196 * a Token as the first element (or root), which indicates the type 197 * of the node. May return null if the node <code>isEmpty()</code>. 198 */ 199 200 public Token getRoot() 201 { 202 return this; 203 } 204 205 206 207 /** 208 * Returns the text of the root node. Uses <code>getRoot(true)</code> 209 * to get the root, so you will only receive null in return if the 210 * root token returns it. 211 */ 212 213 public String getRootText() 214 { 215 return text; 216 } 217 218 219 220 /** 221 * Returns the text of the token. Equivalent to 222 * <code>getRootText()</code> when called directly. 223 */ 224 225 public String getText() 226 { 227 return text; 228 } 229 230 231 232 /** 233 * Not advisable, but if you need to adjust the token's text, this 234 * will do it. 235 */ 236 237 public void setText( String text ) 238 { 239 this.text = text; 240 } 241 242 243 244 /** 245 * Returns the starting line of the node. Returns -1 246 * if not known. 247 */ 248 249 public int getStartLine() 250 { 251 return startLine; 252 } 253 254 255 256 /** 257 * Returns the starting column of the node. Returns -1 258 * if not known. 259 */ 260 261 public int getStartColumn() 262 { 263 return startColumn; 264 } 265 266 267 268 269 //--------------------------------------------------------------------------- 270 // OPERATIONS 271 272 273 /** 274 * Creates a <code>Reduction</code> from this token. Returns self if the 275 * node is already a <code>Reduction</code>. 276 */ 277 278 public Reduction asReduction() 279 { 280 return new Reduction( this ); 281 } 282 283 284 285 /** 286 * Creates a <code>Reduction</code> from this token, adding the supplied 287 * node as the second element. 288 */ 289 290 public Reduction asReduction( CSTNode second ) 291 { 292 Reduction created = asReduction(); 293 created.add( second ); 294 return created; 295 } 296 297 298 299 /** 300 * Creates a <code>Reduction</code> from this token, adding the supplied 301 * nodes as the second and third element, respectively. 302 */ 303 304 public Reduction asReduction( CSTNode second, CSTNode third ) 305 { 306 Reduction created = asReduction( second ); 307 created.add( third ); 308 return created; 309 } 310 311 312 313 /** 314 * Creates a <code>Reduction</code> from this token, adding the supplied 315 * nodes as the second, third, and fourth element, respectively. 316 */ 317 318 public Reduction asReduction( CSTNode second, CSTNode third, CSTNode fourth ) 319 { 320 Reduction created = asReduction( second, third ); 321 created.add( fourth ); 322 return created; 323 } 324 325 326 327 328 //--------------------------------------------------------------------------- 329 // TOKEN FACTORIES 330 331 332 /** 333 * Creates a token that represents a keyword. Returns null if the 334 * specified text isn't a keyword. 335 */ 336 337 public static Token newKeyword( String text, int startLine, int startColumn ) 338 { 339 340 int type = Types.lookupKeyword( text ); 341 if( type != Types.UNKNOWN ) 342 { 343 return new Token( type, text, startLine, startColumn ); 344 } 345 346 return null; 347 348 } 349 350 351 /** 352 * Creates a token that represents a double-quoted string. 353 */ 354 355 public static Token newString( String text, int startLine, int startColumn ) 356 { 357 return new Token( Types.STRING, text, startLine, startColumn ); 358 } 359 360 361 /** 362 * Creates a token that represents an identifier. 363 */ 364 365 public static Token newIdentifier( String text, int startLine, int startColumn ) 366 { 367 return new Token( Types.IDENTIFIER, text, startLine, startColumn ); 368 } 369 370 371 /** 372 * Creates a token that represents an integer. 373 */ 374 375 public static Token newInteger( String text, int startLine, int startColumn ) 376 { 377 return new Token( Types.INTEGER_NUMBER, text, startLine, startColumn ); 378 } 379 380 381 /** 382 * Creates a token that represents a decimal number. 383 */ 384 385 public static Token newDecimal( String text, int startLine, int startColumn ) 386 { 387 return new Token( Types.DECIMAL_NUMBER, text, startLine, startColumn ); 388 } 389 390 391 /** 392 * Creates a token that represents a symbol, using a library for the text. 393 */ 394 395 public static Token newSymbol( int type, int startLine, int startColumn ) 396 { 397 return new Token( type, Types.getText(type), startLine, startColumn ); 398 } 399 400 401 /** 402 * Creates a token that represents a symbol, using a library for the type. 403 */ 404 405 public static Token newSymbol( String type, int startLine, int startColumn ) 406 { 407 return new Token( Types.lookupSymbol(type), type, startLine, startColumn ); 408 } 409 410 411 /** 412 * Creates a token with the specified meaning. 413 */ 414 415 public static Token newPlaceholder( int type ) 416 { 417 Token token = new Token( Types.UNKNOWN, "", -1, -1 ); 418 token.setMeaning( type ); 419 420 return token; 421 } 422 423 }