// // 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)adaptor Tree:(CommonTree *)aTree { return [[BufferedTreeNodeStream alloc] initWithTreeAdaptor:adaptor Tree:(CommonTree *)aTree]; } + (BufferedTreeNodeStream *) newBufferedTreeNodeStream:(id)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)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)getTokenStream { return tokens; } - (void) setTokenStream:(id)newtokens { tokens = newtokens; } - (id)getTreeAdaptor { return adaptor; } - (void) setTreeAdaptor:(id)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