KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > groovy > syntax > lexer > GStringLexer


1 package org.codehaus.groovy.syntax.lexer;
2
3 //{{{ imports
4
import org.codehaus.groovy.syntax.ReadException;
5 import org.codehaus.groovy.syntax.Types;
6 import org.codehaus.groovy.syntax.Token;
7 //}}}
8

9 /**
10  * A lexer for GStrings, usually run on a LexerFilter base.
11  *
12  * @author Chris Poirier
13  */

14
15 public class GStringLexer extends LexerBase
16 {
17
18     protected boolean sentStartToken = false;
19     protected boolean sentEndToken = false;
20
21     protected StringBuffer JavaDoc fullText = new StringBuffer JavaDoc();
22     protected int fullTextStartLine = 0;
23     protected int fullTextStartColumn = 0;
24
25     protected GroovyExpressionLexer child = null;
26     protected boolean inExpression = false;
27
28
29    /**
30     * Finds and returns (consuming) the next token from the underlying stream.
31     * Returns null when out of tokens.
32     */

33
34     protected Token undelegatedNextToken() throws ReadException, LexerException
35     {
36         // System.out.println( "" + this + "undelegatedNextToken()" );
37
Token token = null;
38
39
40         //
41
// Handle bracketing tokens and EOS
42

43         if( !sentStartToken )
44         {
45             mark();
46             fullTextStartLine = getStartLine();
47             fullTextStartColumn = getStartColumn();
48             sentStartToken = true;
49
50             // System.out.println( "" + this + "returning GSTRING_START" );
51
return symbol( Types.GSTRING_START );
52         }
53         else if( la(1) == CharStream.EOS )
54         {
55             if( !sentEndToken )
56             {
57                 sentEndToken = true;
58                 token = Token.newSymbol( Types.GSTRING_END, fullTextStartLine, fullTextStartColumn );
59                 token.setText( fullText.toString() );
60             }
61
62             // System.out.println( "" + this + "returning " + token );
63
return token;
64         }
65
66
67         //
68
// If we get this far, we are no longer delegated. If
69
// we just processed an expression, the next character
70
// had better be a '}'...
71

72         if( inExpression && la(1) != '}' )
73         {
74             mark();
75             unexpected( la(1), 0 );
76         }
77
78
79         //
80
// Otherwise, it's a lex...
81

82         mark();
83         StringBuffer JavaDoc segment = new StringBuffer JavaDoc();
84
85         char c;
86         MAIN_LOOP: while( true )
87         {
88             c = la(1);
89
90             ROOT_SWITCH: switch( c )
91             {
92                 case CharStream.EOS:
93                 {
94                     break MAIN_LOOP;
95                 }
96
97                 case '\r':
98                 case '\n':
99                 {
100                     readEOL( segment );
101                     break ROOT_SWITCH;
102                 }
103
104                 case '\\':
105                 {
106                     ESCAPE_SWITCH: switch( la(2) )
107                     {
108                         case '\\':
109                         case '$':
110                         {
111                             consume();
112                             segment.append( consume() );
113                             break ESCAPE_SWITCH;
114                         }
115
116                         default:
117                         {
118                             segment.append( consume() );
119                             break ESCAPE_SWITCH;
120                         }
121                     }
122
123                     break ROOT_SWITCH;
124                 }
125
126                 case '$':
127                 {
128                     if( la(2) == '{' )
129                     {
130                         if( segment.length() == 0 )
131                         {
132                             sourceDelimiting( false ); // ensures ${"..."} works
133

134                             mark();
135                             consume();
136                             consume();
137
138                             token = symbol( Types.GSTRING_EXPRESSION_START );
139                             inExpression = true;
140
141                             if( child == null )
142                             {
143                                 child = new GroovyExpressionLexer();
144                             }
145                             else
146                             {
147                                 child.reset();
148                             }
149
150                             delegate( child );
151
152                             break MAIN_LOOP;
153                         }
154                         else
155                         {
156                             break MAIN_LOOP;
157                         }
158                     }
159                     else
160                     {
161                         segment.append( consume() );
162                     }
163
164                     break ROOT_SWITCH;
165                 }
166
167                 case '}':
168                 {
169                     if( inExpression )
170                     {
171                         mark();
172                         consume();
173                         token = symbol( Types.GSTRING_EXPRESSION_END );
174
175                         inExpression = false;
176
177                         break MAIN_LOOP;
178                     }
179                     else
180                     {
181                         segment.append( consume() );
182                         break ROOT_SWITCH;
183                     }
184                 }
185
186                 default:
187                 {
188                     segment.append( consume() );
189                     break ROOT_SWITCH;
190                 }
191             }
192         }
193
194
195         if( token != null )
196         {
197             // System.out.println( "" + this + "returning " + token );
198
return token;
199         }
200         else
201         {
202             // System.out.println( "" + this + "returning string of " + segment );
203
return Token.newString( segment.toString(), getStartLine(), getStartColumn() );
204         }
205
206     }
207
208
209
210
211   //---------------------------------------------------------------------------
212
// DELEGATION
213

214
215    /**
216     * Coordinates with our source about delimiting. When
217     * entering or processing sub-expressions, source delimiting
218     * should be off.
219     */

220
221     protected void sourceDelimiting( boolean delimit )
222     {
223         if( source instanceof Delimiter )
224         {
225             ((Delimiter)source).delimit( delimit );
226         }
227     }
228
229
230
231    /**
232     * Delegates our duties to another Lexer.
233     */

234
235     public void delegate( Lexer to )
236     {
237         this.delegate = to;
238         sourceDelimiting( false );
239         to.setSource( this );
240     }
241
242
243
244    /**
245     * Retakes responsibility for our duties.
246     */

247
248     public void undelegate()
249     {
250         if( delegate != null )
251         {
252             delegate.unsetSource( );
253             delegate = null;
254             sourceDelimiting( true );
255         }
256     }
257
258
259
260    /**
261     * Sets the source lexer.
262     */

263
264     public void setSource( Lexer source )
265     {
266         super.setSource( source );
267
268         sentStartToken = false;
269         sentEndToken = false;
270
271         fullTextStartLine = getStartLine();
272         fullTextStartColumn = getStartColumn();
273         fullText = new StringBuffer JavaDoc();
274
275         inExpression = false;
276     }
277
278
279
280    /**
281     * Unsets the source lexer.
282     */

283
284     public void unsetSource()
285     {
286         super.unsetSource();
287
288         sentStartToken = false;
289         sentEndToken = false;
290         fullText = null;
291         inExpression = false;
292     }
293
294
295
296
297   //---------------------------------------------------------------------------
298
// STREAM ROUTINES
299

300
301    /**
302     * Eats a character from the input stream.
303     */

304
305     public char consume() throws LexerException, ReadException
306     {
307         char c = super.consume();
308
309         if( c != CharStream.EOS )
310         {
311             fullText.append(c);
312         }
313
314         return c;
315     }
316
317
318 }
319
320
Popular Tags