001 /*
002 $Id: Token.java,v 1.29 2005/04/12 15:04:59 jstrachan Exp $
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 Lexer
056 * @see Parser
057 * @see Token
058 * @see Reduction
059 * @see Types
060 *
061 * @author <a href="mailto:bob@werken.com">bob mcwhirter</a>
062 * @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
063 *
064 * @version $Id: Token.java,v 1.29 2005/04/12 15:04:59 jstrachan Exp $
065 */
066
067 public class Token extends CSTNode
068 {
069 public static final Token NULL = new Token();
070 public static final Token EOF = new Token( Types.EOF, "", -1, -1 );
071
072
073 //---------------------------------------------------------------------------
074 // TOKEN INITIALIZATION AND SUCH
075
076 private int type = Types.UNKNOWN; // the actual type identified by the lexer
077 private int meaning = Types.UNKNOWN; // an interpretation applied to the token after the fact
078
079 private String text = ""; // the text of the token
080 private int startLine = -1; // the source line on which the token begins
081 private int startColumn = -1; // the source column on which the token begins
082
083
084 /**
085 * Initializes the Token with the specified information.
086 */
087
088 public Token( int type, String text, int startLine, int startColumn )
089 {
090 this.type = type;
091 this.meaning = type;
092 this.text = text;
093 this.startLine = startLine;
094 this.startColumn = startColumn;
095 }
096
097
098 /**
099 * Initializes the NULL Token.
100 */
101
102 private Token() { }
103
104
105
106 /**
107 * Returns a copy of this Token.
108 */
109
110 public Token dup()
111 {
112 Token token = new Token( this.type, this.text, this.startLine, this.startColumn );
113 token.setMeaning( this.meaning );
114
115 return token;
116 }
117
118
119
120
121 //---------------------------------------------------------------------------
122 // NODE IDENTIFICATION AND MEANING
123
124
125 /**
126 * Returns the meaning of this node. If the node isEmpty(), returns
127 * the type of Token.NULL.
128 */
129
130 public int getMeaning()
131 {
132 return meaning;
133 }
134
135
136
137 /**
138 * Sets the meaning for this node (and it's root Token). Not
139 * valid if the node isEmpty(). Returns this token, for
140 * convenience.
141 */
142
143 public CSTNode setMeaning( int meaning )
144 {
145 this.meaning = meaning;
146 return this;
147 }
148
149
150
151 /**
152 * Returns the actual type of the node. If the node isEmpty(), returns
153 * the type of Token.NULL.
154 */
155
156 public int getType()
157 {
158 return type;
159 }
160
161
162
163
164 //---------------------------------------------------------------------------
165 // MEMBER ACCESS
166
167
168 /**
169 * Returns the number of elements in the node (including root).
170 */
171
172 public int size()
173 {
174 return 1;
175 }
176
177
178
179 /**
180 * Returns the specified element, or null.
181 */
182
183 public CSTNode get( int index )
184 {
185 if( index > 0 )
186 {
187 throw new GroovyBugError( "attempt to access Token element other than root" );
188 }
189
190 return this;
191 }
192
193
194
195 /**
196 * Returns the root of the node. By convention, all nodes have
197 * a Token as the first element (or root), which indicates the type
198 * of the node. May return null if the node <code>isEmpty()</code>.
199 */
200
201 public Token getRoot()
202 {
203 return this;
204 }
205
206
207
208 /**
209 * Returns the text of the root node. Uses <code>getRoot(true)</code>
210 * to get the root, so you will only receive null in return if the
211 * root token returns it.
212 */
213
214 public String getRootText()
215 {
216 return text;
217 }
218
219
220
221 /**
222 * Returns the text of the token. Equivalent to
223 * <code>getRootText()</code> when called directly.
224 */
225
226 public String getText()
227 {
228 return text;
229 }
230
231
232
233 /**
234 * Not advisable, but if you need to adjust the token's text, this
235 * will do it.
236 */
237
238 public void setText( String text )
239 {
240 this.text = text;
241 }
242
243
244
245 /**
246 * Returns the starting line of the node. Returns -1
247 * if not known.
248 */
249
250 public int getStartLine()
251 {
252 return startLine;
253 }
254
255
256
257 /**
258 * Returns the starting column of the node. Returns -1
259 * if not known.
260 */
261
262 public int getStartColumn()
263 {
264 return startColumn;
265 }
266
267
268
269
270 //---------------------------------------------------------------------------
271 // OPERATIONS
272
273
274 /**
275 * Creates a <code>Reduction</code> from this token. Returns self if the
276 * node is already a <code>Reduction</code>.
277 */
278
279 public Reduction asReduction()
280 {
281 return new Reduction( this );
282 }
283
284
285
286 /**
287 * Creates a <code>Reduction</code> from this token, adding the supplied
288 * node as the second element.
289 */
290
291 public Reduction asReduction( CSTNode second )
292 {
293 Reduction created = asReduction();
294 created.add( second );
295 return created;
296 }
297
298
299
300 /**
301 * Creates a <code>Reduction</code> from this token, adding the supplied
302 * nodes as the second and third element, respectively.
303 */
304
305 public Reduction asReduction( CSTNode second, CSTNode third )
306 {
307 Reduction created = asReduction( second );
308 created.add( third );
309 return created;
310 }
311
312
313
314 /**
315 * Creates a <code>Reduction</code> from this token, adding the supplied
316 * nodes as the second, third, and fourth element, respectively.
317 */
318
319 public Reduction asReduction( CSTNode second, CSTNode third, CSTNode fourth )
320 {
321 Reduction created = asReduction( second, third );
322 created.add( fourth );
323 return created;
324 }
325
326
327
328
329 //---------------------------------------------------------------------------
330 // TOKEN FACTORIES
331
332
333 /**
334 * Creates a token that represents a keyword. Returns null if the
335 * specified text isn't a keyword.
336 */
337
338 public static Token newKeyword( String text, int startLine, int startColumn )
339 {
340
341 int type = Types.lookupKeyword( text );
342 if( type != Types.UNKNOWN )
343 {
344 return new Token( type, text, startLine, startColumn );
345 }
346
347 return null;
348
349 }
350
351
352 /**
353 * Creates a token that represents a double-quoted string.
354 */
355
356 public static Token newString( String text, int startLine, int startColumn )
357 {
358 return new Token( Types.STRING, text, startLine, startColumn );
359 }
360
361
362 /**
363 * Creates a token that represents an identifier.
364 */
365
366 public static Token newIdentifier( String text, int startLine, int startColumn )
367 {
368 return new Token( Types.IDENTIFIER, text, startLine, startColumn );
369 }
370
371
372 /**
373 * Creates a token that represents an integer.
374 */
375
376 public static Token newInteger( String text, int startLine, int startColumn )
377 {
378 return new Token( Types.INTEGER_NUMBER, text, startLine, startColumn );
379 }
380
381
382 /**
383 * Creates a token that represents a decimal number.
384 */
385
386 public static Token newDecimal( String text, int startLine, int startColumn )
387 {
388 return new Token( Types.DECIMAL_NUMBER, text, startLine, startColumn );
389 }
390
391
392 /**
393 * Creates a token that represents a symbol, using a library for the text.
394 */
395
396 public static Token newSymbol( int type, int startLine, int startColumn )
397 {
398 return new Token( type, Types.getText(type), startLine, startColumn );
399 }
400
401
402 /**
403 * Creates a token that represents a symbol, using a library for the type.
404 */
405
406 public static Token newSymbol( String type, int startLine, int startColumn )
407 {
408 return new Token( Types.lookupSymbol(type), type, startLine, startColumn );
409 }
410
411
412 /**
413 * Creates a token with the specified meaning.
414 */
415
416 public static Token newPlaceholder( int type )
417 {
418 Token token = new Token( Types.UNKNOWN, "", -1, -1 );
419 token.setMeaning( type );
420
421 return token;
422 }
423
424 }