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