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