1// [The "BSD licence"]
2// Copyright (c) 2010 Alan Condit
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions
7// are met:
8// 1. Redistributions of source code must retain the above copyright
9//    notice, this list of conditions and the following disclaimer.
10// 2. Redistributions in binary form must reproduce the above copyright
11//    notice, this list of conditions and the following disclaimer in the
12//    documentation and/or other materials provided with the distribution.
13// 3. The name of the author may not be used to endorse or promote products
14//    derived from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27#import "ANTLRBufferedTokenStream.h"
28#import "ANTLRTokenSource.h"
29#import "ANTLRCommonTreeAdaptor.h"
30#import "ANTLRRuntimeException.h"
31
32extern NSInteger debug;
33
34@implementation ANTLRBufferedTokenStream
35
36@synthesize tokenSource;
37@synthesize tokens;
38@synthesize lastMarker;
39@synthesize index;
40@synthesize range;
41
42+ (ANTLRBufferedTokenStream *) newANTLRBufferedTokenStream
43{
44    return [[ANTLRBufferedTokenStream alloc] init];
45}
46
47+ (ANTLRBufferedTokenStream *) newANTLRBufferedTokenStreamWith:(id<ANTLRTokenSource>)aSource
48{
49    return [[ANTLRBufferedTokenStream alloc] initWithTokenSource:aSource];
50}
51
52- (ANTLRBufferedTokenStream *) init
53{
54	if ((self = [super init]) != nil)
55	{
56        tokenSource = nil;
57        tokens = [[AMutableArray arrayWithCapacity:1000] retain];
58        index = -1;
59        range = -1;
60	}
61	return self;
62}
63
64-(id) initWithTokenSource:(id<ANTLRTokenSource>)aSource
65{
66	if ((self = [super init]) != nil)
67	{
68        tokenSource = [aSource retain];
69        tokens = [[AMutableArray arrayWithCapacity:1000] retain];
70        index = -1;
71        range = -1;
72	}
73	return self;
74}
75
76- (id) copyWithZone:(NSZone *)aZone
77{
78    ANTLRBufferedTokenStream *copy;
79    
80    copy = [[[self class] allocWithZone:aZone] init];
81    copy.tokenSource = self.tokenSource;
82    if ( self.tokens )
83        copy.tokens = [tokens copyWithZone:aZone];
84    copy.lastMarker = self.lastMarker;
85    copy.index = self.index;
86    copy.range = self.range;
87    return copy;
88}
89
90- (void)dealloc
91{
92#ifdef DEBUG_DEALLOC
93    NSLog( @"called dealloc in ANTLRBufferedTokenStream" );
94#endif
95    if ( tokens ) [tokens release];
96    if ( tokenSource ) [tokenSource release];
97	[super dealloc];
98}
99
100- (NSUInteger)line
101{
102    return ((ANTLRCommonToken *)[tokens objectAtIndex:index]).line;
103}
104
105- (NSUInteger)charPositionInLine
106{
107    return ((ANTLRCommonToken *)[tokens objectAtIndex:index]).charPositionInLine;
108}
109
110- (id<ANTLRTokenSource>) getTokenSource
111{
112    return tokenSource;
113}
114
115- (NSInteger) getRange
116{
117    return range;
118}
119
120- (void) setRange:(NSInteger)anInt
121{
122    range = anInt;
123}
124
125- (NSInteger) mark
126{
127    if ( index == -1 ) {
128        [self setup];
129//        [self fill];
130    }
131    lastMarker = self.index;
132    return lastMarker;
133}
134
135- (void) release:(NSInteger) marker
136{
137    // no resources to release
138}
139
140- (void) rewind:(NSInteger) marker
141{
142    [self seek:marker];
143}
144
145- (void) rewind
146{
147    [self seek:lastMarker];
148}
149
150- (void) reset
151{
152    index = 0;
153    lastMarker = 0;
154}
155
156- (void) seek:(NSInteger) anIndex
157{
158    index = anIndex;
159}
160
161- (NSInteger) size
162{
163    return [tokens count];
164}
165
166/** Move the input pointer to the next incoming token.  The stream
167 *  must become active with LT(1) available.  consume() simply
168 *  moves the input pointer so that LT(1) points at the next
169 *  input symbol. Consume at least one token.
170 *
171 *  Walk past any token not on the channel the parser is listening to.
172 */
173- (void) consume
174{
175    if ( index == -1 ) {
176        [self setup];
177//        [self fill];
178    }
179    index++;
180    [self sync:index];
181}
182
183/** Make sure index i in tokens has a token. */
184- (void) sync:(NSInteger) i
185{
186    // how many more elements we need?
187    NSInteger n = (i - [tokens count]) + 1;
188    if (debug > 1) NSLog(@"[self sync:%d] needs %d\n", i, n);
189    if ( n > 0 )
190        [self fetch:n];
191}
192
193/** add n elements to buffer */
194- (void) fetch:(NSInteger)n
195{
196    for (NSInteger i=1; i <= n; i++) {
197        id<ANTLRToken> t = [tokenSource nextToken];
198        [t setTokenIndex:[tokens count]];
199        if (debug > 1) NSLog(@"adding %@ at index %d\n", [t text], [tokens count]);
200        [tokens addObject:t];
201        if ( t.type == ANTLRTokenTypeEOF )
202            break;
203    }
204}
205
206- (id<ANTLRToken>) getToken:(NSInteger) i
207{
208    if ( i < 0 || i >= [tokens count] ) {
209        @throw [ANTLRNoSuchElementException newException:[NSString stringWithFormat:@"token index %d out of range 0..%d", i, [tokens count]-1]];
210    }
211    return [tokens objectAtIndex:i];
212}
213
214/** Get all tokens from start..stop inclusively */
215- (AMutableArray *)getFrom:(NSInteger)startIndex To:(NSInteger)stopIndex
216{
217    if ( startIndex < 0 || stopIndex < 0 )
218        return nil;
219    if ( index == -1 ) {
220        [self setup];
221//        [self fill];
222    }
223    AMutableArray *subset = [AMutableArray arrayWithCapacity:5];
224    if ( stopIndex >= [tokens count] )
225        stopIndex = [tokens count]-1;
226    for (NSInteger i = startIndex; i <= stopIndex; i++) {
227        id<ANTLRToken>t = [tokens objectAtIndex:i];
228        if ( t.type == ANTLRTokenTypeEOF )
229            break;
230        [subset addObject:t];
231    }
232    return subset;
233}
234
235- (NSInteger) LA:(NSInteger)i
236{
237    return [[self LT:i] type];
238}
239
240- (id<ANTLRToken>) LB:(NSInteger)k
241{
242    if ( (index - k) < 0 )
243        return nil;
244    return [tokens objectAtIndex:(index-k)];
245}
246
247- (id<ANTLRToken>) LT:(NSInteger)k
248{
249    if ( index == -1 ) {
250        [self setup];
251//        [self fill];
252    }
253    if ( k == 0 )
254        return nil;
255    if ( k < 0 )
256        return [self LB:-k];
257    
258    NSInteger i = index + k - 1;
259    [self sync:i];
260    if ( i >= [tokens count] ) { // return EOF token
261                                // EOF must be last token
262        return [tokens objectAtIndex:([tokens count]-1)];
263    }
264    if ( i > range )
265        range = i; 		
266    return [tokens objectAtIndex:i];
267}
268
269- (void) setup
270{
271    [self sync:0];
272    index = 0;
273}
274
275/** Reset this token stream by setting its token source. */
276- (void) setTokenSource:(id<ANTLRTokenSource>) aTokenSource
277{
278    tokenSource = aTokenSource;
279    if ( [tokens count] )
280        [tokens removeAllObjects];
281    index = -1;
282}
283
284- (AMutableArray *)getTokens
285{
286    return tokens;
287}
288
289- (AMutableArray *)getTokensFrom:(NSInteger) startIndex To:(NSInteger) stopIndex
290{
291    return [self getTokensFrom:startIndex To:stopIndex With:(ANTLRBitSet *)nil];
292}
293
294/** Given a start and stop index, return a List of all tokens in
295 *  the token type BitSet.  Return null if no tokens were found.  This
296 *  method looks at both on and off channel tokens.
297 */
298- (AMutableArray *)getTokensFrom:(NSInteger)startIndex To:(NSInteger)stopIndex With:(ANTLRBitSet *)types
299{
300    if ( index == -1 ) {
301        [self setup];
302//        [self fill];
303    }
304    if ( stopIndex >= [tokens count] )
305        stopIndex = [tokens count]-1;
306    if ( startIndex < 0 )
307        startIndex = 0;
308    if ( startIndex > stopIndex )
309        return nil;
310    
311    // list = tokens[start:stop]:{Token t, t.getType() in types}
312    AMutableArray *filteredTokens = [AMutableArray arrayWithCapacity:5];
313    for (NSInteger i = startIndex; i <= stopIndex; i++) {
314        id<ANTLRToken>t = [tokens objectAtIndex:i];
315        if ( types == nil || [types member:t.type] ) {
316            [filteredTokens addObject:t];
317        }
318    }
319    if ( [filteredTokens count] == 0 ) {
320        filteredTokens = nil;
321    }
322    return filteredTokens;
323}
324
325- (AMutableArray *)getTokensFrom:(NSInteger)startIndex To:(NSInteger)stopIndex WithType:(NSInteger)ttype
326{
327    return [self getTokensFrom:startIndex To:stopIndex With:[ANTLRBitSet of:ttype]];
328}
329
330- (AMutableArray *)getTokensFrom:(NSInteger)startIndex To:(NSInteger)stopIndex WithList:(AMutableArray *)types
331{
332    return [self getTokensFrom:startIndex To:stopIndex With:[ANTLRBitSet newANTLRBitSetWithArray:types]];
333}
334            
335- (NSString *)getSourceName
336{
337    return [tokenSource getSourceName];
338}
339
340/** Grab *all* tokens from stream and return string */
341- (NSString *) toString
342{
343    if ( index == -1 ) {
344        [self setup];
345    }
346    [self fill];
347    return [self toStringFromStart:0 ToEnd:[tokens count]-1];
348}
349
350- (NSString *) toStringFromStart:(NSInteger)startIdx ToEnd:(NSInteger)stopIdx
351{
352    if ( startIdx < 0 || stopIdx < 0 )
353        return nil;
354    if ( index == -1 ) {
355        [self setup];
356    }
357    if ( stopIdx >= [tokens count] )
358        stopIdx = [tokens count]-1;
359    NSMutableString *buf = [NSMutableString stringWithCapacity:5];
360    for (NSInteger i = startIdx; i <= stopIdx; i++) {
361        id<ANTLRToken>t = [tokens objectAtIndex:i];
362        if ( t.type == ANTLRTokenTypeEOF )
363            break;
364        [buf appendString:[t text]];
365    }
366    return buf;
367}
368
369- (NSString *) toStringFromToken:(id<ANTLRToken>)startToken ToToken:(id<ANTLRToken>)stopToken
370{
371    if ( startToken != nil && stopToken != nil ) {
372        return [self toStringFromStart:[startToken getTokenIndex] ToEnd:[stopToken getTokenIndex]];
373    }
374    return nil;
375}
376
377/** Get all tokens from lexer until EOF */
378- (void) fill
379{
380    if ( index == -1 ) [self setup];
381    if ( [((ANTLRCommonToken *)[tokens objectAtIndex:index]) type] == ANTLRTokenTypeEOF )
382        return;
383    
384    NSInteger i = index+1;
385    [self sync:i];
386    while ( [((ANTLRCommonToken *)[tokens objectAtIndex:i]) type] != ANTLRTokenTypeEOF ) {
387        i++;
388        [self sync:i];
389    }
390}
391
392@end
393