You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
230 lines
4.6 KiB
230 lines
4.6 KiB
//
|
|
// LookaheadStream.m
|
|
// ANTLR
|
|
//
|
|
// Created by Ian Michell on 26/04/2010.
|
|
// [The "BSD licence"]
|
|
// Copyright (c) 2010 Ian Michell 2010 Alan Condit
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions
|
|
// are met:
|
|
// 1. Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// 2. Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
// 3. The name of the author may not be used to endorse or promote products
|
|
// derived from this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
#import "LookaheadStream.h"
|
|
#import "ANTLRError.h"
|
|
#import "RecognitionException.h"
|
|
#import "CommonToken.h"
|
|
#import "RuntimeException.h"
|
|
|
|
@implementation LookaheadStream
|
|
|
|
@synthesize eof;
|
|
@synthesize index;
|
|
@synthesize eofElementIndex;
|
|
@synthesize lastMarker;
|
|
@synthesize markDepth;
|
|
@synthesize prevElement;
|
|
|
|
-(id) init
|
|
{
|
|
self = [super init];
|
|
if ( self != nil ) {
|
|
eof = [[CommonToken eofToken] retain];
|
|
eofElementIndex = UNITIALIZED_EOF_ELEMENT_INDEX;
|
|
markDepth = 0;
|
|
index = 0;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
-(id) initWithEOF:(id)obj
|
|
{
|
|
if ((self = [super init]) != nil) {
|
|
self.eof = obj;
|
|
if ( self.eof ) [self.eof retain];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void) reset
|
|
{
|
|
[super reset];
|
|
index = 0;
|
|
p = 0;
|
|
prevElement = nil;
|
|
eofElementIndex = UNITIALIZED_EOF_ELEMENT_INDEX;
|
|
}
|
|
|
|
-(id) nextElement
|
|
{
|
|
// [self doesNotRecognizeSelector:_cmd];
|
|
return nil;
|
|
}
|
|
|
|
- (id) remove
|
|
{
|
|
id obj = [self objectAtIndex:0];
|
|
p++;
|
|
// have we hit end of buffer and not backtracking?
|
|
if ( p == [data count] && markDepth==0 ) {
|
|
// if so, it's an opportunity to start filling at index 0 again
|
|
[self clear]; // size goes to 0, but retains memory
|
|
}
|
|
[obj release];
|
|
return obj;
|
|
}
|
|
|
|
-(void) consume
|
|
{
|
|
[self sync:1];
|
|
prevElement = [self remove];
|
|
index++;
|
|
}
|
|
|
|
-(void) sync:(NSInteger) need
|
|
{
|
|
NSInteger n = (p + need - 1) - [data count] + 1;
|
|
if ( n > 0 ) {
|
|
[self fill:n];
|
|
}
|
|
}
|
|
|
|
-(void) fill:(NSInteger) n
|
|
{
|
|
id obj;
|
|
for (NSInteger i = 1; i <= n; i++) {
|
|
obj = [self nextElement];
|
|
if ( obj == eof ) {
|
|
[data addObject:self.eof];
|
|
eofElementIndex = [data count] - 1;
|
|
}
|
|
else {
|
|
[data addObject:obj];
|
|
}
|
|
}
|
|
}
|
|
|
|
-(NSUInteger) count
|
|
{
|
|
@throw [NSException exceptionWithName:@"UnsupportedOperationException" reason:@"Streams have no defined size" userInfo:nil];
|
|
}
|
|
|
|
-(id) LT:(NSInteger) k
|
|
{
|
|
if (k == 0) {
|
|
return nil;
|
|
}
|
|
if (k < 0) {
|
|
return [self LB:-k];
|
|
}
|
|
if ((p + k - 1) >= eofElementIndex) {
|
|
return self.eof;
|
|
}
|
|
[self sync:k];
|
|
return [self objectAtIndex:(k - 1)];
|
|
}
|
|
|
|
-(id) LB:(NSInteger) k
|
|
{
|
|
if (k == 1) {
|
|
return prevElement;
|
|
}
|
|
@throw [NoSuchElementException newException:@"can't look backwards more than one token in this stream"];
|
|
}
|
|
|
|
-(id) getCurrentSymbol
|
|
{
|
|
return [self LT:1];
|
|
}
|
|
|
|
-(NSInteger) mark
|
|
{
|
|
markDepth++;
|
|
lastMarker = p;
|
|
return lastMarker;
|
|
}
|
|
|
|
-(void) release:(NSInteger) marker
|
|
{
|
|
// no resources to release
|
|
}
|
|
|
|
-(void) rewind:(NSInteger) marker
|
|
{
|
|
markDepth--;
|
|
[self seek:marker];
|
|
// if (marker == 0) [self reset];
|
|
}
|
|
|
|
-(void) rewind
|
|
{
|
|
[self seek:lastMarker];
|
|
// if (lastMarker == 0) [self reset];
|
|
}
|
|
|
|
-(void) seek:(NSInteger) anIndex
|
|
{
|
|
p = anIndex;
|
|
}
|
|
|
|
- (id) getEof
|
|
{
|
|
return eof;
|
|
}
|
|
|
|
- (void) setEof:(id) anID
|
|
{
|
|
eof = anID;
|
|
}
|
|
|
|
- (NSInteger) getEofElementIndex
|
|
{
|
|
return eofElementIndex;
|
|
}
|
|
|
|
- (void) setEofElementIndex:(NSInteger) anInt
|
|
{
|
|
eofElementIndex = anInt;
|
|
}
|
|
|
|
- (NSInteger) getLastMarker
|
|
{
|
|
return lastMarker;
|
|
}
|
|
|
|
- (void) setLastMarker:(NSInteger) anInt
|
|
{
|
|
lastMarker = anInt;
|
|
}
|
|
|
|
- (NSInteger) getMarkDepthlastMarker
|
|
{
|
|
return markDepth;
|
|
}
|
|
|
|
- (void) setMarkDepth:(NSInteger) anInt
|
|
{
|
|
markDepth = anInt;
|
|
}
|
|
|
|
@end
|