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