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 "ANTLRCommonTree.h"
28
29
30@implementation ANTLRCommonTree
31
32+ (ANTLRCommonTree *)INVALID_NODE
33{
34	return [[ANTLRCommonTree alloc] initWithToken:[ANTLRCommonToken invalidToken]];
35}
36
37+ (ANTLRCommonTree *)invalidNode
38{
39    // Had to cast to ANTLRCommonTree * here, because GCC is dumb.
40	return [[ANTLRCommonTree alloc] initWithToken:ANTLRCommonToken.INVALID_TOKEN];
41}
42
43+ (ANTLRCommonTree *)newTree
44{
45    return [[ANTLRCommonTree alloc] init];
46}
47
48+ (ANTLRCommonTree *)newTreeWithTree:(ANTLRCommonTree *)aTree
49{
50    return [[ANTLRCommonTree alloc] initWithTreeNode:aTree];
51}
52
53+ (ANTLRCommonTree *)newTreeWithToken:(id<ANTLRToken>)aToken
54{
55	return [[ANTLRCommonTree alloc] initWithToken:aToken];
56}
57
58+ (ANTLRCommonTree *)newTreeWithTokenType:(NSInteger)aTType
59{
60	return [[ANTLRCommonTree alloc] initWithTokenType:(NSInteger)aTType];
61}
62
63+ (ANTLRCommonTree *)newTreeWithTokenType:(NSInteger)aTType Text:(NSString *)theText
64{
65	return [[ANTLRCommonTree alloc] initWithTokenType:(NSInteger)aTType Text:theText];
66}
67
68- (id)init
69{
70	self = (ANTLRCommonTree *)[super init];
71	if ( self != nil ) {
72        token = nil;
73		startIndex = -1;
74		stopIndex = -1;
75        parent = nil;
76        childIndex = -1;
77	}
78	return (ANTLRCommonTree *)self;
79}
80
81- (id)initWithTreeNode:(ANTLRCommonTree *)aNode
82{
83	self = (ANTLRCommonTree *)[super init];
84	if ( self != nil ) {
85		token = aNode.token;
86        if ( token ) [token retain];
87		startIndex = aNode.startIndex;
88		stopIndex = aNode.stopIndex;
89        parent = nil;
90        childIndex = -1;
91	}
92	return self;
93}
94
95- (id)initWithToken:(id<ANTLRToken>)aToken
96{
97	self = (ANTLRCommonTree *)[super init];
98	if ( self != nil ) {
99		token = aToken;
100        if ( token ) [token retain];
101		startIndex = -1;
102		stopIndex = -1;
103        parent = nil;
104        childIndex = -1;
105	}
106	return self;
107}
108
109- (id)initWithTokenType:(NSInteger)aTokenType
110{
111	self = (ANTLRCommonTree *)[super init];
112	if ( self != nil ) {
113		token = [[ANTLRCommonToken newToken:aTokenType] retain];
114//		startIndex = token.startIndex;
115		startIndex = -1;
116//		stopIndex = token.stopIndex;
117		stopIndex = -1;
118        parent = nil;
119        childIndex = -1;
120	}
121	return self;
122}
123
124- (id) initWithTokenType:(NSInteger)aTokenType Text:(NSString *)theText
125{
126	self = (ANTLRCommonTree *)[super init];
127	if ( self != nil ) {
128		token = [[ANTLRCommonToken newToken:aTokenType Text:theText] retain];
129//		startIndex = token.startIndex;
130		startIndex = -1;
131//		stopIndex = token.stopIndex;
132		stopIndex = -1;
133        parent = nil;
134        childIndex = -1;
135	}
136	return self;
137}
138
139- (void) dealloc
140{
141    if ( token ) {
142        [token release];
143        token = nil;
144    }
145    if ( parent ) {
146        [parent release];
147        parent = nil;
148    }
149	[super dealloc];
150}
151
152- (id) copyWithZone:(NSZone *)aZone
153{
154    ANTLRCommonTree *copy;
155	
156    //    copy = [[[self class] allocWithZone:aZone] init];
157    copy = [super copyWithZone:aZone]; // allocation occurs in ANTLRBaseTree
158    if ( self.token )
159        copy.token = [self.token copyWithZone:aZone];
160    copy.startIndex = startIndex;
161    copy.stopIndex = stopIndex;
162    copy.parent = (ANTLRCommonTree *)[self.parent copyWithZone:aZone];
163    copy.childIndex = childIndex;
164    return copy;
165}
166
167- (BOOL) isNil
168{
169	return token == nil;
170}
171
172- (ANTLRCommonToken *) getToken
173{
174	return token;
175}
176
177- (void) setToken:(ANTLRCommonToken *) aToken
178{
179	if ( token != aToken ) {
180		if ( token ) [token release];
181		[aToken retain];
182		token = aToken;
183	}
184}
185
186- (ANTLRCommonTree *) dupNode
187{
188    return [ANTLRCommonTree newTreeWithTree:self ];
189}
190
191- (NSInteger)type
192{
193	if (token)
194		return token.type;
195	return ANTLRTokenTypeInvalid;
196}
197
198- (NSString *)text
199{
200	if (token)
201		return token.text;
202	return nil;
203}
204
205- (NSUInteger)line
206{
207	if (token)
208		return token.line;
209	return 0;
210}
211
212- (void) setLine:(NSUInteger)aLine
213{
214    if (token)
215        token.line = aLine;
216}
217
218- (NSUInteger)charPositionInLine
219{
220	if (token)
221		return token.charPositionInLine;
222	return 0;
223}
224
225- (void) setCharPositionInLine:(NSUInteger)pos
226{
227    if (token)
228        token.charPositionInLine = pos;
229}
230
231- (NSInteger) getTokenStartIndex
232{
233	if ( startIndex == -1 && token != nil ) {
234		return [token getTokenIndex];
235	}
236    return startIndex;
237}
238
239- (void) setTokenStartIndex: (NSInteger) aStartIndex
240{
241    startIndex = aStartIndex;
242}
243
244- (NSInteger) getTokenStopIndex
245{
246	if ( stopIndex == -1 && token != nil ) {
247		return [token getTokenIndex];
248	}
249    return stopIndex;
250}
251
252- (void) setTokenStopIndex: (NSInteger) aStopIndex
253{
254    stopIndex = aStopIndex;
255}
256
257#ifdef DONTUSENOMO
258- (NSString *) treeDescription
259{
260	if (children) {
261		NSMutableString *desc = [NSMutableString stringWithString:@"(^"];
262		[desc appendString:[self description]];
263		unsigned int childIdx;
264		for (childIdx = 0; childIdx < [children count]; childIdx++) {
265			[desc appendFormat:@"%@", [[children objectAtIndex:childIdx] treeDescription]];
266		}
267		[desc appendString:@")"];
268		return desc;
269	} else {
270		return [self description];
271	}
272}
273#endif
274
275/** For every node in this subtree, make sure it's start/stop token's
276 *  are set.  Walk depth first, visit bottom up.  Only updates nodes
277 *  with at least one token index < 0.
278 */
279- (void) setUnknownTokenBoundaries
280{
281    if ( children == nil ) {
282        if ( startIndex<0 || stopIndex<0 ) {
283            startIndex = stopIndex = [token getTokenIndex];
284        }
285        return;
286    }
287    for (NSUInteger i=0; i < [children count]; i++) {
288        [[children objectAtIndex:i] setUnknownTokenBoundaries];
289    }
290    if ( startIndex >= 0 && stopIndex >= 0 )
291         return; // already set
292    if ( [children count] > 0 ) {
293        ANTLRCommonTree *firstChild = (ANTLRCommonTree *)[children objectAtIndex:0];
294        ANTLRCommonTree *lastChild = (ANTLRCommonTree *)[children objectAtIndex:[children count]-1];
295        startIndex = [firstChild getTokenStartIndex];
296        stopIndex = [lastChild getTokenStopIndex];
297    }
298}
299
300- (NSInteger) getChildIndex
301{
302    return childIndex;
303}
304
305- (ANTLRCommonTree *) getParent
306{
307    return parent;
308}
309
310- (void) setParent:(ANTLRCommonTree *) t
311{
312    parent = t;
313}
314
315- (void) setChildIndex:(NSInteger) anIndex
316{
317    childIndex = anIndex;
318}
319
320- (NSString *) description
321{
322    return [self toString];
323}
324
325- (NSString *) toString
326{
327    if ( [self isNil] ) {
328        return @"nil";
329    }
330    if ( [self type] == ANTLRTokenTypeInvalid ) {
331        return @"<errornode>";
332    }
333    if ( token==nil ) {
334        return nil;
335    }
336    return token.text;
337}
338
339@synthesize token;
340@synthesize startIndex;
341@synthesize stopIndex;
342@synthesize parent;
343@synthesize childIndex;
344
345@end
346