001    /*
002     $Id: Token.java,v 1.29 2005/04/12 15:04:59 jstrachan Exp $
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 Lexer
056     *  @see Parser
057     *  @see Token
058     *  @see Reduction
059     *  @see Types
060     *
061     *  @author <a href="mailto:bob@werken.com">bob mcwhirter</a>
062     *  @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
063     *
064     *  @version $Id: Token.java,v 1.29 2005/04/12 15:04:59 jstrachan Exp $
065     */
066    
067    public class Token extends CSTNode
068    {
069        public static final Token NULL = new Token();
070        public static final Token EOF  = new Token( Types.EOF, "", -1, -1 );
071    
072    
073      //---------------------------------------------------------------------------
074      // TOKEN INITIALIZATION AND SUCH
075    
076        private int type        = Types.UNKNOWN;  // the actual type identified by the lexer
077        private int meaning     = Types.UNKNOWN;  // an interpretation applied to the token after the fact
078    
079        private String     text = "";             // the text of the token
080        private int   startLine = -1;             // the source line on which the token begins
081        private int startColumn = -1;             // the source column on which the token begins
082    
083    
084       /**
085        *  Initializes the Token with the specified information.
086        */
087    
088        public Token( int type, String text, int startLine, int startColumn )
089        {
090            this.type        = type;
091            this.meaning     = type;
092            this.text        = text;
093            this.startLine   = startLine;
094            this.startColumn = startColumn;
095        }
096    
097    
098       /**
099        *  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    }