View Javadoc

1   /*
2    $Id: Token.java,v 1.29 2005/04/12 15:04:59 jstrachan 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  
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    // TOKEN INITIALIZATION AND SUCH
75  
76      private int type        = Types.UNKNOWN;  // the actual type identified by the lexer
77      private int meaning     = Types.UNKNOWN;  // an interpretation applied to the token after the fact
78  
79      private String     text = "";             // the text of the token
80      private int   startLine = -1;             // the source line on which the token begins
81      private int startColumn = -1;             // the source column on which the token begins
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   // 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 }