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