Home | History | Annotate | Download | only in Framework
      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