| // |
| // ANTLRTreeRewriter.m |
| // ANTLR |
| // |
| // Created by Alan Condit on 6/17/10. |
| // [The "BSD licence"] |
| // Copyright (c) 2010 Alan Condit |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions |
| // are met: |
| // 1. Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // 2. Redistributions in binary form must reproduce the above copyright |
| // notice, this list of conditions and the following disclaimer in the |
| // documentation and/or other materials provided with the distribution. |
| // 3. The name of the author may not be used to endorse or promote products |
| // derived from this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| #import "ANTLRTreeRewriter.h" |
| #import "ANTLRCommonTreeNodeStream.h" |
| #import "ANTLRTreeRuleReturnScope.h" |
| #import "ANTLRCommonTreeAdaptor.h" |
| #import "ANTLRTreeVisitor.h" |
| |
| @implementation ANTLRfptr |
| |
| + (ANTLRfptr *)newANTLRfptrWithRule:(SEL)aRuleAction withObject:(id)anObject |
| { |
| return [[ANTLRfptr alloc] initWithRule:aRuleAction withObject:(id)anObject]; |
| } |
| |
| -initWithRule:(SEL)aRuleAction withObject:(id)anObject |
| { |
| if ((self = [super init]) != nil) { |
| actor = anObject; |
| ruleSEL = aRuleAction; |
| } |
| return self; |
| } |
| |
| - (id)rule |
| { |
| if ( [actor respondsToSelector:ruleSEL] ) |
| return [actor performSelector:ruleSEL]; |
| else |
| @throw [ANTLRRuntimeException newException:@"Unknown Rewrite exception"]; |
| return nil; |
| } |
| |
| @synthesize actor; |
| @synthesize ruleSEL; |
| @end |
| |
| @implementation ANTLRTreeRewriter |
| |
| + (ANTLRTreeRewriter *) newANTLRTreeRewriter:(id<ANTLRTreeNodeStream>)anInput |
| { |
| return [[ANTLRTreeRewriter alloc] initWithStream:anInput State:[ANTLRRecognizerSharedState newANTLRRecognizerSharedState]]; |
| } |
| |
| + (ANTLRTreeRewriter *) newANTLRTreeRewriter:(id<ANTLRTreeNodeStream>)anInput State:(ANTLRRecognizerSharedState *)aState |
| { |
| return [[ANTLRTreeRewriter alloc] initWithStream:anInput State:aState]; |
| } |
| |
| - (id)initWithStream:(id<ANTLRTreeNodeStream>)anInput |
| { |
| SEL aRuleSel; |
| |
| if ((self = [super initWithStream:anInput]) != nil) { |
| showTransformations = NO; |
| state = [[ANTLRRecognizerSharedState newANTLRRecognizerSharedState] retain]; |
| originalAdaptor = [input getTreeAdaptor]; |
| if ( originalAdaptor ) [originalAdaptor retain]; |
| originalTokenStream = [input getTokenStream]; |
| if ( originalTokenStream ) [originalTokenStream retain]; |
| aRuleSel = @selector(topdown); |
| topdown_fptr = [ANTLRfptr newANTLRfptrWithRule:(SEL)aRuleSel withObject:self]; |
| aRuleSel = @selector(bottomup); |
| bottomup_ftpr = [ANTLRfptr newANTLRfptrWithRule:(SEL)aRuleSel withObject:self]; |
| } |
| return self; |
| } |
| |
| - (id)initWithStream:(id<ANTLRTreeNodeStream>)anInput State:(ANTLRRecognizerSharedState *)aState |
| { |
| SEL aRuleSel; |
| |
| if ((self = [super initWithStream:anInput]) != nil) { |
| showTransformations = NO; |
| state = aState; |
| if ( state ) [state retain]; |
| originalAdaptor = [input getTreeAdaptor]; |
| if ( originalAdaptor ) [originalAdaptor retain]; |
| originalTokenStream = [input getTokenStream]; |
| if ( originalTokenStream ) [originalTokenStream retain]; |
| aRuleSel = @selector(topdown); |
| topdown_fptr = [ANTLRfptr newANTLRfptrWithRule:(SEL)aRuleSel withObject:self]; |
| aRuleSel = @selector(bottomup); |
| bottomup_ftpr = [ANTLRfptr newANTLRfptrWithRule:(SEL)aRuleSel withObject:self]; |
| } |
| return self; |
| } |
| |
| - (void) dealloc |
| { |
| #ifdef DEBUG_DEALLOC |
| NSLog( @"called dealloc in ANTLRTreeRewriter" ); |
| #endif |
| if ( state ) [state release]; |
| if ( originalAdaptor ) [originalAdaptor release]; |
| if ( originalTokenStream ) [originalTokenStream release]; |
| [super dealloc]; |
| } |
| |
| - (id) applyOnce:(ANTLRCommonTree *)t Rule:(ANTLRfptr *)whichRule |
| { |
| if ( t == nil ) return nil; |
| @try { |
| // share TreeParser object but not parsing-related state |
| state = [ANTLRRecognizerSharedState newANTLRRecognizerSharedState]; |
| input = [ANTLRCommonTreeNodeStream newANTLRCommonTreeNodeStream:(ANTLRCommonTreeAdaptor *)originalAdaptor Tree:t]; |
| [(ANTLRCommonTreeNodeStream *)input setTokenStream:originalTokenStream]; |
| [self setBacktrackingLevel:1]; |
| ANTLRTreeRuleReturnScope *r = [(ANTLRfptr *)whichRule rule]; |
| [self setBacktrackingLevel:0]; |
| if ( [self getFailed] ) |
| return t; |
| if ( showTransformations && |
| r != nil && !(t == r.start) && r.start != nil ) { |
| [self reportTransformation:t Tree:r.start]; |
| } |
| if ( r != nil && r.start != nil ) |
| return r.start; |
| else |
| return t; |
| } |
| @catch (ANTLRRecognitionException *e) { |
| return t; |
| } |
| return t; |
| } |
| |
| - (id) applyRepeatedly:(ANTLRCommonTree *)t Rule:(ANTLRfptr *)whichRule |
| { |
| BOOL treeChanged = true; |
| while ( treeChanged ) { |
| ANTLRTreeRewriter *u = [self applyOnce:t Rule:whichRule]; |
| treeChanged = !(t == u); |
| t = u; |
| } |
| return t; |
| } |
| |
| - (id) downup:(ANTLRCommonTree *)t |
| { |
| return [self downup:t XForm:NO]; |
| } |
| |
| - (id) pre:(ANTLRCommonTree *)t |
| { |
| return [self applyOnce:t Rule:topdown_fptr]; |
| } |
| |
| - (id)post:(ANTLRCommonTree *)t |
| { |
| return [self applyRepeatedly:t Rule:bottomup_ftpr]; |
| } |
| |
| #ifdef DONTUSENOMO |
| public Object downup(Object t, boolean showTransformations) { |
| this.showTransformations = showTransformations; |
| TreeVisitor v = new TreeVisitor(new CommonTreeAdaptor()); |
| TreeVisitorAction actions = new TreeVisitorAction() { |
| public Object pre(Object t) { return applyOnce(t, topdown_fptr); } |
| public Object post(Object t) { return applyRepeatedly(t, bottomup_ftpr); } |
| }; |
| t = v.visit(t, actions); |
| return t; |
| } |
| #endif |
| |
| - (id) downup:(ANTLRCommonTree *)t XForm:(BOOL)aShowTransformations |
| { |
| showTransformations = aShowTransformations; |
| ANTLRTreeVisitor *v = [ANTLRTreeVisitor newANTLRTreeVisitor:[[originalAdaptor class] newTreeAdaptor]]; |
| ANTLRTreeVisitorAction *actions = [ANTLRTreeVisitorAction newANTLRTreeVisitorAction]; |
| { |
| //public Object pre(Object t) { return applyOnce(t, topdown_fptr); } |
| [self pre:t]; |
| //public Object post(Object t) { return applyRepeatedly(t, bottomup_ftpr); } |
| [self post:t]; |
| }; |
| t = [v visit:t Action:actions]; |
| return t; |
| } |
| |
| /** Override this if you need transformation tracing to go somewhere |
| * other than stdout or if you're not using Tree-derived trees. |
| */ |
| - (void)reportTransformation:(ANTLRCommonTree *)oldTree Tree:(ANTLRCommonTree *)newTree |
| { |
| //System.out.println(((Tree)oldTree).toStringTree()+" -> "+ ((Tree)newTree).toStringTree()); |
| } |
| |
| - (id)topdown_fptr |
| { |
| return [self topdown]; |
| } |
| |
| - (id)bottomup_ftpr |
| { |
| return [self bottomup]; |
| } |
| |
| // methods the downup strategy uses to do the up and down rules. |
| // to override, just define tree grammar rule topdown and turn on |
| // filter=true. |
| - (id) topdown |
| // @throws RecognitionException |
| { |
| @throw [ANTLRRecognitionException newException:@"TopDown exception"]; |
| return nil; |
| } |
| |
| - (id) bottomup |
| //@throws RecognitionException |
| { |
| @throw [ANTLRRecognitionException newException:@"BottomUp exception"]; |
| return nil; |
| } |
| |
| @synthesize showTransformations; |
| @synthesize originalTokenStream; |
| @synthesize originalAdaptor; |
| @synthesize rule; |
| @end |