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