1//
2//  TreePatternLexer.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 "TreePatternLexer.h"
33
34@implementation TreePatternLexer
35
36@synthesize pattern;
37@synthesize p;
38@synthesize c;
39@synthesize n;
40@synthesize sval;
41@synthesize data;
42@synthesize error;
43
44+ (TreePatternLexer *)newTreePatternLexer:(NSString *)aPattern
45{
46    return [[TreePatternLexer alloc] initWithPattern:aPattern];
47}
48
49- (id) init
50{
51    if ((self = [super init]) != nil ) {
52        p = -1;
53        n = 0;
54        error = NO;
55        sval = [[NSMutableData dataWithLength:1000] retain];
56        data = [sval mutableBytes];
57        pattern = @"";
58        n = [pattern length];
59        if ( pattern ) [pattern retain];
60        [self consume];
61    }
62    return self;
63}
64
65- (id) initWithPattern:(NSString *)aPattern
66{
67    if ((self = [super init]) != nil ) {
68        p = -1;
69        n = 0;
70        error = NO;
71        sval = [[NSMutableData dataWithLength:1000] retain];
72        data = [sval mutableBytes];
73        pattern = [aPattern retain];
74        n = [pattern length];
75        [self consume];
76    }
77    return self;
78}
79
80- (void) dealloc
81{
82#ifdef DEBUG_DEALLOC
83    NSLog( @"called dealloc in TreePatternLexer" );
84#endif
85	if ( pattern ) [pattern release];
86	if ( sval ) [sval release];
87	[super dealloc];
88}
89
90- (NSInteger) nextToken
91{
92    n = 0; // reset, but reuse buffer
93    while ( c != LexerTokenTypeEOF ) {
94        if ( c==' ' || c=='\n' || c=='\r' || c=='\t' ) {
95            [self consume];
96            continue;
97        }
98        if ( (c>='a' && c<='z') || (c>='A' && c<='Z') || c=='_' ) {
99            data[n++] = (char)c;
100            [self consume];
101            while ( (c>='a' && c<='z') || (c>='A' && c<='Z') ||
102                   (c>='0' && c<='9') || c=='_' )
103            {
104                data[n++] = (char)c;
105                [self consume];
106            }
107            return LexerTokenTypeID;
108        }
109        if ( c == '(' ) {
110            [self consume];
111            return LexerTokenTypeBEGIN;
112        }
113        if ( c==')' ) {
114            [self consume];
115            return LexerTokenTypeEND;
116        }
117        if ( c=='%' ) {
118            [self consume];
119            return LexerTokenTypePERCENT;
120        }
121        if ( c==':' ) {
122            [self consume];
123            return LexerTokenTypeCOLON;
124        }
125        if ( c=='.' ) {
126            [self consume];
127            return LexerTokenTypeDOT;
128        }
129        if ( c=='[' ) { // grab [x] as a string, returning x
130            [self consume];
131            while ( c!=']' ) {
132                if ( c=='\\' ) {
133                    [self consume];
134                    if ( c!=']' ) {
135                        data[n++] = (char)'\\';
136                    }
137                    data[n++] = (char)c;
138                }
139                else {
140                    data[n++] = (char)c;
141                }
142                [self consume];
143            }
144            [self consume];
145            return LexerTokenTypeARG;
146        }
147        [self consume];
148        error = true;
149        return LexerTokenTypeEOF;
150    }
151    return LexerTokenTypeEOF;
152}
153
154- (void) consume
155{
156    p++;
157    if ( p >= n ) {
158        c = LexerTokenTypeEOF;
159    }
160    else {
161        c = [pattern characterAtIndex:p];
162    }
163}
164
165- (NSString *)toString
166{
167    char buf[100];
168
169    NSInteger idx = 0;
170    for( NSInteger i = p; i < n; i++ ){
171        buf[idx++] = data[i];
172    }
173    buf[idx] = '\0';
174    return [NSString stringWithFormat:@"%s", buf];
175}
176
177- (NSMutableData *)getSval
178{
179    return sval;
180}
181
182- (void)setSval:(NSMutableData *)aSval
183{
184    if ( sval != aSval ) {
185        if ( sval ) [sval release];
186        [aSval retain];
187    }
188    sval = aSval;
189}
190
191@end
192