ANTLRTreeAdaptor.m revision 324c4644fee44b9898524c09511bd33c3f12e2df
1// [The "BSD licence"]
2// Copyright (c) 2006-2007 Kay Roepke
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 "ANTLRTreeAdaptor.h"
28#import "ANTLRTreeException.h"
29#import "ANTLRBaseTree.h"
30
31@implementation ANTLRTreeAdaptor
32
33
34+ (id<ANTLRBaseTree>) newEmptyTree
35{
36	return [ANTLRTreeAdaptor newTreeWithToken:nil];
37}
38
39+ (id) newAdaptor
40{
41    return [[ANTLRTreeAdaptor alloc] init];
42}
43
44- (id) init
45{
46    self = [super init];
47    return self;
48}
49
50- (id) initWithPayload:(id<ANTLRToken>)payload
51{
52    self = [super init];
53    return self;
54}
55
56#pragma mark Rewrite Rules
57
58/** Create a tree node from Token object; for CommonTree type trees,
59 *  then the token just becomes the payload.  This is the most
60 *  common create call.
61 *
62 *  Override if you want another kind of node to be built.
63 */
64- (id<ANTLRBaseTree>) create:(id<ANTLRToken>) payload
65{
66    return nil;
67}
68
69/** Create a new node derived from a token, with a new token type.
70 *  This is invoked from an imaginary node ref on right side of a
71 *  rewrite rule as IMAG[$tokenLabel].
72 *
73 *  This should invoke createToken(Token).
74 */
75- (id<ANTLRBaseTree>) createTree:(NSInteger)tokenType fromToken:(id<ANTLRToken>)fromToken
76{
77	id<ANTLRToken> newToken = [self createToken:fromToken];
78	[newToken setType:tokenType];
79    
80	id<ANTLRBaseTree> newTree = [self create:newToken];
81	[newToken release];
82	return newTree;
83}
84
85/** Create a new node derived from a token, with a new token type.
86 *  This is invoked from an imaginary node ref on right side of a
87 *  rewrite rule as IMAG[$tokenLabel].
88 *
89 *  This should invoke createToken(Token).
90 */
91- (id<ANTLRBaseTree>) createTree:(NSInteger)tokenType fromToken:(id<ANTLRToken>)fromToken text:(NSString *)tokenText
92{
93	id<ANTLRToken> newToken = [self createToken:fromToken];
94	[newToken setText:tokenText];
95	
96	id<ANTLRBaseTree> newTree = [self create:newToken];
97	[newToken release];
98	return newTree;
99}
100
101/** Create a new node derived from a token, with a new token type.
102 *  This is invoked from an imaginary node ref on right side of a
103 *  rewrite rule as IMAG["IMAG"].
104 *
105 *  This should invoke createToken(int,String).
106 */
107- (id<ANTLRBaseTree>) createTree:(NSInteger)tokenType text:(NSString *)tokenText
108{
109	id<ANTLRToken> newToken = [self createToken:tokenType text:tokenText];
110	
111	id<ANTLRBaseTree> newTree = [self create:newToken];
112	[newToken release];
113	return newTree;
114}
115
116- (id) copyNode:(id<ANTLRBaseTree>)aNode
117{
118	return [aNode copyWithZone:nil];	// not -copy: to silence warnings
119}
120
121- (id) copyTree:(id<ANTLRBaseTree>)aTree
122{
123	return [aTree deepCopy];
124}
125
126
127- (void) addChild:(id<ANTLRBaseTree>)child toTree:(id<ANTLRBaseTree>)aTree
128{
129	[aTree addChild:child];
130}
131
132- (id) makeNode:(id<ANTLRBaseTree>)newRoot parentOf:(id<ANTLRBaseTree>)oldRoot
133{
134	id<ANTLRBaseTree> newRootNode = newRoot;
135
136	if (oldRoot == nil)
137		return newRootNode;
138    // handles ^(nil real-node) case
139	if ([newRootNode isNil]) {
140		if ([newRootNode getChildCount] > 1) {
141#warning TODO: Find a way to the current input stream here!
142			@throw [ANTLRTreeException exceptionWithOldRoot:oldRoot newRoot:newRootNode stream:nil];
143		}
144#warning TODO: double check memory management with respect to code generation
145		// remove the empty node, placing its sole child in its role.
146		id<ANTLRBaseTree> tmpRootNode = [[newRootNode childAtIndex:0] retain];
147		[newRootNode release];
148		newRootNode = tmpRootNode;		
149	}
150	// the handling of an empty node at the root of oldRoot happens in addChild:
151	[newRootNode addChild:oldRoot];
152    // this release relies on the fact that the ANTLR code generator always assigns the return value of this method
153    // to the variable originally holding oldRoot. If we don't release we leak the reference.
154    // FIXME: this is totally non-obvious. maybe do it in calling code by comparing pointers and conditionally releasing
155    // the old object
156    [oldRoot release];
157    
158    // what happens to newRootNode's retain count? Should we be autoreleasing this one? Probably.
159	return [newRootNode retain];
160}
161
162
163- (id<ANTLRBaseTree>) postProcessTree:(id<ANTLRBaseTree>)aTree
164{
165	id<ANTLRBaseTree> processedNode = aTree;
166	if (aTree != nil && [aTree isNil] != NO && [aTree getChildCount] == 1) {
167		processedNode = [aTree childAtIndex:0];
168	}
169	return processedNode;
170}
171
172
173- (NSUInteger) uniqueIdForTree:(id<ANTLRBaseTree>)aNode
174{
175	// TODO: is hash appropriate here?
176	return [aNode hash];
177}
178
179
180#pragma mark Content
181
182- (NSInteger) tokenTypeForNode:(id<ANTLRBaseTree>)aNode
183{
184	return [aNode getType];
185}
186
187- (void) setTokenType:(NSInteger)tokenType forNode:(id)aNode
188{
189	// currently unimplemented
190}
191
192
193- (NSString *) textForNode:(id<ANTLRBaseTree>)aNode
194{
195	return [aNode getText];
196}
197
198- (void) setText:(NSString *)tokenText forNode:(id<ANTLRBaseTree>)aNode
199{
200	// currently unimplemented
201}
202
203
204#pragma mark Navigation / Tree Parsing
205
206- (id<ANTLRBaseTree>) childForNode:(id<ANTLRBaseTree>) aNode atIndex:(NSInteger) i
207{
208	// currently unimplemented
209	return nil;
210}
211
212- (NSInteger) childCountForTree:(id<ANTLRBaseTree>) aTree
213{
214	// currently unimplemented
215	return 0;
216}
217
218#pragma mark Subclass Responsibilties
219
220- (void) setBoundariesForTree:(id<ANTLRBaseTree>)aTree fromToken:(id<ANTLRToken>)startToken toToken:(id<ANTLRToken>)stopToken
221{
222	// subclass responsibility
223}
224
225- (NSInteger) tokenStartIndexForTree:(id<ANTLRBaseTree>)aTree
226{
227	// subclass responsibility
228	return 0;
229}
230
231- (NSInteger) tokenStopIndexForTree:(id<ANTLRBaseTree>)aTree
232{
233	// subclass responsibility
234	return 0;
235}
236
237
238@end
239