• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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