// [The "BSD licence"] // Copyright (c) 2006-2007 Kay Roepke 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 "ANTLRCommonTreeNodeStream.h" #import "ANTLRTokenStream.h" #import "ANTLRIntStream.h" #import "ANTLRCharStream.h" #import "AMutableArray.h" #import "ANTLRCommonTreeAdaptor.h" #ifndef DEBUG_DEALLOC #define DEBUG_DEALLOC #endif @implementation ANTLRCommonTreeNodeStream @synthesize root; @synthesize tokens; @synthesize adaptor; @synthesize level; + (ANTLRCommonTreeNodeStream *) newANTLRCommonTreeNodeStream:(ANTLRCommonTree *)theTree { return [[ANTLRCommonTreeNodeStream alloc] initWithTree:theTree]; } + (ANTLRCommonTreeNodeStream *) newANTLRCommonTreeNodeStream:(id<ANTLRTreeAdaptor>)anAdaptor Tree:(ANTLRCommonTree *)theTree { return [[ANTLRCommonTreeNodeStream alloc] initWithTreeAdaptor:anAdaptor Tree:theTree]; } - (id) initWithTree:(ANTLRCommonTree *)theTree { if ((self = [super init]) != nil ) { adaptor = [[ANTLRCommonTreeAdaptor newTreeAdaptor] retain]; root = [theTree retain]; navigationNodeEOF = [[adaptor createTree:ANTLRTokenTypeEOF Text:@"EOF"] retain]; // set EOF it = [[ANTLRTreeIterator newANTRLTreeIteratorWithAdaptor:adaptor andTree:root] retain]; calls = [[ANTLRIntArray newArrayWithLen:INITIAL_CALL_STACK_SIZE] retain]; /** Tree (nil A B C) trees like flat A B C streams */ hasNilRoot = NO; level = 0; } return self; } - (id) initWithTreeAdaptor:(id<ANTLRTreeAdaptor>)anAdaptor Tree:(ANTLRCommonTree *)theTree { if ((self = [super init]) != nil ) { adaptor = [anAdaptor retain]; root = [theTree retain]; navigationNodeEOF = [[adaptor createTree:ANTLRTokenTypeEOF Text:@"EOF"] retain]; // set EOF // it = [root objectEnumerator]; it = [[ANTLRTreeIterator newANTRLTreeIteratorWithAdaptor:adaptor andTree:root] retain]; calls = [[ANTLRIntArray newArrayWithLen:INITIAL_CALL_STACK_SIZE] retain]; /** Tree (nil A B C) trees like flat A B C streams */ hasNilRoot = NO; level = 0; } // eof = [self isEOF]; // make sure tree iterator returns the EOF we want return self; } - (void)dealloc { #ifdef DEBUG_DEALLOC NSLog( @"called dealloc in ANTLRCommonTreeNodeStream" ); #endif if ( root ) [root release]; if ( tokens ) [tokens release]; if ( adaptor ) [adaptor release]; if ( it ) [it release]; if ( calls ) [calls release]; [super dealloc]; } - (void) reset { [super reset]; [it reset]; hasNilRoot = false; level = 0; if ( calls != nil ) [calls reset]; // [calls clear]; // in Java } /** Pull elements from tree iterator. Track tree level 0..max_level. * If nil rooted tree, don't give initial nil and DOWN nor final UP. */ - (id) nextElement { id t = [it nextObject]; //System.out.println("pulled "+adaptor.getType(t)); if ( t == [it up] ) { level--; if ( level==0 && hasNilRoot ) return [it nextObject]; // don't give last UP; get EOF } else if ( t == [it down] ) level++; if ( level == 0 && [adaptor isNil:t] ) { // if nil root, scarf nil, DOWN hasNilRoot = true; t = [it nextObject]; // t is now DOWN, so get first real node next level++; t = [it nextObject]; } return t; } - (BOOL) isEOF:(id<ANTLRBaseTree>) aTree { return [adaptor getType:(ANTLRCommonTree *)aTree] == ANTLRTokenTypeEOF; } - (void) setUniqueNavigationNodes:(BOOL) uniqueNavigationNodes { } - (id) getTreeSource { return root; } - (NSString *) getSourceName { return [[self getTokenStream] getSourceName]; } - (id<ANTLRTokenStream>) getTokenStream { return tokens; } - (void) setTokenStream:(id<ANTLRTokenStream>)theTokens { if ( tokens != theTokens ) { if ( tokens ) [tokens release]; [theTokens retain]; } tokens = theTokens; } - (ANTLRCommonTreeAdaptor *) getTreeAdaptor { return adaptor; } - (void) setTreeAdaptor:(ANTLRCommonTreeAdaptor *) anAdaptor { if ( adaptor != anAdaptor ) { if ( adaptor ) [adaptor release]; [anAdaptor retain]; } adaptor = anAdaptor; } - (ANTLRCommonTree *)getNode:(NSInteger) i { @throw [ANTLRRuntimeException newException:@"Absolute node indexes are meaningless in an unbuffered stream"]; return nil; } - (NSInteger) LA:(NSInteger) i { return [adaptor getType:[self LT:i]]; } /** Make stream jump to a new location, saving old location. * Switch back with pop(). */ - (void) push:(NSInteger) anIndex { if ( calls == nil ) { calls = [[ANTLRIntArray newArrayWithLen:INITIAL_CALL_STACK_SIZE] retain]; } [calls push:p]; // save current anIndex [self seek:anIndex]; } /** Seek back to previous anIndex saved during last push() call. * Return top of stack (return anIndex). */ - (NSInteger) pop { int ret = [calls pop]; [self seek:ret]; return ret; } // TREE REWRITE INTERFACE - (void) replaceChildren:(id) parent From:(NSInteger)startChildIndex To:(NSInteger)stopChildIndex With:(id) aTree { if ( parent != nil ) { [adaptor replaceChildren:parent From:startChildIndex To:stopChildIndex With:aTree]; } } - (NSString *) toStringFromNode:(id<ANTLRBaseTree>)startNode ToNode:(id<ANTLRBaseTree>)stopNode { // we'll have to walk from start to stop in tree; we're not keeping // a complete node stream buffer return @"n/a"; } /** For debugging; destructive: moves tree iterator to end. */ - (NSString *) toTokenTypeString { [self reset]; NSMutableString *buf = [NSMutableString stringWithCapacity:5]; id obj = [self LT:1]; NSInteger type = [adaptor getType:obj]; while ( type != ANTLRTokenTypeEOF ) { [buf appendString:@" "]; [buf appendString:[NSString stringWithFormat:@"%d", type]]; [self consume]; obj = [self LT:1]; type = [adaptor getType:obj]; } return buf; } @synthesize it; @synthesize calls; @synthesize hasNilRoot; @end