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