1 // 2 // ANTLRTreeRewriter.m 3 // ANTLR 4 // 5 // Created by Alan Condit on 6/17/10. 6 // [The "BSD licence"] 7 // Copyright (c) 2010 Alan Condit 8 // All rights reserved. 9 // 10 // Redistribution and use in source and binary forms, with or without 11 // modification, are permitted provided that the following conditions 12 // are met: 13 // 1. Redistributions of source code must retain the above copyright 14 // notice, this list of conditions and the following disclaimer. 15 // 2. Redistributions in binary form must reproduce the above copyright 16 // notice, this list of conditions and the following disclaimer in the 17 // documentation and/or other materials provided with the distribution. 18 // 3. The name of the author may not be used to endorse or promote products 19 // derived from this software without specific prior written permission. 20 // 21 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 32 #import "ANTLRTreeRewriter.h" 33 #import "ANTLRCommonTreeNodeStream.h" 34 #import "ANTLRTreeRuleReturnScope.h" 35 #import "ANTLRCommonTreeAdaptor.h" 36 #import "ANTLRTreeVisitor.h" 37 38 @implementation ANTLRfptr 39 40 + (ANTLRfptr *)newANTLRfptrWithRule:(SEL)aRuleAction withObject:(id)anObject 41 { 42 return [[ANTLRfptr alloc] initWithRule:aRuleAction withObject:(id)anObject]; 43 } 44 45 -initWithRule:(SEL)aRuleAction withObject:(id)anObject 46 { 47 if ((self = [super init]) != nil) { 48 actor = anObject; 49 ruleSEL = aRuleAction; 50 } 51 return self; 52 } 53 54 - (id)rule 55 { 56 if ( [actor respondsToSelector:ruleSEL] ) 57 return [actor performSelector:ruleSEL]; 58 else 59 @throw [ANTLRRuntimeException newException:@"Unknown Rewrite exception"]; 60 return nil; 61 } 62 63 @synthesize actor; 64 @synthesize ruleSEL; 65 @end 66 67 @implementation ANTLRTreeRewriter 68 69 + (ANTLRTreeRewriter *) newANTLRTreeRewriter:(id<ANTLRTreeNodeStream>)anInput 70 { 71 return [[ANTLRTreeRewriter alloc] initWithStream:anInput State:[ANTLRRecognizerSharedState newANTLRRecognizerSharedState]]; 72 } 73 74 + (ANTLRTreeRewriter *) newANTLRTreeRewriter:(id<ANTLRTreeNodeStream>)anInput State:(ANTLRRecognizerSharedState *)aState 75 { 76 return [[ANTLRTreeRewriter alloc] initWithStream:anInput State:aState]; 77 } 78 79 - (id)initWithStream:(id<ANTLRTreeNodeStream>)anInput 80 { 81 SEL aRuleSel; 82 83 if ((self = [super initWithStream:anInput]) != nil) { 84 showTransformations = NO; 85 state = [[ANTLRRecognizerSharedState newANTLRRecognizerSharedState] retain]; 86 originalAdaptor = [input getTreeAdaptor]; 87 if ( originalAdaptor ) [originalAdaptor retain]; 88 originalTokenStream = [input getTokenStream]; 89 if ( originalTokenStream ) [originalTokenStream retain]; 90 aRuleSel = @selector(topdown); 91 topdown_fptr = [ANTLRfptr newANTLRfptrWithRule:(SEL)aRuleSel withObject:self]; 92 aRuleSel = @selector(bottomup); 93 bottomup_ftpr = [ANTLRfptr newANTLRfptrWithRule:(SEL)aRuleSel withObject:self]; 94 } 95 return self; 96 } 97 98 - (id)initWithStream:(id<ANTLRTreeNodeStream>)anInput State:(ANTLRRecognizerSharedState *)aState 99 { 100 SEL aRuleSel; 101 102 if ((self = [super initWithStream:anInput]) != nil) { 103 showTransformations = NO; 104 state = aState; 105 if ( state ) [state retain]; 106 originalAdaptor = [input getTreeAdaptor]; 107 if ( originalAdaptor ) [originalAdaptor retain]; 108 originalTokenStream = [input getTokenStream]; 109 if ( originalTokenStream ) [originalTokenStream retain]; 110 aRuleSel = @selector(topdown); 111 topdown_fptr = [ANTLRfptr newANTLRfptrWithRule:(SEL)aRuleSel withObject:self]; 112 aRuleSel = @selector(bottomup); 113 bottomup_ftpr = [ANTLRfptr newANTLRfptrWithRule:(SEL)aRuleSel withObject:self]; 114 } 115 return self; 116 } 117 118 - (void) dealloc 119 { 120 #ifdef DEBUG_DEALLOC 121 NSLog( @"called dealloc in ANTLRTreeRewriter" ); 122 #endif 123 if ( state ) [state release]; 124 if ( originalAdaptor ) [originalAdaptor release]; 125 if ( originalTokenStream ) [originalTokenStream release]; 126 [super dealloc]; 127 } 128 129 - (id) applyOnce:(ANTLRCommonTree *)t Rule:(ANTLRfptr *)whichRule 130 { 131 if ( t == nil ) return nil; 132 @try { 133 // share TreeParser object but not parsing-related state 134 state = [ANTLRRecognizerSharedState newANTLRRecognizerSharedState]; 135 input = [ANTLRCommonTreeNodeStream newANTLRCommonTreeNodeStream:(ANTLRCommonTreeAdaptor *)originalAdaptor Tree:t]; 136 [(ANTLRCommonTreeNodeStream *)input setTokenStream:originalTokenStream]; 137 [self setBacktrackingLevel:1]; 138 ANTLRTreeRuleReturnScope *r = [(ANTLRfptr *)whichRule rule]; 139 [self setBacktrackingLevel:0]; 140 if ( [self getFailed] ) 141 return t; 142 if ( showTransformations && 143 r != nil && !(t == r.start) && r.start != nil ) { 144 [self reportTransformation:t Tree:r.start]; 145 } 146 if ( r != nil && r.start != nil ) 147 return r.start; 148 else 149 return t; 150 } 151 @catch (ANTLRRecognitionException *e) { 152 return t; 153 } 154 return t; 155 } 156 157 - (id) applyRepeatedly:(ANTLRCommonTree *)t Rule:(ANTLRfptr *)whichRule 158 { 159 BOOL treeChanged = true; 160 while ( treeChanged ) { 161 ANTLRTreeRewriter *u = [self applyOnce:t Rule:whichRule]; 162 treeChanged = !(t == u); 163 t = u; 164 } 165 return t; 166 } 167 168 - (id) downup:(ANTLRCommonTree *)t 169 { 170 return [self downup:t XForm:NO]; 171 } 172 173 - (id) pre:(ANTLRCommonTree *)t 174 { 175 return [self applyOnce:t Rule:topdown_fptr]; 176 } 177 178 - (id)post:(ANTLRCommonTree *)t 179 { 180 return [self applyRepeatedly:t Rule:bottomup_ftpr]; 181 } 182 183 #ifdef DONTUSENOMO 184 public Object downup(Object t, boolean showTransformations) { 185 this.showTransformations = showTransformations; 186 TreeVisitor v = new TreeVisitor(new CommonTreeAdaptor()); 187 TreeVisitorAction actions = new TreeVisitorAction() { 188 public Object pre(Object t) { return applyOnce(t, topdown_fptr); } 189 public Object post(Object t) { return applyRepeatedly(t, bottomup_ftpr); } 190 }; 191 t = v.visit(t, actions); 192 return t; 193 } 194 #endif 195 196 - (id) downup:(ANTLRCommonTree *)t XForm:(BOOL)aShowTransformations 197 { 198 showTransformations = aShowTransformations; 199 ANTLRTreeVisitor *v = [ANTLRTreeVisitor newANTLRTreeVisitor:[[originalAdaptor class] newTreeAdaptor]]; 200 ANTLRTreeVisitorAction *actions = [ANTLRTreeVisitorAction newANTLRTreeVisitorAction]; 201 { 202 //public Object pre(Object t) { return applyOnce(t, topdown_fptr); } 203 [self pre:t]; 204 //public Object post(Object t) { return applyRepeatedly(t, bottomup_ftpr); } 205 [self post:t]; 206 }; 207 t = [v visit:t Action:actions]; 208 return t; 209 } 210 211 /** Override this if you need transformation tracing to go somewhere 212 * other than stdout or if you're not using Tree-derived trees. 213 */ 214 - (void)reportTransformation:(ANTLRCommonTree *)oldTree Tree:(ANTLRCommonTree *)newTree 215 { 216 //System.out.println(((Tree)oldTree).toStringTree()+" -> "+ ((Tree)newTree).toStringTree()); 217 } 218 219 - (id)topdown_fptr 220 { 221 return [self topdown]; 222 } 223 224 - (id)bottomup_ftpr 225 { 226 return [self bottomup]; 227 } 228 229 // methods the downup strategy uses to do the up and down rules. 230 // to override, just define tree grammar rule topdown and turn on 231 // filter=true. 232 - (id) topdown 233 // @throws RecognitionException 234 { 235 @throw [ANTLRRecognitionException newException:@"TopDown exception"]; 236 return nil; 237 } 238 239 - (id) bottomup 240 //@throws RecognitionException 241 { 242 @throw [ANTLRRecognitionException newException:@"BottomUp exception"]; 243 return nil; 244 } 245 246 @synthesize showTransformations; 247 @synthesize originalTokenStream; 248 @synthesize originalAdaptor; 249 @synthesize rule; 250 @end 251