Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 433 lines (361 sloc) 13.653 kB
05eedb5 @itod initial add
authored
1 // Copyright 2010 Todd Ditchendorf
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #import "EBNFParser.h"
16 #import "NSString+ParseKitAdditions.h"
17
18 /*
19 statement = exprOrAssignment ';'
20 exprOrAssignment = expression | assigment
21 assigment = declaration '=' expression
22 declaration = '$' Word
23 variable = '$' Word
24 expression = term orTerm*
25 term = factor nextFactor*
26 orTerm = '|' term
27 factor = phrase | phraseStar | phraseQuestion | phrasePlus
28 nextFactor = factor
29 phrase = atomicValue | '(' expression ')'
30 phraseStar = phrase '*'
31 phraseQuestion = phrase '?'
32 phrasePlus = phrase '+'
33 atomicValue = Word | Number | QuotedString | variable
34 */
35
36 static NSString * const kEBNFEqualsString = @"=";
37 static NSString * const kEBNFVariablePrefix = @"$";
38 static NSString * const kEBNFVariableSuffix = @"";
39
40 @interface PKParser (PKParserFactoryAdditionsFriend)
41 - (void)setTokenizer:(PKTokenizer *)t;
42 @end
43
44 @interface EBNFParser ()
45 - (void)addSymbolString:(NSString *)s toTokenizer:(PKTokenizer *)t;
46
253c2e0 @itod merging changes from google code
authored
47 - (void)parser:(PKParser *)p didMatchWord:(PKAssembly *)a;
48 - (void)parser:(PKParser *)p didMatchNum:(PKAssembly *)a;
49 - (void)parser:(PKParser *)p didMatchQuotedString:(PKAssembly *)a;
50 - (void)parser:(PKParser *)p didMatchStar:(PKAssembly *)a;
51 - (void)parser:(PKParser *)p didMatchQuestion:(PKAssembly *)a;
52 - (void)parser:(PKParser *)p didMatchPlus:(PKAssembly *)a;
53 - (void)parser:(PKParser *)p didMatchAnd:(PKAssembly *)a;
54 - (void)parser:(PKParser *)p didMatchOr:(PKAssembly *)a;
55 - (void)parser:(PKParser *)p didMatchAssignment:(PKAssembly *)a;
56 - (void)parser:(PKParser *)p didMatchVariable:(PKAssembly *)a;
05eedb5 @itod initial add
authored
57 @end
58
59 @implementation EBNFParser
60
61 - (id)init {
62 if ([super initWithSubparser:self.statementParser]) {
63 self.tokenizer = [PKTokenizer tokenizer];
64 [self addSymbolString:kEBNFEqualsString toTokenizer:self.tokenizer];
65 [self addSymbolString:kEBNFVariablePrefix toTokenizer:self.tokenizer];
66 [self addSymbolString:kEBNFVariableSuffix toTokenizer:self.tokenizer];
67 }
68 return self;
69 }
70
71
72 - (void)dealloc {
73 self.tokenizer = nil;
74 self.statementParser = nil;
75 self.exprOrAssignmentParser = nil;
76 self.assignmentParser = nil;
77 self.declarationParser = nil;
78 self.variableParser = nil;
79 self.expressionParser = nil;
80 self.termParser = nil;
81 self.orTermParser = nil;
82 self.factorParser = nil;
83 self.nextFactorParser = nil;
84 self.phraseParser = nil;
85 self.phraseStarParser = nil;
86 self.phraseQuestionParser = nil;
87 self.phrasePlusParser = nil;
88 self.atomicValueParser = nil;
89 [super dealloc];
90 }
91
92
93 - (id)parse:(NSString *)s {
94 self.tokenizer.string = s;
95 PKTokenAssembly *a = [PKTokenAssembly assemblyWithTokenizer:self.tokenizer];
96 PKAssembly *result = [self completeMatchFor:a];
97 return [result pop];
98 }
99
100
101 - (void)addSymbolString:(NSString *)s toTokenizer:(PKTokenizer *)t {
102 if ([s length]) {
eb778c5 @itod merging changes from Google Code SVN repo
authored
103 PKUniChar c = [s characterAtIndex:0];
05eedb5 @itod initial add
authored
104 [t setTokenizerState:t.symbolState from:c to:c];
105 [t.symbolState add:s];
106 }
107 }
108
109
110 // statement = exprOrAssignment ';'
111 - (PKCollectionParser *)statementParser {
112 if (!statementParser) {
113 self.statementParser = [PKTrack track];
114 [statementParser add:self.exprOrAssignmentParser];
115 [statementParser add:[[PKSymbol symbolWithString:@";"] discard]];
116 }
117 return statementParser;
118 }
119
120
121 // exprOrAssignmentParser = expression | assignment
122 - (PKCollectionParser *)exprOrAssignmentParser {
123 if (!exprOrAssignmentParser) {
124 self.exprOrAssignmentParser = [PKAlternation alternation];
125 [exprOrAssignmentParser add:self.expressionParser];
126 [exprOrAssignmentParser add:self.assignmentParser];
127 }
128 return exprOrAssignmentParser;
129 }
130
131
132 // declaration = variable '=' expression
133 - (PKCollectionParser *)assignmentParser {
134 if (!assignmentParser) {
135 self.assignmentParser = [PKTrack track];
136 [assignmentParser add:self.declarationParser];
137 [assignmentParser add:[[PKSymbol symbolWithString:kEBNFEqualsString] discard]];
138 [assignmentParser add:self.expressionParser];
253c2e0 @itod merging changes from google code
authored
139 [assignmentParser setAssembler:self selector:@selector(parser:didMatchAssignment:)];
05eedb5 @itod initial add
authored
140 }
141 return assignmentParser;
142 }
143
144
145 // declaration = '$' Word
146 - (PKCollectionParser *)declarationParser {
147 if (!declarationParser) {
148 self.declarationParser = [PKTrack track];
149 [declarationParser add:[[PKSymbol symbolWithString:kEBNFVariablePrefix] discard]];
150 [declarationParser add:[PKWord word]];
151 if ([kEBNFVariableSuffix length]) {
152 [declarationParser add:[[PKSymbol symbolWithString:kEBNFVariableSuffix] discard]];
153 }
154 }
155 return declarationParser;
156 }
157
158
159 // variable = '$' Word
160 - (PKCollectionParser *)variableParser {
161 if (!variableParser) {
162 self.variableParser = [PKTrack track];
163 [variableParser add:[[PKSymbol symbolWithString:kEBNFVariablePrefix] discard]];
164 [variableParser add:[PKWord word]];
165 if ([kEBNFVariableSuffix length]) {
166 [variableParser add:[[PKSymbol symbolWithString:kEBNFVariableSuffix] discard]];
167 }
168 }
169 return variableParser;
170 }
171
172
173 // expression = term orTerm*
174 - (PKCollectionParser *)expressionParser {
175 if (!expressionParser) {
176 self.expressionParser = [PKSequence sequence];
177 [expressionParser add:self.termParser];
178 [expressionParser add:[PKRepetition repetitionWithSubparser:self.orTermParser]];
179 }
180 return expressionParser;
181 }
182
183
184 // term = factor nextFactor*
185 - (PKCollectionParser *)termParser {
186 if (!termParser) {
187 self.termParser = [PKSequence sequence];
188 [termParser add:self.factorParser];
189 [termParser add:[PKRepetition repetitionWithSubparser:self.nextFactorParser]];
190 }
191 return termParser;
192 }
193
194
195 // orTerm = '|' term
196 - (PKCollectionParser *)orTermParser {
197 if (!orTermParser) {
198 self.orTermParser = [PKTrack track];
199 [orTermParser add:[[PKSymbol symbolWithString:@"|"] discard]];
200 [orTermParser add:self.termParser];
253c2e0 @itod merging changes from google code
authored
201 [orTermParser setAssembler:self selector:@selector(parser:didMatchOr:)];
05eedb5 @itod initial add
authored
202 }
203 return orTermParser;
204 }
205
206
207 // factor = phrase | phraseStar | phraseQuestion | phrasePlus
208 - (PKCollectionParser *)factorParser {
209 if (!factorParser) {
210 self.factorParser = [PKAlternation alternation];
211 [factorParser add:self.phraseParser];
212 [factorParser add:self.phraseStarParser];
213 [factorParser add:self.phraseQuestionParser];
214 [factorParser add:self.phrasePlusParser];
215 }
216 return factorParser;
217 }
218
219
220 // nextFactor = factor
221 - (PKCollectionParser *)nextFactorParser {
222 if (!nextFactorParser) {
223 self.nextFactorParser = [PKAlternation alternation];
224 [nextFactorParser add:self.phraseParser];
225 [nextFactorParser add:self.phraseStarParser];
226 [nextFactorParser add:self.phraseQuestionParser];
227 [nextFactorParser add:self.phrasePlusParser];
253c2e0 @itod merging changes from google code
authored
228 [nextFactorParser setAssembler:self selector:@selector(parser:didMatchAnd:)];
05eedb5 @itod initial add
authored
229 }
230 return nextFactorParser;
231 }
232
233
234 // phrase = atomicValue | '(' expression ')'
235 - (PKCollectionParser *)phraseParser {
236 if (!phraseParser) {
237 PKSequence *s = [PKTrack track];
238 [s add:[[PKSymbol symbolWithString:@"("] discard]];
239 [s add:self.expressionParser];
240 [s add:[[PKSymbol symbolWithString:@")"] discard]];
241
242 self.phraseParser = [PKAlternation alternation];
243 [phraseParser add:self.atomicValueParser];
244 [phraseParser add:s];
245 }
246 return phraseParser;
247 }
248
249
250 // phraseStar = phrase '*'
251 - (PKCollectionParser *)phraseStarParser {
252 if (!phraseStarParser) {
253 self.phraseStarParser = [PKSequence sequence];
254 [phraseStarParser add:self.phraseParser];
255 [phraseStarParser add:[[PKSymbol symbolWithString:@"*"] discard]];
253c2e0 @itod merging changes from google code
authored
256 [phraseStarParser setAssembler:self selector:@selector(parser:didMatchStar:)];
05eedb5 @itod initial add
authored
257 }
258 return phraseStarParser;
259 }
260
261
262 // phraseQuestion = phrase '?'
263 - (PKCollectionParser *)phraseQuestionParser {
264 if (!phraseQuestionParser) {
265 self.phraseQuestionParser = [PKSequence sequence];
266 [phraseQuestionParser add:self.phraseParser];
267 [phraseQuestionParser add:[[PKSymbol symbolWithString:@"?"] discard]];
253c2e0 @itod merging changes from google code
authored
268 [phraseQuestionParser setAssembler:self selector:@selector(parser:didMatchQuestion:)];
05eedb5 @itod initial add
authored
269 }
270 return phraseQuestionParser;
271 }
272
273
274 // phrasePlus = phrase '+'
275 - (PKCollectionParser *)phrasePlusParser {
276 if (!phrasePlusParser) {
277 self.phrasePlusParser = [PKSequence sequence];
278 [phrasePlusParser add:self.phraseParser];
279 [phrasePlusParser add:[[PKSymbol symbolWithString:@"+"] discard]];
253c2e0 @itod merging changes from google code
authored
280 [phrasePlusParser setAssembler:self selector:@selector(parser:didMatchPlus:)];
05eedb5 @itod initial add
authored
281 }
282 return phrasePlusParser;
283 }
284
285
286 // atomicValue = Word | Number | QuotedString | Variable
287 - (PKCollectionParser *)atomicValueParser {
288 if (!atomicValueParser) {
289 self.atomicValueParser = [PKAlternation alternation];
290
291 PKParser *p = [PKWord word];
253c2e0 @itod merging changes from google code
authored
292 [p setAssembler:self selector:@selector(parser:didMatchWord:)];
05eedb5 @itod initial add
authored
293 [atomicValueParser add:p];
294
295 p = [PKNumber number];
253c2e0 @itod merging changes from google code
authored
296 [p setAssembler:self selector:@selector(parser:didMatchNum:)];
05eedb5 @itod initial add
authored
297 [atomicValueParser add:p];
298
299 p = [PKQuotedString quotedString];
253c2e0 @itod merging changes from google code
authored
300 [p setAssembler:self selector:@selector(parser:didMatchQuotedString:)];
05eedb5 @itod initial add
authored
301 [atomicValueParser add:p];
302
303 p = self.variableParser;
253c2e0 @itod merging changes from google code
authored
304 [p setAssembler:self selector:@selector(parser:didMatchVariable:)];
05eedb5 @itod initial add
authored
305 [atomicValueParser add:p];
306 }
307 return atomicValueParser;
308 }
309
310
253c2e0 @itod merging changes from google code
authored
311 - (void)parser:(PKParser *)p didMatchWord:(PKAssembly *)a {
05eedb5 @itod initial add
authored
312 // NSLog(@"%s", _cmd);
313 // NSLog(@"a: %@", a);
314 PKToken *tok = [a pop];
315 [a push:[PKLiteral literalWithString:tok.stringValue]];
316 }
317
318
253c2e0 @itod merging changes from google code
authored
319 - (void)parser:(PKParser *)p didMatchNum:(PKAssembly *)a {
05eedb5 @itod initial add
authored
320 // NSLog(@"%s", _cmd);
321 // NSLog(@"a: %@", a);
322 PKToken *tok = [a pop];
323 [a push:[PKLiteral literalWithString:tok.stringValue]];
324 }
325
326
253c2e0 @itod merging changes from google code
authored
327 - (void)parser:(PKParser *)p didMatchQuotedString:(PKAssembly *)a {
05eedb5 @itod initial add
authored
328 // NSLog(@"%s", _cmd);
329 // NSLog(@"a: %@", a);
330 PKToken *tok = [a pop];
331 NSString *s = [tok.stringValue stringByTrimmingQuotes];
332
253c2e0 @itod merging changes from google code
authored
333 PKSequence *seq = [PKSequence sequence];
05eedb5 @itod initial add
authored
334 PKTokenizer *t = [PKTokenizer tokenizerWithString:s];
335 PKToken *eof = [PKToken EOFToken];
336 while (eof != (tok = [t nextToken])) {
253c2e0 @itod merging changes from google code
authored
337 [seq add:[PKLiteral literalWithString:tok.stringValue]];
05eedb5 @itod initial add
authored
338 }
339
253c2e0 @itod merging changes from google code
authored
340 [a push:seq];
05eedb5 @itod initial add
authored
341 }
342
343
253c2e0 @itod merging changes from google code
authored
344 - (void)parser:(PKParser *)p didMatchStar:(PKAssembly *)a {
05eedb5 @itod initial add
authored
345 // NSLog(@"%s", _cmd);
346 // NSLog(@"a: %@", a);
253c2e0 @itod merging changes from google code
authored
347 PKRepetition *rep = [PKRepetition repetitionWithSubparser:[a pop]];
348 [a push:rep];
05eedb5 @itod initial add
authored
349 }
350
351
253c2e0 @itod merging changes from google code
authored
352 - (void)parser:(PKParser *)p didMatchQuestion:(PKAssembly *)a {
05eedb5 @itod initial add
authored
353 // NSLog(@"%s", _cmd);
354 // NSLog(@"a: %@", a);
253c2e0 @itod merging changes from google code
authored
355 PKAlternation *alt = [PKAlternation alternation];
356 [alt add:[a pop]];
357 [alt add:[PKEmpty empty]];
358 [a push:alt];
05eedb5 @itod initial add
authored
359 }
360
361
253c2e0 @itod merging changes from google code
authored
362 - (void)parser:(PKParser *)p didMatchPlus:(PKAssembly *)a {
05eedb5 @itod initial add
authored
363 // NSLog(@"%s", _cmd);
364 // NSLog(@"a: %@", a);
365 id top = [a pop];
253c2e0 @itod merging changes from google code
authored
366 PKSequence *seq = [PKSequence sequence];
367 [seq add:top];
368 [seq add:[PKRepetition repetitionWithSubparser:top]];
369 [a push:seq];
05eedb5 @itod initial add
authored
370 }
371
372
253c2e0 @itod merging changes from google code
authored
373 - (void)parser:(PKParser *)p didMatchAnd:(PKAssembly *)a {
05eedb5 @itod initial add
authored
374 // NSLog(@"%s", _cmd);
375 // NSLog(@"a: %@", a);
376 id top = [a pop];
253c2e0 @itod merging changes from google code
authored
377 PKSequence *seq = [PKSequence sequence];
378 [seq add:[a pop]];
379 [seq add:top];
380 [a push:seq];
05eedb5 @itod initial add
authored
381 }
382
383
253c2e0 @itod merging changes from google code
authored
384 - (void)parser:(PKParser *)p didMatchOr:(PKAssembly *)a {
05eedb5 @itod initial add
authored
385 // NSLog(@"%s", _cmd);
386 // NSLog(@"a: %@", a);
387 id top = [a pop];
388 // NSLog(@"top: %@", top);
389 // NSLog(@"top class: %@", [top class]);
253c2e0 @itod merging changes from google code
authored
390 PKAlternation *alt = [PKAlternation alternation];
391 [alt add:[a pop]];
392 [alt add:top];
393 [a push:alt];
05eedb5 @itod initial add
authored
394 }
395
396
253c2e0 @itod merging changes from google code
authored
397 - (void)parser:(PKParser *)p didMatchAssignment:(PKAssembly *)a {
eb778c5 @itod merging changes from Google Code SVN repo
authored
398 NSLog(@"%s", __PRETTY_FUNCTION__);
05eedb5 @itod initial add
authored
399 NSLog(@"a: %@", a);
400 id val = [a pop];
401 PKToken *keyTok = [a pop];
402 NSMutableDictionary *table = [NSMutableDictionary dictionaryWithDictionary:a.target];
403 [table setObject:val forKey:keyTok.stringValue];
404 a.target = table;
405 }
406
407
253c2e0 @itod merging changes from google code
authored
408 - (void)parser:(PKParser *)p didMatchVariable:(PKAssembly *)a {
05eedb5 @itod initial add
authored
409 // NSLog(@"%s", _cmd);
410 // NSLog(@"a: %@", a);
411 PKToken *keyTok = [a pop];
412 id val = [a.target objectForKey:keyTok.stringValue];
413 if (val) {
414 [a push:val];
415 }
416 }
417
418 @synthesize statementParser;
419 @synthesize exprOrAssignmentParser;
420 @synthesize assignmentParser;
421 @synthesize declarationParser;
422 @synthesize variableParser;
423 @synthesize expressionParser;
424 @synthesize termParser;
425 @synthesize orTermParser;
426 @synthesize factorParser;
427 @synthesize nextFactorParser;
428 @synthesize phraseParser;
429 @synthesize phraseStarParser;
430 @synthesize phraseQuestionParser;
431 @synthesize phrasePlusParser;
432 @synthesize atomicValueParser;
433 @end
Something went wrong with that request. Please try again.