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 "BaseTree.h" 28 #import "BaseTreeAdaptor.h" 29 #import "Token.h" 30 // TODO: this shouldn't be here...but needed for invalidNode 31 #import "AMutableArray.h" 32 #import "CommonTree.h" 33 #import "RuntimeException.h" 34 #import "ANTLRError.h" 35 36 #pragma mark - Navigation Nodes 37 TreeNavigationNodeDown *navigationNodeDown = nil; 38 TreeNavigationNodeUp *navigationNodeUp = nil; 39 TreeNavigationNodeEOF *navigationNodeEOF = nil; 40 41 42 @implementation BaseTree 43 44 static id<BaseTree> invalidNode = nil; 45 46 #pragma mark Tree protocol conformance 47 48 + (id<BaseTree>) INVALID_NODE 49 { 50 if ( invalidNode == nil ) { 51 invalidNode = [[CommonTree alloc] initWithTokenType:TokenTypeInvalid]; 52 } 53 return invalidNode; 54 } 55 56 + (id<BaseTree>) invalidNode 57 { 58 if ( invalidNode == nil ) { 59 invalidNode = [[CommonTree alloc] initWithTokenType:TokenTypeInvalid]; 60 } 61 return invalidNode; 62 } 63 64 + newTree 65 { 66 return [[BaseTree alloc] init]; 67 } 68 69 /** Create a new node from an existing node does nothing for BaseTree 70 * as there are no fields other than the children list, which cannot 71 * be copied as the children are not considered part of this node. 72 */ 73 + newTree:(id<BaseTree>) node 74 { 75 return [[BaseTree alloc] initWith:(id<BaseTree>) node]; 76 } 77 78 - (id) init 79 { 80 self = [super init]; 81 if ( self != nil ) { 82 children = nil; 83 return self; 84 } 85 return nil; 86 } 87 88 - (id) initWith:(id<BaseTree>)node 89 { 90 self = [super init]; 91 if ( self != nil ) { 92 // children = [[AMutableArray arrayWithCapacity:5] retain]; 93 // [children addObject:node]; 94 [self addChild:node]; 95 return self; 96 } 97 return nil; 98 } 99 100 - (void) dealloc 101 { 102 #ifdef DEBUG_DEALLOC 103 NSLog( @"called dealloc in BaseTree %x", (NSInteger)self ); 104 #endif 105 if ( children ) { 106 #ifdef DEBUG_DEALLOC 107 NSLog( @"called dealloc children in BaseTree" ); 108 #endif 109 [children release]; 110 } 111 [super dealloc]; 112 } 113 114 - (id<BaseTree>) getChild:(NSUInteger)i 115 { 116 if ( children == nil || i >= [children count] ) { 117 return nil; 118 } 119 return (id<BaseTree>)[children objectAtIndex:i]; 120 } 121 122 /** Get the children internal List; note that if you directly mess with 123 * the list, do so at your own risk. 124 */ 125 - (AMutableArray *) children 126 { 127 return children; 128 } 129 130 - (void) setChildren:(AMutableArray *)anArray 131 { 132 if ( children != anArray ) { 133 if ( children ) [children release]; 134 if ( anArray ) [anArray retain]; 135 } 136 children = anArray; 137 } 138 139 - (id<BaseTree>) getFirstChildWithType:(NSInteger) aType 140 { 141 for (NSUInteger i = 0; children != nil && i < [children count]; i++) { 142 id<BaseTree> t = (id<BaseTree>) [children objectAtIndex:i]; 143 if ( t.type == aType ) { 144 return t; 145 } 146 } 147 return nil; 148 } 149 150 - (NSUInteger) getChildCount 151 { 152 if ( children == nil ) { 153 return 0; 154 } 155 return [children count]; 156 } 157 158 /** Add t as child of this node. 159 * 160 * Warning: if t has no children, but child does 161 * and child isNil then this routine moves children to t via 162 * t.children = child.children; i.e., without copying the array. 163 */ 164 - (void) addChild:(id<BaseTree>) t 165 { 166 //System.out.println("add child "+t.toStringTree()+" "+self.toStringTree()); 167 //System.out.println("existing children: "+children); 168 if ( t == nil ) { 169 return; // do nothing upon addChild(nil) 170 } 171 if ( self == (BaseTree *)t ) 172 @throw [IllegalArgumentException newException:@"BaseTree Can't add self to self as child"]; 173 id<BaseTree> childTree = (id<BaseTree>) t; 174 if ( [childTree isNil] ) { // t is an empty node possibly with children 175 if ( children != nil && children == childTree.children ) { 176 @throw [RuntimeException newException:@"BaseTree add child list to itself"]; 177 } 178 // just add all of childTree's children to this 179 if ( childTree.children != nil ) { 180 if ( children != nil ) { // must copy, this has children already 181 int n = [childTree.children count]; 182 for ( int i = 0; i < n; i++) { 183 id<BaseTree> c = (id<BaseTree>)[childTree.children objectAtIndex:i]; 184 [children addObject:c]; 185 // handle double-link stuff for each child of nil root 186 [c setParent:(id<BaseTree>)self]; 187 [c setChildIndex:[children count]-1]; 188 } 189 } 190 else { 191 // no children for this but t has children; just set pointer 192 // call general freshener routine 193 children = childTree.children; 194 [self freshenParentAndChildIndexes]; 195 } 196 } 197 } 198 else { // child is not nil (don't care about children) 199 if ( children == nil ) { 200 children = [[AMutableArray arrayWithCapacity:5] retain]; // create children list on demand 201 } 202 [children addObject:t]; 203 [childTree setParent:(id<BaseTree>)self]; 204 [childTree setChildIndex:[children count]-1]; 205 } 206 // System.out.println("now children are: "+children); 207 } 208 209 /** Add all elements of kids list as children of this node */ 210 - (void) addChildren:(AMutableArray *) kids 211 { 212 for (NSUInteger i = 0; i < [kids count]; i++) { 213 id<BaseTree> t = (id<BaseTree>) [kids objectAtIndex:i]; 214 [self addChild:t]; 215 } 216 } 217 218 - (void) setChild:(NSUInteger) i With:(id<BaseTree>)t 219 { 220 if ( t == nil ) { 221 return; 222 } 223 if ( [t isNil] ) { 224 @throw [IllegalArgumentException newException:@"BaseTree Can't set single child to a list"]; 225 } 226 if ( children == nil ) { 227 children = [[AMutableArray arrayWithCapacity:5] retain]; 228 } 229 if ([children count] > i ) { 230 [children replaceObjectAtIndex:i withObject:t]; 231 } 232 else { 233 [children insertObject:t atIndex:i]; 234 } 235 [t setParent:(id<BaseTree>)self]; 236 [t setChildIndex:i]; 237 } 238 239 - (id) deleteChild:(NSUInteger) idx 240 { 241 if ( children == nil ) { 242 return nil; 243 } 244 id<BaseTree> killed = (id<BaseTree>)[children objectAtIndex:idx]; 245 [children removeObjectAtIndex:idx]; 246 // walk rest and decrement their child indexes 247 [self freshenParentAndChildIndexes:idx]; 248 return killed; 249 } 250 251 /** Delete children from start to stop and replace with t even if t is 252 * a list (nil-root Tree). num of children can increase or decrease. 253 * For huge child lists, inserting children can force walking rest of 254 * children to set their childindex; could be slow. 255 */ 256 - (void) replaceChildrenFrom:(NSInteger)startChildIndex To:(NSInteger)stopChildIndex With:(id) t 257 { 258 /* 259 System.out.println("replaceChildren "+startChildIndex+", "+stopChildIndex+ 260 " with "+((BaseTree)t).toStringTree()); 261 System.out.println("in="+toStringTree()); 262 */ 263 if ( children == nil ) { 264 @throw [IllegalArgumentException newException:@"BaseTree Invalid Indexes; no children in list"]; 265 } 266 int replacingHowMany = stopChildIndex - startChildIndex + 1; 267 int replacingWithHowMany; 268 id<BaseTree> newTree = (id<BaseTree>) t; 269 AMutableArray *newChildren = nil; 270 // normalize to a list of children to add: newChildren 271 if ( [newTree isNil] ) { 272 newChildren = newTree.children; 273 } 274 else { 275 newChildren = [AMutableArray arrayWithCapacity:5]; 276 [newChildren addObject:newTree]; 277 } 278 replacingWithHowMany = [newChildren count]; 279 int numNewChildren = [newChildren count]; 280 int delta = replacingHowMany - replacingWithHowMany; 281 // if same number of nodes, do direct replace 282 if ( delta == 0 ) { 283 int j = 0; // index into new children 284 for (int i=startChildIndex; i <= stopChildIndex; i++) { 285 id<BaseTree> child = (id<BaseTree>)[newChildren objectAtIndex:j]; 286 [children replaceObjectAtIndex:i withObject:(id)child]; 287 [child setParent:(id<BaseTree>)self]; 288 [child setChildIndex:i]; 289 j++; 290 } 291 } 292 else if ( delta > 0 ) { // fewer new nodes than there were 293 // set children and then delete extra 294 for (int j = 0; j < numNewChildren; j++) { 295 [children replaceObjectAtIndex:startChildIndex+j withObject:[newChildren objectAtIndex:j]]; 296 } 297 int indexToDelete = startChildIndex+numNewChildren; 298 for (int c=indexToDelete; c<=stopChildIndex; c++) { 299 // delete same index, shifting everybody down each time 300 [children removeObjectAtIndex:indexToDelete]; 301 } 302 [self freshenParentAndChildIndexes:startChildIndex]; 303 } 304 else { // more new nodes than were there before 305 // fill in as many children as we can (replacingHowMany) w/o moving data 306 for (int j=0; j<replacingHowMany; j++) { 307 [children replaceObjectAtIndex:startChildIndex+j withObject:[newChildren objectAtIndex:j]]; 308 } 309 // int numToInsert = replacingWithHowMany-replacingHowMany; 310 for (int j=replacingHowMany; j<replacingWithHowMany; j++) { 311 [children insertObject:[newChildren objectAtIndex:j] atIndex:startChildIndex+j]; 312 } 313 [self freshenParentAndChildIndexes:startChildIndex]; 314 } 315 //System.out.println("out="+toStringTree()); 316 } 317 318 /** Override in a subclass to change the impl of children list */ 319 - (AMutableArray *) createChildrenList 320 { 321 return [AMutableArray arrayWithCapacity:5]; 322 } 323 324 - (BOOL) isNil 325 { 326 return NO; 327 } 328 329 /** Set the parent and child index values for all child of t */ 330 - (void) freshenParentAndChildIndexes 331 { 332 [self freshenParentAndChildIndexes:0]; 333 } 334 335 - (void) freshenParentAndChildIndexes:(NSInteger) offset 336 { 337 int n = [self getChildCount]; 338 for (int i = offset; i < n; i++) { 339 id<BaseTree> child = (id<BaseTree>)[self getChild:i]; 340 [child setChildIndex:i]; 341 [child setParent:(id<BaseTree>)self]; 342 } 343 } 344 345 - (void) sanityCheckParentAndChildIndexes 346 { 347 [self sanityCheckParentAndChildIndexes:nil At:-1]; 348 } 349 350 - (void) sanityCheckParentAndChildIndexes:(id<BaseTree>)aParent At:(NSInteger) i 351 { 352 if ( aParent != [self getParent] ) { 353 @throw [IllegalStateException newException:[NSString stringWithFormat:@"parents don't match; expected %s found %s", aParent, [self getParent]]]; 354 } 355 if ( i != [self getChildIndex] ) { 356 @throw [IllegalStateException newException:[NSString stringWithFormat:@"child indexes don't match; expected %d found %d", i, [self getChildIndex]]]; 357 } 358 int n = [self getChildCount]; 359 for (int c = 0; c < n; c++) { 360 id<BaseTree> child = (id<BaseTree>)[self getChild:c]; 361 [child sanityCheckParentAndChildIndexes:(id<BaseTree>)self At:c]; 362 } 363 } 364 365 /** What is the smallest token index (indexing from 0) for this node 366 * and its children? 367 */ 368 - (NSInteger) getTokenStartIndex 369 { 370 return 0; 371 } 372 373 - (void) setTokenStartIndex:(NSInteger) anIndex 374 { 375 } 376 377 /** What is the largest token index (indexing from 0) for this node 378 * and its children? 379 */ 380 - (NSInteger) getTokenStopIndex 381 { 382 return 0; 383 } 384 385 - (void) setTokenStopIndex:(NSInteger) anIndex 386 { 387 } 388 389 - (id<BaseTree>) dupNode 390 { 391 return nil; 392 } 393 394 395 /** BaseTree doesn't track child indexes. */ 396 - (NSInteger) getChildIndex 397 { 398 return 0; 399 } 400 401 - (void) setChildIndex:(NSInteger) anIndex 402 { 403 } 404 405 /** BaseTree doesn't track parent pointers. */ 406 - (id<BaseTree>) getParent 407 { 408 return nil; 409 } 410 411 - (void) setParent:(id<BaseTree>) t 412 { 413 } 414 415 /** Walk upwards looking for ancestor with this token type. */ 416 - (BOOL) hasAncestor:(NSInteger) ttype 417 { 418 return([self getAncestor:ttype] != nil); 419 } 420 421 /** Walk upwards and get first ancestor with this token type. */ 422 - (id<BaseTree>) getAncestor:(NSInteger) ttype 423 { 424 id<BaseTree> t = (id<BaseTree>)self; 425 t = (id<BaseTree>)[t getParent]; 426 while ( t != nil ) { 427 if ( t.type == ttype ) 428 return t; 429 t = (id<BaseTree>)[t getParent]; 430 } 431 return nil; 432 } 433 434 /** Return a list of all ancestors of this node. The first node of 435 * list is the root and the last is the parent of this node. 436 */ 437 - (AMutableArray *)getAncestors 438 { 439 if ( [self getParent] == nil ) 440 return nil; 441 AMutableArray *ancestors = [AMutableArray arrayWithCapacity:5]; 442 id<BaseTree> t = (id<BaseTree>)self; 443 t = (id<BaseTree>)[t getParent]; 444 while ( t != nil ) { 445 [ancestors insertObject:t atIndex:0]; // insert at start 446 t = (id<BaseTree>)[t getParent]; 447 } 448 return ancestors; 449 } 450 451 - (NSInteger)type 452 { 453 return TokenTypeInvalid; 454 } 455 456 - (NSString *)text 457 { 458 return nil; 459 } 460 461 - (NSUInteger)line 462 { 463 return 0; 464 } 465 466 - (NSUInteger)charPositionInLine 467 { 468 return 0; 469 } 470 471 - (void) setCharPositionInLine:(NSUInteger) pos 472 { 473 } 474 475 #pragma mark Copying 476 477 // the children themselves are not copied here! 478 - (id) copyWithZone:(NSZone *)aZone 479 { 480 id<BaseTree> theCopy = [[[self class] allocWithZone:aZone] init]; 481 [theCopy addChildren:self.children]; 482 return theCopy; 483 } 484 485 - (id) deepCopy // performs a deepCopyWithZone: with the default zone 486 { 487 return [self deepCopyWithZone:NULL]; 488 } 489 490 - (id) deepCopyWithZone:(NSZone *)aZone 491 { 492 id<BaseTree> theCopy = [self copyWithZone:aZone]; 493 494 if ( [theCopy.children count] ) 495 [theCopy.children removeAllObjects]; 496 AMutableArray *childrenCopy = theCopy.children; 497 for (id loopItem in children) { 498 id<BaseTree> childCopy = [loopItem deepCopyWithZone:aZone]; 499 [theCopy addChild:childCopy]; 500 } 501 if ( childrenCopy ) [childrenCopy release]; 502 return theCopy; 503 } 504 505 - (NSString *) treeDescription 506 { 507 if ( children == nil || [children count] == 0 ) { 508 return [self description]; 509 } 510 NSMutableString *buf = [NSMutableString stringWithCapacity:[children count]]; 511 if ( ![self isNil] ) { 512 [buf appendString:@"("]; 513 [buf appendString:[self toString]]; 514 [buf appendString:@" "]; 515 } 516 for (int i = 0; children != nil && i < [children count]; i++) { 517 id<BaseTree> t = (id<BaseTree>)[children objectAtIndex:i]; 518 if ( i > 0 ) { 519 [buf appendString:@" "]; 520 } 521 [buf appendString:[(id<BaseTree>)t toStringTree]]; 522 } 523 if ( ![self isNil] ) { 524 [buf appendString:@")"]; 525 } 526 return buf; 527 } 528 529 /** Print out a whole tree not just a node */ 530 - (NSString *) toStringTree 531 { 532 return [self treeDescription]; 533 } 534 535 - (NSString *) description 536 { 537 return nil; 538 } 539 540 /** Override to say how a node (not a tree) should look as text */ 541 - (NSString *) toString 542 { 543 return nil; 544 } 545 546 @synthesize children; 547 @synthesize anException; 548 549 @end 550 551 #pragma mark - 552 553 @implementation TreeNavigationNode 554 - (id)init 555 { 556 self = (TreeNavigationNode *)[super init]; 557 return self; 558 } 559 560 - (id) copyWithZone:(NSZone *)aZone 561 { 562 return nil; 563 } 564 @end 565 566 @implementation TreeNavigationNodeDown 567 + (TreeNavigationNodeDown *) getNavigationNodeDown 568 { 569 if ( navigationNodeDown == nil ) 570 navigationNodeDown = [[TreeNavigationNodeDown alloc] init]; 571 return navigationNodeDown; 572 } 573 574 - (id)init 575 { 576 self = [super init]; 577 return self; 578 } 579 580 - (NSInteger) tokenType { return TokenTypeDOWN; } 581 - (NSString *) description { return @"DOWN"; } 582 @end 583 584 @implementation TreeNavigationNodeUp 585 + (TreeNavigationNodeUp *) getNavigationNodeUp 586 { 587 if ( navigationNodeUp == nil ) 588 navigationNodeUp = [[TreeNavigationNodeUp alloc] init]; 589 return navigationNodeUp; 590 } 591 592 593 - (id)init 594 { 595 self = [super init]; 596 return self; 597 } 598 599 - (NSInteger) tokenType { return TokenTypeUP; } 600 - (NSString *) description { return @"UP"; } 601 @end 602 603 @implementation TreeNavigationNodeEOF 604 + (TreeNavigationNodeEOF *) getNavigationNodeEOF 605 { 606 if ( navigationNodeEOF == nil ) 607 navigationNodeEOF = [[TreeNavigationNodeEOF alloc] init]; 608 return navigationNodeEOF; 609 } 610 611 - (id)init 612 { 613 self = [super init]; 614 return self; 615 } 616 617 - (NSInteger) tokenType { return TokenTypeEOF; } 618 - (NSString *) description { return @"EOF"; } 619 620 @end 621 622