KickJava   Java API By Example, From Geeks To Geeks.

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


1 package org.codehaus.groovy.syntax.lexer;
2
3 import org.codehaus.groovy.syntax.ReadException;
4 import org.codehaus.groovy.syntax.Token;
5
6 /**
7  * Lexes Groovy, counting braces. Considers itself at end of stream
8  * when the } count exceeds the { count.
9  *
10  * @author Chris Poirier
11  */

12
13 public class GroovyExpressionLexer extends GroovyLexerBase implements Delimiter
14 {
15
16     protected boolean delimited = true; // When true, the lexer can do its delimiting
17
protected boolean finished = false; // Set when we reach the delimiter
18
protected int balance = 0; // The current number of unmatched open-braces
19

20
21    /**
22     * Finds and returns (and consumes) the next token from the underlying stream.
23     * Returns null when out of tokens. We let the GroovyLexerBase version deal
24     * with delegation stuff.
25     */

26
27     public Token nextToken() throws ReadException, LexerException
28     {
29         if( finished )
30         {
31             return null;
32         }
33         else
34         {
35             return super.nextToken();
36         }
37
38     }
39
40
41
42   //---------------------------------------------------------------------------
43
// DELIMITER ROUTINES
44

45
46    /**
47     * Turns delimiting on or off. This should affect <code>la()</code>
48     * and <code>consume()</code>. However, once the delimiter has been
49     * reached, this routine should have no effect.
50     */

51
52     public void delimit( boolean delimited )
53     {
54         this.delimited = delimited;
55     }
56
57
58
59    /**
60     * Returns true if the lexer is applying its delimiter policy.
61     */

62
63     public boolean isDelimited()
64     {
65         return this.delimited;
66     }
67
68
69
70    /**
71     * Returns true if the lexer stream is dry.
72     */

73
74     public boolean isFinished()
75     {
76         return finished;
77     }
78
79
80
81    /**
82     * Restarts the lexer stream after a <code>finish()</code>
83     * and some intevening act (like a new source).
84     */

85
86     protected void restart()
87     {
88         finished = false;
89     }
90
91
92
93    /**
94     * Stops the lexer stream.
95     */

96
97     protected void finish()
98     {
99         finished = true;
100     }
101
102
103
104
105   //---------------------------------------------------------------------------
106
// DELEGATION
107

108
109    /**
110     * Delegates our duties to another Lexer.
111     */

112
113     public void delegate( Lexer to )
114     {
115         this.delegate = to;
116         delimit( false );
117         to.setSource( this );
118     }
119
120
121
122    /**
123     * Retakes responsibility for our duties.
124     */

125
126     public void undelegate()
127     {
128         if( delegate != null )
129         {
130             delegate.unsetSource( );
131             delegate = null;
132             delimit( true );
133         }
134     }
135
136
137
138   //---------------------------------------------------------------------------
139
// STREAM ROUTINES
140

141
142
143    /**
144     * Returns the next <code>k</code>th character, without consuming any.
145     */

146
147     public char la(int k) throws LexerException, ReadException
148     {
149         if( source != null )
150         {
151             if( delimited )
152             {
153                 char c = ' ';
154                 int balance = this.balance;
155                 for( int i = 1; i <= k && balance >= 0; i++ )
156                 {
157                     c = source.la(k);
158                     switch( c )
159                     {
160                         case '{':
161                             balance++;
162                             break;
163                         case '}':
164                             balance--;
165                             break;
166                     }
167                 }
168
169                 if( balance >= 0 )
170                 {
171                     return c;
172                 }
173                 else
174                 {
175                     return CharStream.EOS;
176                 }
177
178             }
179             else
180             {
181                 return source.la(k);
182             }
183
184         }
185         else
186         {
187             return CharStream.EOS;
188         }
189     }
190
191
192
193    /**
194     * Eats a character from the input stream.
195     */

196
197     public char consume() throws LexerException, ReadException
198     {
199         if( source != null )
200         {
201             if( delimited )
202             {
203                 char c = source.la(1);
204                 switch( c )
205                 {
206                     case '{':
207                         balance++;
208                         break;
209                     case '}':
210                         balance--;
211                         break;
212                 }
213
214                 if( balance >= 0 )
215                 {
216                     return source.consume();
217                 }
218                 else
219                 {
220                     finish();
221                 }
222             }
223             else
224             {
225                 return source.consume();
226             }
227         }
228
229         return CharStream.EOS;
230     }
231
232 }
233
Popular Tags