xref: /aosp_15_r20/external/antlr/runtime/ObjC/Framework/BaseTree.m (revision 16467b971bd3e2009fad32dd79016f2c7e421deb)
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