Home | History | Annotate | Download | only in Framework
      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