1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 package org.codehaus.groovy.syntax;
48
49 import org.codehaus.groovy.GroovyBugError;
50
51
52 /***
53 * A <code>CSTNode</code> produced by the <code>Lexer</code>.
54 *
55 * @see Lexer
56 * @see Parser
57 * @see Token
58 * @see Reduction
59 * @see Types
60 *
61 * @author <a href="mailto:bob@werken.com">bob mcwhirter</a>
62 * @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
63 *
64 * @version $Id: Token.java,v 1.29 2005/04/12 15:04:59 jstrachan Exp $
65 */
66
67 public class Token extends CSTNode
68 {
69 public static final Token NULL = new Token();
70 public static final Token EOF = new Token( Types.EOF, "", -1, -1 );
71
72
73
74
75
76 private int type = Types.UNKNOWN;
77 private int meaning = Types.UNKNOWN;
78
79 private String text = "";
80 private int startLine = -1;
81 private int startColumn = -1;
82
83
84 /***
85 * Initializes the Token with the specified information.
86 */
87
88 public Token( int type, String text, int startLine, int startColumn )
89 {
90 this.type = type;
91 this.meaning = type;
92 this.text = text;
93 this.startLine = startLine;
94 this.startColumn = startColumn;
95 }
96
97
98 /***
99 * 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
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
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
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
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 }