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 "TreeAdaptor.h" 28#import "TreeException.h" 29#import "BaseTree.h" 30 31@implementation TreeAdaptor 32 33 34+ (id) newEmptyTree 35{ 36 return [TreeAdaptor newTreeWithToken:nil]; 37} 38 39+ (id) newAdaptor 40{ 41 return [[TreeAdaptor alloc] init]; 42} 43 44- (id) init 45{ 46 self = [super init]; 47 return self; 48} 49 50- (id) initWithPayload:(id<Token>)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) create:(id<Token>) 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) createTree:(NSInteger)tokenType fromToken:(id<Token>)fromToken 76{ 77 id<Token> newToken = [self createToken:fromToken]; 78 [newToken setType:tokenType]; 79 80 id 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) createTree:(NSInteger)tokenType fromToken:(id<Token>)fromToken text:(NSString *)tokenText 92{ 93 id<Token> newToken = [self createToken:fromToken]; 94 [newToken setText:tokenText]; 95 96 id 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) createTree:(NSInteger)tokenType text:(NSString *)tokenText 108{ 109 id<Token> newToken = [self createToken:tokenType text:tokenText]; 110 111 id newTree = [self create:newToken]; 112 [newToken release]; 113 return newTree; 114} 115 116- (id) copyNode:(id)aNode 117{ 118 return [aNode copyWithZone:nil]; // not -copy: to silence warnings 119} 120 121- (id) copyTree:(id)aTree 122{ 123 return [aTree deepCopy]; 124} 125 126 127- (void) addChild:(id)child toTree:(id)aTree 128{ 129 [aTree addChild:child]; 130} 131 132- (id) makeNode:(id)newRoot parentOf:(id)oldRoot 133{ 134 id 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 [TreeException 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 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) postProcessTree:(id)aTree 164{ 165 id 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)aNode 174{ 175 // TODO: is hash appropriate here? 176 return [aNode hash]; 177} 178 179 180#pragma mark Content 181 182- (NSInteger) tokenTypeForNode:(id)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)aNode 194{ 195 return [aNode getText]; 196} 197 198- (void) setText:(NSString *)tokenText forNode:(id)aNode 199{ 200 // currently unimplemented 201} 202 203 204#pragma mark Navigation / Tree Parsing 205 206- (id) childForNode:(id) aNode atIndex:(NSInteger) i 207{ 208 // currently unimplemented 209 return nil; 210} 211 212- (NSInteger) childCountForTree:(id) aTree 213{ 214 // currently unimplemented 215 return 0; 216} 217 218#pragma mark Subclass Responsibilties 219 220- (void) setBoundariesForTree:(id)aTree fromToken:(id<Token>)startToken toToken:(id<Token>)stopToken 221{ 222 // subclass responsibility 223} 224 225- (NSInteger) tokenStartIndexForTree:(id)aTree 226{ 227 // subclass responsibility 228 return 0; 229} 230 231- (NSInteger) tokenStopIndexForTree:(id)aTree 232{ 233 // subclass responsibility 234 return 0; 235} 236 237 238@end 239