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 28 #import "ANTLRUnbufferedCommonTreeNodeStream.h" 29 #import "ANTLRUnbufferedCommonTreeNodeStreamState.h" 30 #import "ANTLRBaseTree.h" 31 #import "ANTLRToken.h" 32 33 #define INITIAL_LOOKAHEAD_BUFFER_SIZE 5 34 @implementation ANTLRUnbufferedCommonTreeNodeStream 35 36 @synthesize root; 37 @synthesize currentNode; 38 @synthesize previousNode; 39 @synthesize treeAdaptor; 40 @synthesize tokenStream; 41 @synthesize nodeStack; 42 @synthesize indexStack; 43 @synthesize markers; 44 @synthesize lastMarker; 45 @synthesize currentChildIndex; 46 @synthesize absoluteNodeIndex; 47 @synthesize lookahead; 48 @synthesize head; 49 @synthesize tail; 50 51 - (id) initWithTree:(ANTLRCommonTree *)theTree 52 { 53 return [self initWithTree:theTree treeAdaptor:nil]; 54 } 55 56 - (id) initWithTree:(ANTLRCommonTree *)theTree treeAdaptor:(ANTLRCommonTreeAdaptor *)theAdaptor 57 { 58 if ((self = [super init]) != nil) { 59 [self setRoot:theTree]; 60 if ( theAdaptor == nil ) 61 [self setTreeAdaptor:[ANTLRCommonTreeAdaptor newTreeAdaptor]]; 62 else 63 [self setTreeAdaptor:theAdaptor]; 64 nodeStack = [[NSMutableArray arrayWithCapacity:5] retain]; 65 indexStack = [[NSMutableArray arrayWithCapacity:5] retain]; 66 markers = [[ANTLRPtrBuffer newANTLRPtrBufferWithLen:100] retain]; 67 // [markers insertObject:[NSNull null] atIndex:0]; // markers is one based - maybe fix this later 68 lookahead = [NSMutableArray arrayWithCapacity:INITIAL_LOOKAHEAD_BUFFER_SIZE]; // lookahead is filled with [NSNull null] in -reset 69 [lookahead retain]; 70 [self reset]; 71 } 72 return self; 73 } 74 75 - (void) dealloc 76 { 77 [self setRoot:nil]; 78 [self setTreeAdaptor:nil]; 79 80 [nodeStack release]; nodeStack = nil; 81 [indexStack release]; indexStack = nil; 82 [markers release]; markers = nil; 83 [lookahead release]; lookahead = nil; 84 85 [super dealloc]; 86 } 87 88 - (void) reset 89 { 90 currentNode = root; 91 previousNode = nil; 92 currentChildIndex = -1; 93 absoluteNodeIndex = -1; 94 head = tail = 0; 95 [nodeStack removeAllObjects]; 96 [indexStack removeAllObjects]; 97 [markers removeAllObjects]; 98 // [markers insertObject:[NSNull null] atIndex:0]; // markers is one based - maybe fix this later 99 [lookahead removeAllObjects]; 100 // TODO: this is not ideal, but works for now. optimize later 101 int i; 102 for (i = 0; i < INITIAL_LOOKAHEAD_BUFFER_SIZE; i++) 103 [lookahead addObject:[NSNull null]]; 104 } 105 106 107 #pragma mark ANTLRTreeNodeStream conformance 108 109 - (id) LT:(NSInteger)k 110 { 111 if (k == -1) 112 return previousNode; 113 if (k < 0) 114 @throw [NSException exceptionWithName:@"ANTLRTreeException" reason:@"-LT: looking back more than one node unsupported for unbuffered streams" userInfo:nil]; 115 if (k == 0) 116 return ANTLRBaseTree.INVALID_NODE; 117 [self fillBufferWithLookahead:k]; 118 return [lookahead objectAtIndex:(head+k-1) % [lookahead count]]; 119 } 120 121 - (id) treeSource 122 { 123 return [self root]; 124 } 125 126 - (id<ANTLRTreeAdaptor>) getTreeAdaptor; 127 { 128 return treeAdaptor; 129 } 130 131 - (void)setTreeAdaptor:(id<ANTLRTreeAdaptor>)aTreeAdaptor 132 { 133 if (treeAdaptor != aTreeAdaptor) { 134 [aTreeAdaptor retain]; 135 [treeAdaptor release]; 136 treeAdaptor = aTreeAdaptor; 137 } 138 } 139 140 - (id<ANTLRTokenStream>) getTokenStream 141 { 142 return tokenStream; 143 } 144 145 - (void) setTokenStream:(id<ANTLRTokenStream>)aTokenStream 146 { 147 if (tokenStream != aTokenStream) { 148 [tokenStream release]; 149 [aTokenStream retain]; 150 tokenStream = aTokenStream; 151 } 152 } 153 154 - (void) setUsesUniqueNavigationNodes:(BOOL)flag 155 { 156 shouldUseUniqueNavigationNodes = flag; 157 } 158 159 - (id) nodeAtIndex:(NSUInteger) idx 160 { 161 @throw [NSException exceptionWithName:@"ANTLRTreeException" reason:@"-nodeAtIndex: unsupported for unbuffered streams" userInfo:nil]; 162 } 163 164 - (NSString *) toString 165 { 166 @throw [NSException exceptionWithName:@"ANTLRTreeException" reason:@"-toString unsupported for unbuffered streams" userInfo:nil]; 167 } 168 169 - (NSString *) toStringWithRange:(NSRange) aRange 170 { 171 @throw [NSException exceptionWithName:@"ANTLRTreeException" reason:@"-toString: unsupported for unbuffered streams" userInfo:nil]; 172 } 173 174 - (NSString *) toStringFromNode:(id)startNode ToNode:(id)stopNode 175 { 176 @throw [NSException exceptionWithName:@"ANTLRTreeException" reason:@"-toStringFromNode:toNode: unsupported for unbuffered streams" userInfo:nil]; 177 } 178 179 #pragma mark ANTLRIntStream conformance 180 181 - (void) consume 182 { 183 [self fillBufferWithLookahead:1]; 184 absoluteNodeIndex++; 185 previousNode = [lookahead objectAtIndex:head]; 186 head = (head+1) % [lookahead count]; 187 } 188 189 - (NSInteger) LA:(NSUInteger) i 190 { 191 ANTLRCommonTree *node = [self LT:i]; 192 if (!node) 193 return ANTLRTokenTypeInvalid; 194 int ttype = [node getType]; 195 return ttype; 196 } 197 198 - (NSUInteger) mark 199 { 200 ANTLRUnbufferedCommonTreeNodeStreamState *state = [[[ANTLRUnbufferedCommonTreeNodeStreamState alloc] init] retain]; 201 [state setCurrentNode:currentNode]; 202 [state setPreviousNode:previousNode]; 203 [state setIndexStackSize:[indexStack count]]; 204 [state setNodeStackSize:[nodeStack count]]; 205 [state setCurrentChildIndex:currentChildIndex]; 206 [state setAbsoluteNodeIndex:absoluteNodeIndex]; 207 unsigned int lookaheadSize = [self lookaheadSize]; 208 unsigned int k; 209 for ( k = 0; k < lookaheadSize; k++) { 210 [state addToLookahead:[self LT:k+1]]; 211 } 212 [markers addObject:state]; 213 //[state release]; 214 return [markers count]; 215 } 216 217 - (NSUInteger) getIndex 218 { 219 return absoluteNodeIndex + 1; 220 } 221 222 - (void) rewind:(NSUInteger) marker 223 { 224 if ( [markers count] < marker ) { 225 return; 226 } 227 ANTLRUnbufferedCommonTreeNodeStreamState *state = [markers objectAtIndex:marker]; 228 [markers removeObjectAtIndex:marker]; 229 230 absoluteNodeIndex = [state absoluteNodeIndex]; 231 currentChildIndex = [state currentChildIndex]; 232 currentNode = [state currentNode]; 233 previousNode = [state previousNode]; 234 // drop node and index stacks back to old size 235 [nodeStack removeObjectsInRange:NSMakeRange([state nodeStackSize], [nodeStack count]-[state nodeStackSize])]; 236 [indexStack removeObjectsInRange:NSMakeRange([state indexStackSize], [indexStack count]-[state indexStackSize])]; 237 238 head = tail = 0; // wack lookahead buffer and then refill 239 [lookahead release]; 240 lookahead = [[NSMutableArray alloc] initWithArray:[state lookahead]]; 241 tail = [lookahead count]; 242 // make some room after the restored lookahead, so that the above line is not a bug ;) 243 // this also ensures that a subsequent -addLookahead: will not immediately need to resize the buffer 244 [lookahead addObjectsFromArray:[NSArray arrayWithObjects:[NSNull null], [NSNull null], [NSNull null], [NSNull null], [NSNull null], nil]]; 245 } 246 247 - (void) rewind 248 { 249 [self rewind:[markers count]]; 250 } 251 252 - (void) release:(NSUInteger) marker 253 { 254 @throw [NSException exceptionWithName:@"ANTLRTreeException" reason:@"-release: unsupported for unbuffered streams" userInfo:nil]; 255 } 256 257 - (void) seek:(NSUInteger) anIndex 258 { 259 if ( anIndex < (NSUInteger) index ) 260 @throw [NSException exceptionWithName:@"ANTLRTreeException" reason:@"-seek: backwards unsupported for unbuffered streams" userInfo:nil]; 261 while ( (NSUInteger) index < anIndex ) { 262 [self consume]; 263 } 264 } 265 266 - (NSUInteger) size; 267 { 268 return absoluteNodeIndex + 1; // not entirely correct, but cheap. 269 } 270 271 272 #pragma mark Lookahead Handling 273 - (void) addLookahead:(id<ANTLRBaseTree>)aNode 274 { 275 [lookahead replaceObjectAtIndex:tail withObject:aNode]; 276 tail = (tail+1) % [lookahead count]; 277 278 if ( tail == head ) { 279 NSMutableArray *newLookahead = [[[NSMutableArray alloc] initWithCapacity:[lookahead count]*2] retain]; 280 281 NSRange headRange = NSMakeRange(head, [lookahead count]-head); 282 NSRange tailRange = NSMakeRange(0, tail); 283 284 [newLookahead addObjectsFromArray:[lookahead objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:headRange]]]; 285 [newLookahead addObjectsFromArray:[lookahead objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:tailRange]]]; 286 287 unsigned int i; 288 unsigned int lookaheadCount = [newLookahead count]; 289 for (i = 0; i < lookaheadCount; i++) 290 [newLookahead addObject:[NSNull null]]; 291 [lookahead release]; 292 lookahead = newLookahead; 293 294 head = 0; 295 tail = lookaheadCount; // tail is the location the _next_ lookahead node will end up in, not the last element's idx itself! 296 } 297 298 } 299 300 - (NSUInteger) lookaheadSize 301 { 302 return tail < head 303 ? ([lookahead count] - head + tail) 304 : (tail - head); 305 } 306 307 - (void) fillBufferWithLookahead:(NSInteger)k 308 { 309 unsigned int n = [self lookaheadSize]; 310 unsigned int i; 311 id lookaheadObject = self; // any valid object would do. 312 for (i=1; i <= k-n && lookaheadObject != nil; i++) { 313 lookaheadObject = [self nextObject]; 314 } 315 } 316 317 - (id) nextObject 318 { 319 // NOTE: this could/should go into an NSEnumerator subclass for treenode streams. 320 if (currentNode == nil) { 321 if ( navigationNodeEOF == nil ) { 322 navigationNodeEOF = [[ANTLRTreeNavigationNodeEOF alloc] init]; 323 } 324 [self addLookahead:navigationNodeEOF]; 325 return nil; 326 } 327 if (currentChildIndex == -1) { 328 return [self handleRootNode]; 329 } 330 if (currentChildIndex < (NSInteger)[currentNode getChildCount]) { 331 return [self visitChild:currentChildIndex]; 332 } 333 [self walkBackToMostRecentNodeWithUnvisitedChildren]; 334 if (currentNode != nil) { 335 return [self visitChild:currentChildIndex]; 336 } 337 338 return nil; 339 } 340 341 #pragma mark Node visiting 342 - (ANTLRCommonTree *) handleRootNode 343 { 344 ANTLRCommonTree *node = currentNode; 345 currentChildIndex = 0; 346 if ([node isNil]) { 347 node = [self visitChild:currentChildIndex]; 348 } else { 349 [self addLookahead:node]; 350 if ([currentNode getChildCount] == 0) { 351 currentNode = nil; 352 } 353 } 354 return node; 355 } 356 357 - (ANTLRCommonTree *) visitChild:(NSInteger)childNumber 358 { 359 ANTLRCommonTree *node = nil; 360 361 [nodeStack addObject:currentNode]; 362 [indexStack addObject:[NSNumber numberWithInt:childNumber]]; 363 if (childNumber == 0 && ![currentNode isNil]) 364 [self addNavigationNodeWithType:ANTLRTokenTypeDOWN]; 365 366 currentNode = [currentNode getChild:childNumber]; 367 currentChildIndex = 0; 368 node = currentNode; // record node to return 369 [self addLookahead:node]; 370 [self walkBackToMostRecentNodeWithUnvisitedChildren]; 371 return node; 372 } 373 374 - (void) walkBackToMostRecentNodeWithUnvisitedChildren 375 { 376 while (currentNode != nil && currentChildIndex >= (NSInteger)[currentNode getChildCount]) 377 { 378 currentNode = (ANTLRCommonTree *)[nodeStack lastObject]; 379 [nodeStack removeLastObject]; 380 currentChildIndex = [(NSNumber *)[indexStack lastObject] intValue]; 381 [indexStack removeLastObject]; 382 currentChildIndex++; // move to next child 383 if (currentChildIndex >= (NSInteger)[currentNode getChildCount]) { 384 if (![currentNode isNil]) { 385 [self addNavigationNodeWithType:ANTLRTokenTypeUP]; 386 } 387 if (currentNode == root) { // we done yet? 388 currentNode = nil; 389 } 390 } 391 } 392 393 } 394 395 - (void) addNavigationNodeWithType:(NSInteger)tokenType 396 { 397 // TODO: this currently ignores shouldUseUniqueNavigationNodes. 398 switch (tokenType) { 399 case ANTLRTokenTypeDOWN: { 400 if (navigationNodeDown == nil) { 401 navigationNodeDown = [[ANTLRTreeNavigationNodeDown alloc] init]; 402 } 403 [self addLookahead:navigationNodeDown]; 404 break; 405 } 406 case ANTLRTokenTypeUP: { 407 if (navigationNodeUp == nil) { 408 navigationNodeUp = [[ANTLRTreeNavigationNodeUp alloc] init]; 409 } 410 [self addLookahead:navigationNodeUp]; 411 break; 412 } 413 } 414 } 415 416 #pragma mark Accessors 417 - (ANTLRCommonTree *) root 418 { 419 return root; 420 } 421 422 - (void) setRoot: (ANTLRCommonTree *) aRoot 423 { 424 if (root != aRoot) { 425 [aRoot retain]; 426 [root release]; 427 root = aRoot; 428 } 429 } 430 431 @end 432 433