1// 2// TreeRewriter.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 "TreeRewriter.h" 33#import "CommonTreeNodeStream.h" 34#import "TreeRuleReturnScope.h" 35#import "CommonTreeAdaptor.h" 36#import "TreeVisitor.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 [RuntimeException newException:@"Unknown Rewrite exception"]; 60 return nil; 61} 62 63@synthesize actor; 64@synthesize ruleSEL; 65@end 66 67@implementation TreeRewriter 68 69+ (TreeRewriter *) newTreeRewriter:(id<TreeNodeStream>)anInput 70{ 71 return [[TreeRewriter alloc] initWithStream:anInput State:[RecognizerSharedState newRecognizerSharedState]]; 72} 73 74+ (TreeRewriter *) newTreeRewriter:(id<TreeNodeStream>)anInput State:(RecognizerSharedState *)aState 75{ 76 return [[TreeRewriter alloc] initWithStream:anInput State:aState]; 77} 78 79- (id)initWithStream:(id<TreeNodeStream>)anInput 80{ 81 SEL aRuleSel; 82 83 if ((self = [super initWithStream:anInput]) != nil) { 84 showTransformations = NO; 85 state = [[RecognizerSharedState newRecognizerSharedState] 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<TreeNodeStream>)anInput State:(RecognizerSharedState *)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 TreeRewriter" ); 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:(CommonTree *)t Rule:(ANTLRfptr *)whichRule 130{ 131 if ( t == nil ) return nil; 132 @try { 133 // share TreeParser object but not parsing-related state 134 state = [RecognizerSharedState newRecognizerSharedState]; 135 input = [CommonTreeNodeStream newCommonTreeNodeStream:(CommonTreeAdaptor *)originalAdaptor Tree:t]; 136 [(CommonTreeNodeStream *)input setTokenStream:originalTokenStream]; 137 [self setBacktrackingLevel:1]; 138 TreeRuleReturnScope *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 (RecognitionException *e) { 152 return t; 153 } 154 return t; 155} 156 157- (id) applyRepeatedly:(CommonTree *)t Rule:(ANTLRfptr *)whichRule 158{ 159 BOOL treeChanged = true; 160 while ( treeChanged ) { 161 TreeRewriter *u = [self applyOnce:t Rule:whichRule]; 162 treeChanged = !(t == u); 163 t = u; 164 } 165 return t; 166} 167 168- (id) downup:(CommonTree *)t 169{ 170 return [self downup:t XForm:NO]; 171} 172 173- (id) pre:(CommonTree *)t 174{ 175 return [self applyOnce:t Rule:topdown_fptr]; 176} 177 178- (id)post:(CommonTree *)t 179{ 180 return [self applyRepeatedly:t Rule:bottomup_ftpr]; 181} 182 183#ifdef DONTUSENOMO 184public 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:(CommonTree *)t XForm:(BOOL)aShowTransformations 197{ 198 showTransformations = aShowTransformations; 199 TreeVisitor *v = [TreeVisitor newTreeVisitor:[[originalAdaptor class] newTreeAdaptor]]; 200 TreeVisitorAction *actions = [TreeVisitorAction newTreeVisitorAction]; 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:(CommonTree *)oldTree Tree:(CommonTree *)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 [RecognitionException newException:@"TopDown exception"]; 236 return nil; 237} 238 239- (id) bottomup 240//@throws RecognitionException 241{ 242 @throw [RecognitionException newException:@"BottomUp exception"]; 243 return nil; 244} 245 246@synthesize showTransformations; 247@synthesize originalTokenStream; 248@synthesize originalAdaptor; 249@synthesize rule; 250@end 251