xref: /aosp_15_r20/external/antlr/runtime/ObjC/Framework/TreePatternParser.m (revision 16467b971bd3e2009fad32dd79016f2c7e421deb)
1*16467b97STreehugger Robot//
2*16467b97STreehugger Robot//  TreePatternParser.m
3*16467b97STreehugger Robot//  ANTLR
4*16467b97STreehugger Robot//
5*16467b97STreehugger Robot//  Created by Alan Condit on 6/18/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 "TreePatternParser.h"
33*16467b97STreehugger Robot#import "TreePatternLexer.h"
34*16467b97STreehugger Robot
35*16467b97STreehugger Robot@implementation TreePatternParser
36*16467b97STreehugger Robot
37*16467b97STreehugger Robot+ (TreePatternParser *)newTreePatternParser:(TreePatternLexer *)aTokenizer
38*16467b97STreehugger Robot                                               Wizard:(TreeWizard *)aWizard
39*16467b97STreehugger Robot                                              Adaptor:(id<TreeAdaptor>)anAdaptor
40*16467b97STreehugger Robot{
41*16467b97STreehugger Robot    return [[TreePatternParser alloc] initWithTokenizer:aTokenizer Wizard:aWizard Adaptor:anAdaptor];
42*16467b97STreehugger Robot}
43*16467b97STreehugger Robot
44*16467b97STreehugger Robot- (id) init
45*16467b97STreehugger Robot{
46*16467b97STreehugger Robot    if ((self = [super init]) != nil) {
47*16467b97STreehugger Robot        //tokenizer = aTokenizer;
48*16467b97STreehugger Robot        //wizard = aWizard;
49*16467b97STreehugger Robot        //adaptor = anAdaptor;
50*16467b97STreehugger Robot        //ttype = [tokenizer nextToken]; // kickstart
51*16467b97STreehugger Robot    }
52*16467b97STreehugger Robot    return self;
53*16467b97STreehugger Robot}
54*16467b97STreehugger Robot
55*16467b97STreehugger Robot- (id) initWithTokenizer:(TreePatternLexer *)aTokenizer
56*16467b97STreehugger Robot                  Wizard:(TreeWizard *)aWizard
57*16467b97STreehugger Robot                 Adaptor:(id<TreeAdaptor>)anAdaptor
58*16467b97STreehugger Robot{
59*16467b97STreehugger Robot    if ((self = [super init]) != nil) {
60*16467b97STreehugger Robot        adaptor = anAdaptor;
61*16467b97STreehugger Robot        if ( adaptor ) [adaptor retain];
62*16467b97STreehugger Robot        tokenizer = aTokenizer;
63*16467b97STreehugger Robot        if ( tokenizer ) [tokenizer retain];
64*16467b97STreehugger Robot        wizard = aWizard;
65*16467b97STreehugger Robot        if ( wizard ) [wizard retain];
66*16467b97STreehugger Robot        ttype = [aTokenizer nextToken]; // kickstart
67*16467b97STreehugger Robot    }
68*16467b97STreehugger Robot    return self;
69*16467b97STreehugger Robot}
70*16467b97STreehugger Robot
71*16467b97STreehugger Robot- (void) dealloc
72*16467b97STreehugger Robot{
73*16467b97STreehugger Robot#ifdef DEBUG_DEALLOC
74*16467b97STreehugger Robot    NSLog( @"called dealloc in TreePatternParser" );
75*16467b97STreehugger Robot#endif
76*16467b97STreehugger Robot	if ( adaptor ) [adaptor release];
77*16467b97STreehugger Robot	if ( tokenizer ) [tokenizer release];
78*16467b97STreehugger Robot	if ( wizard ) [wizard release];
79*16467b97STreehugger Robot	[super dealloc];
80*16467b97STreehugger Robot}
81*16467b97STreehugger Robot
82*16467b97STreehugger Robot- (id<BaseTree>)pattern
83*16467b97STreehugger Robot{
84*16467b97STreehugger Robot    if ( ttype==LexerTokenTypeBEGIN ) {
85*16467b97STreehugger Robot        return [self parseTree];
86*16467b97STreehugger Robot    }
87*16467b97STreehugger Robot    else if ( ttype==LexerTokenTypeID ) {
88*16467b97STreehugger Robot        id<BaseTree> node = [self parseNode];
89*16467b97STreehugger Robot        if ( ttype==LexerTokenTypeEOF ) {
90*16467b97STreehugger Robot            return node;
91*16467b97STreehugger Robot        }
92*16467b97STreehugger Robot        return nil; // extra junk on end
93*16467b97STreehugger Robot    }
94*16467b97STreehugger Robot    return nil;
95*16467b97STreehugger Robot}
96*16467b97STreehugger Robot
97*16467b97STreehugger Robot- (id<BaseTree>) parseTree
98*16467b97STreehugger Robot{
99*16467b97STreehugger Robot    if ( ttype != LexerTokenTypeBEGIN ) {
100*16467b97STreehugger Robot        @throw [RuntimeException newException:@"no BEGIN"];
101*16467b97STreehugger Robot    }
102*16467b97STreehugger Robot    ttype = [tokenizer nextToken];
103*16467b97STreehugger Robot    id<BaseTree> root = [self parseNode];
104*16467b97STreehugger Robot    if ( root==nil ) {
105*16467b97STreehugger Robot        return nil;
106*16467b97STreehugger Robot    }
107*16467b97STreehugger Robot    while ( ttype==LexerTokenTypeBEGIN  ||
108*16467b97STreehugger Robot           ttype==LexerTokenTypeID      ||
109*16467b97STreehugger Robot           ttype==LexerTokenTypePERCENT ||
110*16467b97STreehugger Robot           ttype==LexerTokenTypeDOT )
111*16467b97STreehugger Robot    {
112*16467b97STreehugger Robot        if ( ttype==LexerTokenTypeBEGIN ) {
113*16467b97STreehugger Robot            id<BaseTree> subtree = [self parseTree];
114*16467b97STreehugger Robot            [adaptor addChild:subtree toTree:root];
115*16467b97STreehugger Robot        }
116*16467b97STreehugger Robot        else {
117*16467b97STreehugger Robot            id<BaseTree> child = [self parseNode];
118*16467b97STreehugger Robot            if ( child == nil ) {
119*16467b97STreehugger Robot                return nil;
120*16467b97STreehugger Robot            }
121*16467b97STreehugger Robot            [adaptor addChild:child toTree:root];
122*16467b97STreehugger Robot        }
123*16467b97STreehugger Robot    }
124*16467b97STreehugger Robot    if ( ttype != LexerTokenTypeEND ) {
125*16467b97STreehugger Robot        @throw [RuntimeException newException:@"no END"];
126*16467b97STreehugger Robot    }
127*16467b97STreehugger Robot    ttype = [tokenizer nextToken];
128*16467b97STreehugger Robot    return root;
129*16467b97STreehugger Robot}
130*16467b97STreehugger Robot
131*16467b97STreehugger Robot- (id<BaseTree>) parseNode
132*16467b97STreehugger Robot{
133*16467b97STreehugger Robot    // "%label:" prefix
134*16467b97STreehugger Robot    NSString *label = nil;
135*16467b97STreehugger Robot    TreePattern *node;
136*16467b97STreehugger Robot    if ( ttype == LexerTokenTypePERCENT ) {
137*16467b97STreehugger Robot        ttype = [tokenizer nextToken];
138*16467b97STreehugger Robot        if ( ttype != LexerTokenTypeID ) {
139*16467b97STreehugger Robot            return nil;
140*16467b97STreehugger Robot        }
141*16467b97STreehugger Robot        label = [tokenizer toString];
142*16467b97STreehugger Robot        ttype = [tokenizer nextToken];
143*16467b97STreehugger Robot        if ( ttype != LexerTokenTypeCOLON ) {
144*16467b97STreehugger Robot            return nil;
145*16467b97STreehugger Robot        }
146*16467b97STreehugger Robot        ttype = [tokenizer nextToken]; // move to ID following colon
147*16467b97STreehugger Robot    }
148*16467b97STreehugger Robot
149*16467b97STreehugger Robot    // Wildcard?
150*16467b97STreehugger Robot    if ( ttype == LexerTokenTypeDOT ) {
151*16467b97STreehugger Robot        ttype = [tokenizer nextToken];
152*16467b97STreehugger Robot        id<Token> wildcardPayload = [CommonToken newToken:0 Text:@"."];
153*16467b97STreehugger Robot        node = [ANTLRWildcardTreePattern newANTLRWildcardTreePattern:wildcardPayload];
154*16467b97STreehugger Robot        if ( label != nil ) {
155*16467b97STreehugger Robot            node.label = label;
156*16467b97STreehugger Robot        }
157*16467b97STreehugger Robot        return node;
158*16467b97STreehugger Robot    }
159*16467b97STreehugger Robot
160*16467b97STreehugger Robot    // "ID" or "ID[arg]"
161*16467b97STreehugger Robot    if ( ttype != LexerTokenTypeID ) {
162*16467b97STreehugger Robot        return nil;
163*16467b97STreehugger Robot    }
164*16467b97STreehugger Robot    NSString *tokenName = [tokenizer toString];
165*16467b97STreehugger Robot    ttype = [tokenizer nextToken];
166*16467b97STreehugger Robot    if ( [tokenName isEqualToString:@"nil"] ) {
167*16467b97STreehugger Robot        return [adaptor emptyNode];
168*16467b97STreehugger Robot    }
169*16467b97STreehugger Robot    NSString *text = tokenName;
170*16467b97STreehugger Robot    // check for arg
171*16467b97STreehugger Robot    NSString *arg = nil;
172*16467b97STreehugger Robot    if ( ttype == LexerTokenTypeARG ) {
173*16467b97STreehugger Robot        arg = [tokenizer toString];
174*16467b97STreehugger Robot        text = arg;
175*16467b97STreehugger Robot        ttype = [tokenizer nextToken];
176*16467b97STreehugger Robot    }
177*16467b97STreehugger Robot
178*16467b97STreehugger Robot    // create node
179*16467b97STreehugger Robot    int treeNodeType = [wizard getTokenType:tokenName];
180*16467b97STreehugger Robot    if ( treeNodeType==TokenTypeInvalid ) {
181*16467b97STreehugger Robot        return nil;
182*16467b97STreehugger Robot    }
183*16467b97STreehugger Robot    node = [adaptor createTree:treeNodeType Text:text];
184*16467b97STreehugger Robot    if ( label!=nil && [node class] == [TreePattern class] ) {
185*16467b97STreehugger Robot        ((TreePattern *)node).label = label;
186*16467b97STreehugger Robot    }
187*16467b97STreehugger Robot    if ( arg!=nil && [node class] == [TreePattern class] ) {
188*16467b97STreehugger Robot        ((TreePattern *)node).hasTextArg = YES;
189*16467b97STreehugger Robot    }
190*16467b97STreehugger Robot    return node;
191*16467b97STreehugger Robot}
192*16467b97STreehugger Robot
193*16467b97STreehugger Robot@synthesize tokenizer;
194*16467b97STreehugger Robot@synthesize ttype;
195*16467b97STreehugger Robot@synthesize wizard;
196*16467b97STreehugger Robot@synthesize adaptor;
197*16467b97STreehugger Robot@end
198