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