blob: bf4102674cc6a5b0ad55e859245a1aeead82525a [file] [log] [blame]
//
// BufferedTreeNodeStream.m
// ANTLR
//
// [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 "BufferedTreeNodeStream.h"
#import "StreamEnumerator.h"
#import "CommonTreeAdaptor.h"
extern NSInteger debug;
#ifdef DONTUSENOMO
@implementation TreeStreamIterator
+ newTreeStreamIteratorWithNodes:(BufferedTreeNodeStream *)theStream
{
return[[TreeStreamIterator alloc] initWithStream:theStream];
}
- (id) initWithStream:(BufferedTreeNodeStream *)theStream
{
if ((self = [super init]) != nil) {
idx = 0;
input = theStream;
nodes = [theStream getNodes];
}
return self;
}
- (BOOL) hasNext
{
return idx < [nodes count];
}
- (id) next
{
NSInteger current = idx;
idx++;
if (current < [nodes count]) {
}
return [nodes getEof];
}
- (void) remove
{
@throw [RuntimeException newException:@"cannot remove nodes from stream"];
}
@end
#endif
@implementation BufferedTreeNodeStream
@synthesize up;
@synthesize down;
@synthesize eof;
@synthesize nodes;
@synthesize root;
@synthesize tokens;
@synthesize adaptor;
@synthesize uniqueNavigationNodes;
@synthesize index;
@synthesize lastMarker;
@synthesize calls;
@synthesize e;
@synthesize currentSymbol;
+ (BufferedTreeNodeStream *) newBufferedTreeNodeStream:(CommonTree *) aTree
{
return [((BufferedTreeNodeStream *)[BufferedTreeNodeStream alloc]) initWithTree:(CommonTree *)aTree];
}
+ (BufferedTreeNodeStream *) newBufferedTreeNodeStream:(id<TreeAdaptor>)adaptor Tree:(CommonTree *)aTree
{
return [[BufferedTreeNodeStream alloc] initWithTreeAdaptor:adaptor Tree:(CommonTree *)aTree];
}
+ (BufferedTreeNodeStream *) newBufferedTreeNodeStream:(id<TreeAdaptor>)adaptor Tree:(CommonTree *)aTree withBufferSize:(NSInteger)initialBufferSize
{
return [[BufferedTreeNodeStream alloc] initWithTreeAdaptor:adaptor Tree:(CommonTree *)aTree WithBufferSize:initialBufferSize];
}
-(BufferedTreeNodeStream *) init
{
self = [super init];
if (self) {
index = -1;
uniqueNavigationNodes = NO;
root = [[CommonTree alloc] init];
// tokens = tree;
adaptor = [[[CommonTreeAdaptor alloc] init] retain];
nodes = [[AMutableArray arrayWithCapacity:DEFAULT_INITIAL_BUFFER_SIZE] retain];
down = [[adaptor createTree:TokenTypeDOWN Text:@"DOWN"] retain];
up = [[adaptor createTree:TokenTypeUP Text:@"UP"] retain];
eof = [[adaptor createTree:TokenTypeEOF Text:@"EOF"] retain];
}
return self;
}
- (BufferedTreeNodeStream *)initWithTree:(CommonTree *) aTree
{
self = [super init];
if (self) {
index = -1;
uniqueNavigationNodes = NO;
root = aTree;
// tokens = aTree;
adaptor = [[[CommonTreeAdaptor alloc] init] retain];
nodes = [[AMutableArray arrayWithCapacity:DEFAULT_INITIAL_BUFFER_SIZE] retain];
down = [[adaptor createTree:TokenTypeDOWN Text:@"DOWN"] retain];
up = [[adaptor createTree:TokenTypeUP Text:@"UP"] retain];
eof = [[adaptor createTree:TokenTypeEOF Text:@"EOF"] retain];
}
return self;
}
-(BufferedTreeNodeStream *) initWithTreeAdaptor:(CommonTreeAdaptor *)anAdaptor Tree:(CommonTree *)aTree
{
self = [super init];
if (self) {
index = -1;
uniqueNavigationNodes = NO;
root = aTree;
// tokens = aTree;
adaptor = [anAdaptor retain];
nodes = [[AMutableArray arrayWithCapacity:DEFAULT_INITIAL_BUFFER_SIZE] retain];
down = [[adaptor createTree:TokenTypeDOWN Text:@"DOWN"] retain];
up = [[adaptor createTree:TokenTypeUP Text:@"UP"] retain];
eof = [[adaptor createTree:TokenTypeEOF Text:@"EOF"] retain];
}
return self;
}
-(BufferedTreeNodeStream *) initWithTreeAdaptor:(CommonTreeAdaptor *)anAdaptor Tree:(CommonTree *)aTree WithBufferSize:(NSInteger)bufferSize
{
self = [super init];
if (self) {
// down = [adaptor createToken:TokenTypeDOWN withText:@"DOWN"];
// up = [adaptor createToken:TokenTypeDOWN withText:@"UP"];
// eof = [adaptor createToken:TokenTypeDOWN withText:@"EOF"];
index = -1;
uniqueNavigationNodes = NO;
root = aTree;
// tokens = aTree;
adaptor = [anAdaptor retain];
nodes = [[AMutableArray arrayWithCapacity:bufferSize] retain];
down = [[adaptor createTree:TokenTypeDOWN Text:@"DOWN"] retain];
up = [[adaptor createTree:TokenTypeUP Text:@"UP"] retain];
eof = [[adaptor createTree:TokenTypeEOF Text:@"EOF"] retain];
}
return self;
}
- (void)dealloc
{
#ifdef DEBUG_DEALLOC
NSLog( @"called dealloc in BufferedTreeNodeStream" );
#endif
if ( adaptor ) [adaptor release];
if ( nodes ) [nodes release];
if ( root ) [root release];
if ( down ) [down release];
if ( up ) [up release];
if ( eof ) [eof release];
[super dealloc];
}
- (id) copyWithZone:(NSZone *)aZone
{
BufferedTreeNodeStream *copy;
copy = [[[self class] allocWithZone:aZone] init];
if ( up )
copy.up = [up copyWithZone:aZone];
if ( down )
copy.down = [down copyWithZone:aZone];
if ( eof )
copy.eof = [eof copyWithZone:aZone];
if ( nodes )
copy.nodes = [nodes copyWithZone:aZone];
if ( root )
copy.root = [root copyWithZone:aZone];
if ( tokens )
copy.tokens = [tokens copyWithZone:aZone];
if ( adaptor )
copy.adaptor = [adaptor copyWithZone:aZone];
copy.uniqueNavigationNodes = self.uniqueNavigationNodes;
copy.index = self.index;
copy.lastMarker = self.lastMarker;
if ( calls )
copy.calls = [calls copyWithZone:aZone];
return copy;
}
// protected methods. DO NOT USE
#pragma mark Protected Methods
-(void) fillBuffer
{
[self fillBufferWithTree:root];
// if (debug > 1) NSLog("revIndex=%@", tokenTypeToStreamIndexesMap);
index = 0; // buffer of nodes intialized now
}
-(void) fillBufferWithTree:(CommonTree *) aTree
{
BOOL empty = [adaptor isNil:(id<BaseTree>)aTree];
if (!empty) {
[nodes addObject:aTree];
}
NSInteger n = [adaptor getChildCount:aTree];
if (!empty && n > 0) {
[self addNavigationNode:TokenTypeDOWN];
}
for (NSInteger c = 0; c < n; c++) {
id child = [adaptor getChild:aTree At:c];
[self fillBufferWithTree:child];
}
if (!empty && n > 0) {
[self addNavigationNode:TokenTypeUP];
}
}
-(NSInteger) getNodeIndex:(CommonTree *) node
{
if (index == -1) {
[self fillBuffer];
}
for (NSUInteger i = 0; i < [nodes count]; i++) {
id t = [nodes objectAtIndex:i];
if (t == node) {
return i;
}
}
return -1;
}
-(void) addNavigationNode:(NSInteger) type
{
id navNode = nil;
if (type == TokenTypeDOWN) {
if (self.uniqueNavigationNodes) {
navNode = [adaptor createToken:TokenTypeDOWN Text:@"DOWN"];
}
else {
navNode = down;
}
}
else {
if (self.uniqueNavigationNodes) {
navNode = [adaptor createToken:TokenTypeUP Text:@"UP"];
}
else {
navNode = up;
}
}
[nodes addObject:navNode];
}
-(id) get:(NSUInteger) i
{
if (index == -1) {
[self fillBuffer];
}
return [nodes objectAtIndex:i];
}
-(id) LT:(NSInteger) k
{
if (index == -1) {
[self fillBuffer];
}
if (k == 0) {
return nil;
}
if (k < 0) {
return [self LB:-k];
}
if ((index + k - 1) >= [nodes count]) {
return eof;
}
return [nodes objectAtIndex:(index + k - 1)];
}
-(id) getCurrentSymbol
{
return [self LT:1];
}
-(id) LB:(NSInteger) k
{
if (k == 0) {
return nil;
}
if ((index - k) < 0) {
return nil;
}
return [nodes objectAtIndex:(index - k)];
}
- (CommonTree *)getTreeSource
{
return root;
}
-(NSString *)getSourceName
{
return [[self getTokenStream] getSourceName];
}
- (id<TokenStream>)getTokenStream
{
return tokens;
}
- (void) setTokenStream:(id<TokenStream>)newtokens
{
tokens = newtokens;
}
- (id<TreeAdaptor>)getTreeAdaptor
{
return adaptor;
}
- (void) setTreeAdaptor:(id<TreeAdaptor>)anAdaptor
{
adaptor = anAdaptor;
}
- (BOOL)getUniqueNavigationNodes
{
return uniqueNavigationNodes;
}
- (void) setUniqueNavigationNodes:(BOOL)aVal
{
uniqueNavigationNodes = aVal;
}
-(void) consume
{
if (index == -1) {
[self fillBuffer];
}
index++;
}
-(NSInteger) LA:(NSInteger) i
{
return [adaptor getType:[self LT:i]];
}
-(NSInteger) mark
{
if (index == -1) {
[self fillBuffer];
}
lastMarker = self.index;
return lastMarker;
}
-(void) release:(NSInteger) marker
{
// do nothing
}
-(void) rewind:(NSInteger) marker
{
[self seek:marker];
}
-(void) rewind
{
[self seek:lastMarker];
}
-(void) seek:(NSInteger) i
{
if (index == -1) {
[self fillBuffer];
}
index = i;
}
-(void) push:(NSInteger) i
{
if (calls == nil) {
calls = [IntArray newArrayWithLen:INITIAL_CALL_STACK_SIZE];
}
[calls push:index];
[self seek:i];
}
-(NSInteger) pop
{
NSInteger ret = [calls pop];
[self seek:ret];
return ret;
}
-(void) reset
{
index = 0;
lastMarker = 0;
if (calls != nil) {
[calls reset];
}
}
-(NSUInteger) count
{
if (index == -1) {
[self fillBuffer];
}
return [nodes count];
}
-(NSUInteger) size
{
return [self count];
}
-(NSEnumerator *) objectEnumerator
{
if (e == nil) {
e = [[StreamEnumerator alloc] initWithNodes:nodes andEOF:eof];
}
return e;
}
-(void) replaceChildren:(CommonTree *) parent From:(NSInteger)startIdx To:(NSInteger)stopIdx With:(CommonTree *)aTree
{
if (parent != nil) {
[adaptor replaceChildren:parent From:startIdx To:stopIdx With:aTree];
}
}
-(NSString *) toTokenTypeString
{
if (index == -1)
{
[self fillBuffer];
}
NSMutableString *buf = [NSMutableString stringWithCapacity:10];
for (NSUInteger i= 0; i < [nodes count]; i++) {
CommonTree * aTree = (CommonTree *)[self get:i];
[buf appendFormat:@" %d", [adaptor getType:aTree]];
}
return buf;
}
-(NSString *) toTokenString:(NSInteger)aStart ToEnd:(NSInteger)aStop
{
if (index == -1) {
[self fillBuffer];
}
NSMutableString *buf = [NSMutableString stringWithCapacity:10];
for (NSUInteger i = aStart; i < [nodes count] && i <= aStop; i++) {
CommonTree * t = (CommonTree *)[self get:i];
[buf appendFormat:@" %d", [adaptor getType:t]];
}
return buf;
}
-(NSString *) toStringFromNode:(id)aStart ToNode:(id)aStop
{
if (aStart == nil || aStop == nil) {
return nil;
}
if (index == -1) {
[self fillBuffer];
}
// if we have a token stream, use that to dump text in order
if ([self getTokenStream] != nil) {
NSInteger beginTokenIndex = [adaptor getTokenStartIndex:aStart];
NSInteger endTokenIndex = [adaptor getTokenStopIndex:aStop];
if ([adaptor getType:aStop] == TokenTypeUP) {
endTokenIndex = [adaptor getTokenStopIndex:aStart];
}
else if ([adaptor getType:aStop] == TokenTypeEOF) {
endTokenIndex = [self count] - 2; //don't use EOF
}
[tokens toStringFromStart:beginTokenIndex ToEnd:endTokenIndex];
}
// walk nodes looking for aStart
CommonTree * aTree = nil;
NSUInteger i = 0;
for (; i < [nodes count]; i++) {
aTree = [nodes objectAtIndex:i];
if (aTree == aStart) {
break;
}
}
NSMutableString *buf = [NSMutableString stringWithCapacity:10];
aTree = [nodes objectAtIndex:i]; // why?
while (aTree != aStop) {
NSString *text = [adaptor getText:aTree];
if (text == nil) {
text = [NSString stringWithFormat:@" %d", [adaptor getType:aTree]];
}
[buf appendString:text];
i++;
aTree = [nodes objectAtIndex:i];
}
NSString *text = [adaptor getText:aStop];
if (text == nil) {
text = [NSString stringWithFormat:@" %d", [adaptor getType:aStop]];
}
[buf appendString:text];
return buf;
}
// getters and setters
- (AMutableArray *) getNodes
{
return nodes;
}
- (id) eof
{
return eof;
}
- (void) setEof:(id)theEOF
{
eof = theEOF;
}
@end