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 }