KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > groovy > syntax > AbstractTokenStream


1 package org.codehaus.groovy.syntax;
2
3 import org.codehaus.groovy.GroovyBugError;
4
5
6 /**
7  * Provides the common code for <code>{@link TokenStream}</code> implementations.
8  */

9
10 public abstract class AbstractTokenStream
11     implements TokenStream
12 {
13     private Token[] buf; // A circular buffer of tokens
14
private int first; // la(1) points to this offset into buf
15
private int avail; // the number of ahead tokens in buf
16

17     private int checkpoint_first; // last checkpoint() copy of first
18
private int checkpoint_avail; // last checkpoint() copy of avail
19

20     private String JavaDoc sourceLocator; // A descriptor of the source of the stream
21

22
23    /**
24     * Default constructor.
25     */

26
27     public AbstractTokenStream()
28     {
29         this( "<unknown>" );
30     }
31
32
33    /**
34     * Initializes the stream with information about the source.
35     */

36
37     public AbstractTokenStream(String JavaDoc sourceLocator)
38     {
39         this.buf = new Token[8 * 1024];
40         this.first = -1;
41         this.avail = 0;
42         this.sourceLocator = sourceLocator;
43     }
44
45
46    /**
47     * Returns a description of the source (typically a file name).
48     */

49
50     public String JavaDoc getSourceLocator()
51     {
52         return this.sourceLocator;
53     }
54
55
56    /**
57     * Implemented by concrete subtypes, provides access to the next
58     * token in the underlying stream.
59     */

60
61     protected abstract Token nextToken()
62         throws ReadException, SyntaxException;
63
64
65    /**
66     * Returns the next token in the stream without consuming it.
67     */

68
69     public Token la()
70         throws ReadException, SyntaxException
71     {
72         return la( 1 );
73     }
74
75
76    /**
77     * Returns the <code>k</code>th token in the stream without consuming
78     * it (or any other unconsumed tokens).
79     */

80
81     public Token la(int k)
82         throws ReadException, SyntaxException
83     {
84         if ( k > buf.length )
85         {
86             throw new GroovyBugError( "Lookahead [" + k + "] is larger than lookahead buffer [" + buf.length + "]" );
87         }
88
89
90         //
91
// If necessary, read more tokens from the underlying stream.
92

93         if ( k > this.avail )
94         {
95             int numToPopulate = k - this.avail;
96
97             for ( int i = 0 ; i < numToPopulate ; ++i )
98             {
99                 if ( this.first < 0 )
100                 {
101                     this.first = 0;
102                 }
103                 int pop = ( ( this.first + this.avail ) % this.buf.length );
104                 this.buf[ pop ] = nextToken();
105                 ++this.avail;
106                 ++this.checkpoint_avail;
107             }
108         }
109
110
111         //
112
// Return the requested token.
113

114         int pos = ( ( k + this.first - 1 ) % this.buf.length );
115
116         return this.buf[ pos ];
117     }
118
119
120    /**
121     * Removes and returns the first token in the stream, provided it
122     * matches the specified type.
123     */

124
125     public Token consume(int type)
126         throws ReadException, SyntaxException
127     {
128         Token token = la();
129
130         if( token == null )
131         {
132             return null;
133         }
134
135         if( !token.isA(type) )
136         {
137             throw new TokenMismatchException( token, type );
138         }
139
140         ++this.first;
141         --this.avail;
142
143         this.first %= this.buf.length;
144
145         return token;
146     }
147
148
149
150    /**
151     * Removes and returns the first token in the stream, provided it
152     * isn't the EOF.
153     */

154
155     public Token consume() throws ReadException, SyntaxException
156     {
157         return consume( Types.NOT_EOF );
158     }
159
160
161
162    /**
163     * Saves the look-ahead state for <code>restore()</code>ing later.
164     */

165
166     public void checkpoint() {
167         checkpoint_first = first;
168         checkpoint_avail = avail;
169     }
170
171
172    /**
173     * Restores the look-ahead state saved by <code>checkpoint()</code>.
174     */

175
176     public void restore() {
177         first = checkpoint_first;
178         avail = checkpoint_avail;
179     }
180
181
182     /**
183      * Returns true if the stream is out of tokens.
184      */

185
186     public boolean atEnd( boolean ignoringWhitespace ) {
187
188         try {
189             int offset = 1;
190
191             if( ignoringWhitespace ) {
192                 try {
193                     while( la(offset).isA(Types.NEWLINE) ) {
194                         offset++;
195                     }
196                 }
197                 catch( Exception JavaDoc e ) {}
198             }
199
200             if( la(offset) == null ) {
201                 return true;
202             }
203         }
204         catch( Exception JavaDoc e ) {}
205
206         return false;
207     }
208
209
210     /**
211      * A synonym for <code>atEnd(true)</code>.
212      */

213
214     public boolean atEnd() {
215         return atEnd(true);
216     }
217
218 }
219
Popular Tags