1//
2//  ANTLRTreePatternParser.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 "ANTLRTreePatternParser.h"
33#import "ANTLRTreePatternLexer.h"
34
35@implementation ANTLRTreePatternParser
36
37+ (ANTLRTreePatternParser *)newANTLRTreePatternParser:(ANTLRTreePatternLexer *)aTokenizer
38                                               Wizard:(ANTLRTreeWizard *)aWizard
39                                              Adaptor:(id<ANTLRTreeAdaptor>)anAdaptor
40{
41    return [[ANTLRTreePatternParser 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:(ANTLRTreePatternLexer *)aTokenizer
56                  Wizard:(ANTLRTreeWizard *)aWizard
57                 Adaptor:(id<ANTLRTreeAdaptor>)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 ANTLRTreePatternParser" );
75#endif
76	if ( adaptor ) [adaptor release];
77	if ( tokenizer ) [tokenizer release];
78	if ( wizard ) [wizard release];
79	[super dealloc];
80}
81
82- (id<ANTLRBaseTree>)pattern
83{
84    if ( ttype==ANTLRLexerTokenTypeBEGIN ) {
85        return [self parseTree];
86    }
87    else if ( ttype==ANTLRLexerTokenTypeID ) {
88        id<ANTLRBaseTree> node = [self parseNode];
89        if ( ttype==ANTLRLexerTokenTypeEOF ) {
90            return node;
91        }
92        return nil; // extra junk on end
93    }
94    return nil;
95}
96
97- (id<ANTLRBaseTree>) parseTree
98{
99    if ( ttype != ANTLRLexerTokenTypeBEGIN ) {
100        @throw [ANTLRRuntimeException newException:@"no BEGIN"];
101    }
102    ttype = [tokenizer nextToken];
103    id<ANTLRBaseTree> root = [self parseNode];
104    if ( root==nil ) {
105        return nil;
106    }
107    while ( ttype==ANTLRLexerTokenTypeBEGIN  ||
108           ttype==ANTLRLexerTokenTypeID      ||
109           ttype==ANTLRLexerTokenTypePERCENT ||
110           ttype==ANTLRLexerTokenTypeDOT )
111    {
112        if ( ttype==ANTLRLexerTokenTypeBEGIN ) {
113            id<ANTLRBaseTree> subtree = [self parseTree];
114            [adaptor addChild:subtree toTree:root];
115        }
116        else {
117            id<ANTLRBaseTree> child = [self parseNode];
118            if ( child == nil ) {
119                return nil;
120            }
121            [adaptor addChild:child toTree:root];
122        }
123    }
124    if ( ttype != ANTLRLexerTokenTypeEND ) {
125        @throw [ANTLRRuntimeException newException:@"no END"];
126    }
127    ttype = [tokenizer nextToken];
128    return root;
129}
130
131- (id<ANTLRBaseTree>) parseNode
132{
133    // "%label:" prefix
134    NSString *label = nil;
135    ANTLRTreePattern *node;
136    if ( ttype == ANTLRLexerTokenTypePERCENT ) {
137        ttype = [tokenizer nextToken];
138        if ( ttype != ANTLRLexerTokenTypeID ) {
139            return nil;
140        }
141        label = [tokenizer toString];
142        ttype = [tokenizer nextToken];
143        if ( ttype != ANTLRLexerTokenTypeCOLON ) {
144            return nil;
145        }
146        ttype = [tokenizer nextToken]; // move to ID following colon
147    }
148    
149    // Wildcard?
150    if ( ttype == ANTLRLexerTokenTypeDOT ) {
151        ttype = [tokenizer nextToken];
152        id<ANTLRToken> wildcardPayload = [ANTLRCommonToken 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 != ANTLRLexerTokenTypeID ) {
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 == ANTLRLexerTokenTypeARG ) {
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==ANTLRTokenTypeInvalid ) {
181        return nil;
182    }
183    node = [adaptor createTree:treeNodeType Text:text];
184    if ( label!=nil && [node class] == [ANTLRTreePattern class] ) {
185        ((ANTLRTreePattern *)node).label = label;
186    }
187    if ( arg!=nil && [node class] == [ANTLRTreePattern class] ) {
188        ((ANTLRTreePattern *)node).hasTextArg = YES;
189    }
190    return node;
191}
192
193@synthesize tokenizer;
194@synthesize ttype;
195@synthesize wizard;
196@synthesize adaptor;
197@end
198