View Javadoc

1   /*
2    $Id: Token.java,v 1.28 2004/04/01 06:21:53 cpoirier Exp $
3   
4    Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
5   
6    Redistribution and use of this software and associated documentation
7    ("Software"), with or without modification, are permitted provided
8    that the following conditions are met:
9   
10   1. Redistributions of source code must retain copyright
11      statements and notices.  Redistributions must also contain a
12      copy of this document.
13  
14   2. Redistributions in binary form must reproduce the
15      above copyright notice, this list of conditions and the
16      following disclaimer in the documentation and/or other
17      materials provided with the distribution.
18  
19   3. The name "groovy" must not be used to endorse or promote
20      products derived from this Software without prior written
21      permission of The Codehaus.  For written permission,
22      please contact info@codehaus.org.
23  
24   4. Products derived from this Software may not be called "groovy"
25      nor may "groovy" appear in their names without prior written
26      permission of The Codehaus. "groovy" is a registered
27      trademark of The Codehaus.
28  
29   5. Due credit should be given to The Codehaus -
30      http://groovy.codehaus.org/
31  
32   THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
33   ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
34   NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
35   FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
36   THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
37   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
43   OF THE POSSIBILITY OF SUCH DAMAGE.
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    // TOKEN INITIALIZATION AND SUCH
76  
77      private int type        = Types.UNKNOWN;  // the actual type identified by the lexer
78      private int meaning     = Types.UNKNOWN;  // an interpretation applied to the token after the fact
79  
80      private String     text = "";             // the text of the token
81      private int   startLine = -1;             // the source line on which the token begins
82      private int startColumn = -1;             // the source column on which the token begins
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   // NODE IDENTIFICATION AND MEANING
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   // MEMBER ACCESS
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   // OPERATIONS
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   // TOKEN FACTORIES
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 }