1// [The "BSD licence"] 2// Copyright (c) 2006-2007 Kay Roepke 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 "CommonTreeNodeStream.h" 28#import "TokenStream.h" 29#import "IntStream.h" 30#import "CharStream.h" 31#import "AMutableArray.h" 32#import "CommonTreeAdaptor.h" 33 34#ifndef DEBUG_DEALLOC 35#define DEBUG_DEALLOC 36#endif 37 38@implementation CommonTreeNodeStream 39 40@synthesize root; 41@synthesize tokens; 42@synthesize adaptor; 43@synthesize level; 44 45+ (CommonTreeNodeStream *) newCommonTreeNodeStream:(CommonTree *)theTree 46{ 47 return [[CommonTreeNodeStream alloc] initWithTree:theTree]; 48} 49 50+ (CommonTreeNodeStream *) newCommonTreeNodeStream:(id<TreeAdaptor>)anAdaptor Tree:(CommonTree *)theTree 51{ 52 return [[CommonTreeNodeStream alloc] initWithTreeAdaptor:anAdaptor Tree:theTree]; 53} 54 55- (id) initWithTree:(CommonTree *)theTree 56{ 57 if ((self = [super init]) != nil ) { 58 adaptor = [[CommonTreeAdaptor newTreeAdaptor] retain]; 59 root = [theTree retain]; 60 navigationNodeEOF = [[adaptor createTree:TokenTypeEOF Text:@"EOF"] retain]; // set EOF 61 it = [[TreeIterator newANTRLTreeIteratorWithAdaptor:adaptor andTree:root] retain]; 62 calls = [[IntArray newArrayWithLen:INITIAL_CALL_STACK_SIZE] retain]; 63 /** Tree (nil A B C) trees like flat A B C streams */ 64 hasNilRoot = NO; 65 level = 0; 66 } 67 return self; 68} 69 70- (id) initWithTreeAdaptor:(id<TreeAdaptor>)anAdaptor Tree:(CommonTree *)theTree 71{ 72 if ((self = [super init]) != nil ) { 73 adaptor = [anAdaptor retain]; 74 root = [theTree retain]; 75 navigationNodeEOF = [[adaptor createTree:TokenTypeEOF Text:@"EOF"] retain]; // set EOF 76 // it = [root objectEnumerator]; 77 it = [[TreeIterator newANTRLTreeIteratorWithAdaptor:adaptor andTree:root] retain]; 78 calls = [[IntArray newArrayWithLen:INITIAL_CALL_STACK_SIZE] retain]; 79 /** Tree (nil A B C) trees like flat A B C streams */ 80 hasNilRoot = NO; 81 level = 0; 82 } 83 // eof = [self isEOF]; // make sure tree iterator returns the EOF we want 84 return self; 85} 86 87- (void)dealloc 88{ 89#ifdef DEBUG_DEALLOC 90 NSLog( @"called dealloc in CommonTreeNodeStream" ); 91#endif 92 if ( root ) [root release]; 93 if ( tokens ) [tokens release]; 94 if ( adaptor ) [adaptor release]; 95 if ( it ) [it release]; 96 if ( calls ) [calls release]; 97 [super dealloc]; 98} 99 100- (void) reset 101{ 102 [super reset]; 103 [it reset]; 104 hasNilRoot = false; 105 level = 0; 106 if ( calls != nil ) 107 [calls reset]; // [calls clear]; // in Java 108} 109 110/** Pull elements from tree iterator. Track tree level 0..max_level. 111 * If nil rooted tree, don't give initial nil and DOWN nor final UP. 112 */ 113- (id) nextElement 114{ 115 id t = [it nextObject]; 116 //System.out.println("pulled "+adaptor.getType(t)); 117 if ( t == [it up] ) { 118 level--; 119 if ( level==0 && hasNilRoot ) return [it nextObject]; // don't give last UP; get EOF 120 } 121 else if ( t == [it down] ) 122 level++; 123 if ( level == 0 && [adaptor isNil:t] ) { // if nil root, scarf nil, DOWN 124 hasNilRoot = true; 125 t = [it nextObject]; // t is now DOWN, so get first real node next 126 level++; 127 t = [it nextObject]; 128 } 129 return t; 130} 131 132- (BOOL) isEOF:(id<BaseTree>) aTree 133{ 134 return [adaptor getType:(CommonTree *)aTree] == TokenTypeEOF; 135} 136 137- (void) setUniqueNavigationNodes:(BOOL) uniqueNavigationNodes 138{ 139} 140 141- (id) getTreeSource 142{ 143 return root; 144} 145 146- (NSString *) getSourceName 147{ 148 return [[self getTokenStream] getSourceName]; 149} 150 151- (id<TokenStream>) getTokenStream 152{ 153 return tokens; 154} 155 156- (void) setTokenStream:(id<TokenStream>)theTokens 157{ 158 if ( tokens != theTokens ) { 159 if ( tokens ) [tokens release]; 160 [theTokens retain]; 161 } 162 tokens = theTokens; 163} 164 165- (CommonTreeAdaptor *) getTreeAdaptor 166{ 167 return adaptor; 168} 169 170- (void) setTreeAdaptor:(CommonTreeAdaptor *) anAdaptor 171{ 172 if ( adaptor != anAdaptor ) { 173 if ( adaptor ) [adaptor release]; 174 [anAdaptor retain]; 175 } 176 adaptor = anAdaptor; 177} 178 179- (CommonTree *)getNode:(NSInteger) i 180{ 181 @throw [RuntimeException newException:@"Absolute node indexes are meaningless in an unbuffered stream"]; 182 return nil; 183} 184 185- (NSInteger) LA:(NSInteger) i 186{ 187 return [adaptor getType:[self LT:i]]; 188} 189 190/** Make stream jump to a new location, saving old location. 191 * Switch back with pop(). 192 */ 193- (void) push:(NSInteger) anIndex 194{ 195 if ( calls == nil ) { 196 calls = [[IntArray newArrayWithLen:INITIAL_CALL_STACK_SIZE] retain]; 197 } 198 [calls push:p]; // save current anIndex 199 [self seek:anIndex]; 200} 201 202/** Seek back to previous anIndex saved during last push() call. 203 * Return top of stack (return anIndex). 204 */ 205- (NSInteger) pop 206{ 207 int ret = [calls pop]; 208 [self seek:ret]; 209 return ret; 210} 211 212// TREE REWRITE INTERFACE 213 214- (void) replaceChildren:(id) parent From:(NSInteger)startChildIndex To:(NSInteger)stopChildIndex With:(id) aTree 215{ 216 if ( parent != nil ) { 217 [adaptor replaceChildren:parent From:startChildIndex To:stopChildIndex With:aTree]; 218 } 219} 220 221- (NSString *) toStringFromNode:(id<BaseTree>)startNode ToNode:(id<BaseTree>)stopNode 222{ 223 // we'll have to walk from start to stop in tree; we're not keeping 224 // a complete node stream buffer 225 return @"n/a"; 226} 227 228/** For debugging; destructive: moves tree iterator to end. */ 229- (NSString *) toTokenTypeString 230{ 231 [self reset]; 232 NSMutableString *buf = [NSMutableString stringWithCapacity:5]; 233 id obj = [self LT:1]; 234 NSInteger type = [adaptor getType:obj]; 235 while ( type != TokenTypeEOF ) { 236 [buf appendString:@" "]; 237 [buf appendString:[NSString stringWithFormat:@"%d", type]]; 238 [self consume]; 239 obj = [self LT:1]; 240 type = [adaptor getType:obj]; 241 } 242 return buf; 243} 244 245@synthesize it; 246@synthesize calls; 247@synthesize hasNilRoot; 248@end 249 250