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 37TreeNavigationNodeDown *navigationNodeDown = nil; 38TreeNavigationNodeUp *navigationNodeUp = nil; 39TreeNavigationNodeEOF *navigationNodeEOF = nil; 40 41 42@implementation BaseTree 43 44static 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