Home | History | Annotate | Download | only in Framework
      1 //
      2 //  ANTLRTreeVisitor.m
      3 //  ANTLR
      4 //
      5 //  Created by Alan Condit on 6/18/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 "ANTLRTreeVisitor.h"
     33 #import "ANTLRCommonTreeAdaptor.h"
     34 
     35 @implementation ANTLRTreeVisitor
     36 
     37 + (ANTLRTreeVisitor *)newANTLRTreeVisitor:(id<ANTLRTreeAdaptor>)anAdaptor
     38 {
     39     return [[ANTLRTreeVisitor alloc] initWithAdaptor:anAdaptor];
     40 }
     41 
     42 + (ANTLRTreeVisitor *)newANTLRTreeVisitor
     43 {
     44     return [[ANTLRTreeVisitor alloc] init];
     45 }
     46 
     47 
     48 - (id)init
     49 {
     50     if ((self = [super init]) != nil) {
     51         adaptor = [[ANTLRCommonTreeAdaptor newTreeAdaptor] retain];
     52     }
     53     return self;
     54 }
     55 
     56 - (id)initWithAdaptor:(id<ANTLRTreeAdaptor>)anAdaptor
     57 {
     58     if ((self = [super init]) != nil) {
     59         adaptor = [anAdaptor retain];
     60     }
     61     return self;
     62 }
     63 
     64 - (void) dealloc
     65 {
     66 #ifdef DEBUG_DEALLOC
     67     NSLog( @"called dealloc in ANTLRTreeVisitor" );
     68 #endif
     69     if ( adaptor ) [adaptor release];
     70     [super dealloc];
     71 }
     72 
     73 /** Visit every node in tree t and trigger an action for each node
     74  *  before/after having visited all of its children.
     75  *  Execute both actions even if t has no children.
     76  *  If a child visit yields a new child, it can update its
     77  *  parent's child list or just return the new child.  The
     78  *  child update code works even if the child visit alters its parent
     79  *  and returns the new tree.
     80  *
     81  *  Return result of applying post action to this node.
     82  */
     83 - (ANTLRTreeVisitor *)visit:(ANTLRCommonTree *)t Action:(ANTLRTreeVisitorAction *)action
     84 {
     85     // System.out.println("visit "+((Tree)t).toStringTree());
     86     BOOL isNil = [adaptor isNil:t];
     87     if ( action != nil && !isNil ) {
     88         t = [action pre:(ANTLRTreeVisitorAction *)t]; // if rewritten, walk children of new t
     89     }
     90     for (int i=0; i < [adaptor getChildCount:t]; i++) {
     91         ANTLRCommonTree *child = [adaptor getChild:t At:i];
     92         ANTLRCommonTree *visitResult = [self visit:child Action:action];
     93         ANTLRCommonTree *childAfterVisit = [adaptor getChild:t At:i];
     94         if ( visitResult !=  childAfterVisit ) { // result & child differ?
     95             [adaptor setChild:t At:i Child:visitResult];
     96         }
     97     }
     98     if ( action != nil && !isNil ) t = [action post:(ANTLRTreeVisitorAction *)t];
     99     return t;
    100 }
    101 
    102 @synthesize adaptor;
    103 @end
    104