rparsec 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,17 +1,20 @@
1
- # require 'rparsec/parser_impls'
2
- class ParserMonad
3
- def fail msg
4
- FailureParser.new(msg)
5
- end
6
- def value v
7
- return Nil if v.nil?
8
- ValueParser.new(v);
9
- end
10
- def bind(v, &proc)
11
- return v unless proc
12
- BoundParser.new(v, proc);
13
- end
14
- def mplus(p1, p2)
15
- PlusParser.new([p1,p2]);
16
- end
1
+ # require 'rparsec/parser_impls'
2
+ class ParserMonad
3
+ def fail msg
4
+ FailureParser.new(msg)
5
+ end
6
+
7
+ def value v
8
+ return Nil if v.nil?
9
+ ValueParser.new(v);
10
+ end
11
+
12
+ def bind(v, &proc)
13
+ return v unless proc
14
+ BoundParser.new(v, proc);
15
+ end
16
+
17
+ def mplus(p1, p2)
18
+ PlusParser.new([p1,p2]);
19
+ end
17
20
  end
@@ -1,604 +1,615 @@
1
- require 'rparsec/parser'
2
-
3
- class FailureParser < Parser
4
- init :msg
5
- def _parse ctxt
6
- return ctxt.failure(@msg)
7
- end
8
- end
9
-
10
- class ValueParser < Parser
11
- init :value
12
- def _parse ctxt
13
- ctxt.retn @value
14
- end
15
- end
16
-
17
- class LazyParser < Parser
18
- init :block
19
- def _parse ctxt
20
- @block.call._parse ctxt
21
- end
22
- end
23
-
24
- def add_error(err, e)
25
- return e if err.nil?
26
- return err if e.nil?
27
- cmp = compare_error(err, e)
28
- return err if cmp > 0
29
- return e if cmp < 0
30
- err
31
- # merge_error(err, e)
32
- end
33
- def get_first_element(err)
34
- while err.kind_of?(Array)
35
- err = err[0]
36
- end
37
- err
38
- end
39
-
40
- def compare_error(e1, e2)
41
- e1, e2 = get_first_element(e1), get_first_element(e2)
42
- return -1 if e1.index < e2.index
43
- return 1 if e1.index > e2.index
44
- 0
45
- end
46
- ###############################################
47
- #def merge_error(e1, e2)
48
- # return e1 << e2 if e1.kind_of?(Array)
49
- # [e1,e2]
50
- #end
51
- ###############################################
52
- class ThrowParser < Parser
53
- init :symbol
54
- def _parse ctxt
55
- throw @symbol
56
- end
57
- end
58
- class CatchParser < Parser
59
- init :symbol, :parser
60
- def _parse ctxt
61
- interrupted = true
62
- ok = false
63
- catch @symbol do
64
- ok = @parser._parse(ctxt)
65
- interrupted = false
66
- end
67
- return ctxt.retn(@symbol) if interrupted
68
- ok
69
- end
70
- end
71
-
72
- class PeekParser < Parser
73
- init :parser
74
- def _parse ctxt
75
- ind = ctxt.index
76
- return false unless @parser._parse ctxt
77
- ctxt.index = ind
78
- return true
79
- end
80
- def peek
81
- self
82
- end
83
- end
84
-
85
- class AtomParser < Parser
86
- init :parser
87
- def _parse ctxt
88
- ind = ctxt.index
89
- return true if @parser._parse ctxt
90
- ctxt.index = ind
91
- return false
92
- end
93
- def atomize
94
- self
95
- end
96
- end
97
-
98
- class LookAheadSensitiveParser < Parser
99
- def initialize(la=1)
100
- super()
101
- @lookahead = la
102
- end
103
- def visible(ctxt, n)
104
- ctxt.index - n < @lookahead
105
- end
106
- def lookahead(n)
107
- raise ArgumentError, "lookahead number #{n} should be positive" unless n>0
108
- return self if n == @lookahead
109
- withLookahead(n)
110
- end
111
- def not(msg="#{self} unexpected")
112
- NotParser.new(self, msg, @lookahead)
113
- end
114
- end
115
-
116
-
117
- class NotParser < LookAheadSensitiveParser
118
- def initialize(parser, msg, la=1)
119
- super(la)
120
- @parser, @msg, @name = parser, msg, "~#{parser.name}"
121
- end
122
- def _parse ctxt
123
- ind = ctxt.index
124
- if @parser._parse ctxt
125
- ctxt.index = ind
126
- return ctxt.expecting(@msg)
127
- end
128
- return ctxt.retn(nil) if visible(ctxt, ind)
129
- return false
130
- end
131
- def withLookahead(n)
132
- NotParser.new(@parser, @msg, n)
133
- end
134
- def not()
135
- @parser
136
- end
137
- end
138
-
139
- class ExpectParser < Parser
140
- def initialize(parser, msg)
141
- super()
142
- @parser, @msg, @name = parser, msg, msg
143
- end
144
- def _parse ctxt
145
- ind = ctxt.index
146
- return true if @parser._parse ctxt
147
- return false unless ind == ctxt.index
148
- ctxt.expecting(@msg)
149
- end
150
- end
151
-
152
- class PlusParser < LookAheadSensitiveParser
153
- def initialize(alts, la=1)
154
- super(la)
155
- @alts = alts
156
- end
157
- def _parse ctxt
158
- ind, result, err = ctxt.index, ctxt.result, ctxt.error
159
- for p in @alts
160
- ctxt.reset_error
161
- ctxt.index, ctxt.result = ind, result
162
- return true if p._parse(ctxt)
163
- return false unless visible(ctxt, ind)
164
- err = add_error(err, ctxt.error)
165
- end
166
- ctxt.error = err
167
- return false
168
- end
169
- def withLookahead(n)
170
- PlusParser.new(@alts, n)
171
- end
172
- def plus other
173
- PlusParser.new(@alts.dup << other, @lookahead).setName(name)
174
- end
175
- def_sig :plus, Parser
176
- end
177
-
178
-
179
- class AltParser < LookAheadSensitiveParser
180
- def initialize(alts, la = 1)
181
- super(la)
182
- @alts, @lookahead = alts, la
183
- end
184
- def _parse ctxt
185
- ind, result, err = ctxt.index, ctxt.result, ctxt.error
186
- err_ind, err_pos = -1, -1
187
- for p in @alts
188
- ctxt.reset_error
189
- ctxt.index, ctxt.result = ind, result
190
- return true if p._parse(ctxt)
191
- if ctxt.error.index > err_pos
192
- err, err_ind, err_pos = ctxt.error, ctxt.index, ctxt.error.index
193
- end
194
- end
195
- ctxt.index, ctxt.error = err_ind, err
196
- return false
197
- end
198
- def withLookahead(n)
199
- AltParser.new(@alts, n)
200
- end
201
- def | other
202
- AltParser.new(@alts.dup << autobox_parser(other)).setName(name)
203
- end
204
- end
205
-
206
-
207
- class BestParser < Parser
208
- init :alts, :longer
209
- def _parse ctxt
210
- best_result, best_ind = nil, -1
211
- err_ind, err_pos = -1, -1
212
- ind, result, err = ctxt.index, ctxt.result, ctxt.error
213
- for p in @alts
214
- ctxt.reset_error
215
- ctxt.index, ctxt.result = ind, result
216
- if p._parse(ctxt)
217
- err, now_ind = nil, ctxt.index
218
- if best_ind==-1 || now_ind != best_ind && @longer == (now_ind>best_ind)
219
- best_result, best_ind = ctxt.result, now_ind
220
- end
221
- elsif best_ind < 0 # no good match found yet.
222
- if ctxt.error.index > err_pos
223
- err_ind, err_pos = ctxt.index, ctxt.error.index
224
- end
225
- err = add_error(err, ctxt.error)
226
- end
227
- end
228
- if best_ind >= 0
229
- ctxt.index = best_ind
230
- return ctxt.retn(best_result)
231
- else
232
- ctxt.error, ctxt.index = err, err_ind
233
- return false
234
- end
235
- end
236
- end
237
-
238
- class BoundParser < Parser
239
- init :parser, :proc
240
- def _parse ctxt
241
- return false unless @parser._parse(ctxt)
242
- @proc.call(ctxt.result)._parse ctxt
243
- end
244
- end
245
- class BoundnParser < Parser
246
- init :parser, :proc
247
- def _parse ctxt
248
- return false unless @parser._parse(ctxt)
249
- @proc.call(*ctxt.result)._parse ctxt
250
- end
251
- end
252
- class MapParser < Parser
253
- init :parser, :proc
254
- def _parse ctxt
255
- return false unless @parser._parse(ctxt)
256
- ctxt.result = @proc.call(ctxt.result)
257
- true
258
- end
259
- end
260
-
261
- class MapnParser < Parser
262
- init :parser, :proc
263
- def _parse ctxt
264
- return false unless @parser._parse(ctxt)
265
- ctxt.result = @proc.call(*ctxt.result)
266
- true
267
- end
268
- end
269
-
270
- class SequenceParser < Parser
271
- init :parsers, :proc
272
- def _parse ctxt
273
- if @proc.nil?
274
- for p in @parsers
275
- return false unless p._parse(ctxt)
276
- end
277
- else
278
- results = []
279
- for p in @parsers
280
- return false unless p._parse(ctxt)
281
- results << ctxt.result
282
- end
283
- ctxt.retn(@proc.call(*results))
284
- end
285
- return true
286
- end
287
- def seq(other, &block)
288
- # TypeChecker.check_arg_type Parser, other, :seq
289
- SequenceParser.new(@parsers.dup << other, &block)
290
- end
291
- def_sig :seq, Parser
292
- end
293
-
294
- class FollowedParser < Parser
295
- init :p1, :p2
296
- def _parse ctxt
297
- return false unless @p1._parse ctxt
298
- result = ctxt.result
299
- return false unless @p2._parse ctxt
300
- ctxt.retn(result)
301
- end
302
- end
303
-
304
- class SatisfiesParser < Parser
305
- init :pred, :expected
306
- def _parse ctxt
307
- elem = nil
308
- if ctxt.eof || !@pred.call(elem=ctxt.current)
309
- return ctxt.expecting(@expected)
310
- end
311
- ctxt.next
312
- ctxt.retn elem
313
- end
314
- end
315
- class AnyParser < Parser
316
- def _parse ctxt
317
- return ctxt.expecting if ctxt.eof
318
- result = ctxt.current
319
- ctxt.next
320
- ctxt.retn result
321
- end
322
- end
323
-
324
- class EofParser < Parser
325
- init :msg
326
- def _parse ctxt
327
- return true if ctxt.eof
328
- return ctxt.expecting(@msg)
329
- end
330
- end
331
- class RegexpParser < Parser
332
- init :ptn, :msg
333
- def _parse ctxt
334
- scanner = ctxt.scanner
335
- result = scanner.check @ptn
336
- if result.nil?
337
- ctxt.expecting(@msg)
338
- else
339
- ctxt.advance(scanner.matched_size)
340
- ctxt.retn(result)
341
- end
342
- end
343
- end
344
- class AreParser < Parser
345
- init :vals, :msg
346
- def _parse ctxt
347
- if @vals.length > ctxt.available
348
- return ctxt.expecting(@msg)
349
- end
350
- cur = 0
351
- for cur in (0...@vals.length)
352
- if @vals[cur] != ctxt.peek(cur)
353
- return ctxt.expecting(@msg)
354
- end
355
- end
356
- ctxt.advance(@vals.length)
357
- ctxt.retn @vals
358
- end
359
- end
360
-
361
- def downcase c
362
- case when c >= ?A && c <=?Z : c + (?a - ?A) else c end
363
- end
364
-
365
- class StringCaseInsensitiveParser < Parser
366
- init :str, :msg
367
- def _parse ctxt
368
- if @str.length > ctxt.available
369
- return ctxt.expecting(@msg)
370
- end
371
- cur = 0
372
- for cur in (0...@str.length)
373
- if downcase(@str[cur]) != downcase(ctxt.peek(cur))
374
- return ctxt.expecting(@msg)
375
- end
376
- end
377
- result = ctxt.src[ctxt.index, @str.length]
378
- ctxt.advance(@str.length)
379
- ctxt.retn result
380
- end
381
- end
382
- class FragmentParser < Parser
383
- init :parser
384
- def _parse ctxt
385
- ind = ctxt.index
386
- return false unless @parser._parse ctxt
387
- ctxt.retn(ctxt.src[ind, ctxt.index-ind])
388
- end
389
- end
390
-
391
- class TokenParser < Parser
392
- init :symbol, :parser
393
- def _parse ctxt
394
- ind = ctxt.index
395
- return false unless @parser._parse ctxt
396
- raw = ctxt.result
397
- raw = ctxt.src[ind, ctxt.index-ind] unless raw.kind_of? String
398
- ctxt.retn(Token.new(@symbol, raw, ind))
399
- end
400
- end
401
-
402
- class NestedParser < Parser
403
- init :parser1, :parser2
404
- def _parse ctxt
405
- ind = ctxt.index
406
- return false unless @parser1._parse ctxt
407
- _run_nested(ind, ctxt, ctxt.result, @parser2)
408
- end
409
- private
410
- def _run_nested(start, ctxt, src, parser)
411
- ctxt.error = nil
412
- new_ctxt = nil
413
- if src.kind_of? String
414
- new_ctxt = ParseContext.new(src)
415
- return true if _run_parser parser, ctxt, new_ctxt
416
- ctxt.index = start + new_ctxt.index
417
- elsif src.kind_of? Array
418
- new_ctxt = ParseContext.new(src)
419
- return true if _run_parser parser, ctxt, new_ctxt
420
- ctxt.index = start + _get_index(new_ctxt) unless new_ctxt.eof
421
- else
422
- new_ctxt = ParseContext.new([src])
423
- return true if _run_parser parser, ctxt, new_ctxt
424
- ctxt.index = ind unless new_ctxt.eof
425
- end
426
- ctxt.error.index = ctxt.index
427
- false
428
- end
429
- def _get_index ctxt
430
- cur = ctxt.current
431
- return cur.index if cur.respond_to? :index
432
- ctxt.index
433
- end
434
- def _run_parser parser, old_ctxt, new_ctxt
435
- if parser._parse new_ctxt
436
- old_ctxt.result = new_ctxt.result
437
- true
438
- else
439
- old_ctxt.error = new_ctxt.error
440
- false
441
- end
442
- end
443
- end
444
-
445
- class WatchParser < Parser
446
- init :proc
447
- def _parse ctxt
448
- @proc.call(ctxt.result)
449
- true
450
- end
451
- end
452
- class WatchnParser < Parser
453
- init :proc
454
- def _parse ctxt
455
- @proc.call(*ctxt.result)
456
- true
457
- end
458
- end
459
- class MapCurrentParser < Parser
460
- init :proc
461
- def _parse ctxt
462
- ctxt.result = @proc.call(ctxt.result)
463
- true
464
- end
465
- end
466
- class MapnCurrentParser < Parser
467
- init :proc
468
- def _parse ctxt
469
- ctxt.result = @proc.call(*ctxt.result)
470
- true
471
- end
472
- end
473
- class Repeat_Parser < Parser
474
- init :parser, :times
475
- def _parse ctxt
476
- for i in (0...@times)
477
- return false unless @parser._parse ctxt
478
- end
479
- return true
480
- end
481
- end
482
-
483
- class RepeatParser < Parser
484
- init :parser, :times
485
- def _parse ctxt
486
- result = []
487
- for i in (0...@times)
488
- return false unless @parser._parse ctxt
489
- result << ctxt.result
490
- end
491
- return ctxt.retn(result)
492
- end
493
- end
494
-
495
- class Many_Parser < Parser
496
- init :parser, :least
497
- def _parse ctxt
498
- for i in (0...@least)
499
- return false unless @parser._parse ctxt
500
- end
501
- while(true)
502
- ind = ctxt.index
503
- if @parser._parse ctxt
504
- return true if ind==ctxt.index # infinite loop
505
- next
506
- end
507
- return ind==ctxt.index
508
- end
509
- end
510
- end
511
-
512
-
513
- class ManyParser < Parser
514
- init :parser, :least
515
- def _parse ctxt
516
- result = []
517
- for i in (0...@least)
518
- return false unless @parser._parse ctxt
519
- result << ctxt.result
520
- end
521
- while(true)
522
- ind = ctxt.index
523
- if @parser._parse ctxt
524
- result << ctxt.result
525
- return ctxt.retn(result) if ind==ctxt.index # infinite loop
526
- next
527
- end
528
- if ind==ctxt.index
529
- return ctxt.retn(result)
530
- else
531
- return false
532
- end
533
- end
534
- end
535
- end
536
-
537
- class Some_Parser < Parser
538
- init :parser, :least, :max
539
- def _parse ctxt
540
- for i in (0...@least)
541
- return false unless @parser._parse ctxt
542
- end
543
- for i in (@least...@max)
544
- ind = ctxt.index
545
- if @parser._parse ctxt
546
- return true if ind==ctxt.index # infinite loop
547
- next
548
- end
549
- return ind==ctxt.index
550
- end
551
- return true
552
- end
553
- end
554
-
555
- class SomeParser < Parser
556
- init :parser, :least, :max
557
- def _parse ctxt
558
- result = []
559
- for i in (0...@least)
560
- return false unless @parser._parse ctxt
561
- result << ctxt.result
562
- end
563
- for i in (@least...@max)
564
- ind = ctxt.index
565
- if @parser._parse ctxt
566
- result << ctxt.result
567
- return ctxt.retn(result) if ind==ctxt.index # infinite loop
568
- next
569
- end
570
- if ind==ctxt.index
571
- return ctxt.retn(result)
572
- else
573
- return false
574
- end
575
- end
576
- return ctxt.retn(result)
577
- end
578
- end
579
-
580
- class OneParser < Parser
581
- def _parse ctxt
582
- true
583
- end
584
- end
585
-
586
- class ZeroParser < Parser
587
- def _parse ctxt
588
- return ctxt.failure
589
- end
590
- end
591
-
592
- class GetIndexParser < Parser
593
- def _parse ctxt
594
- ctxt.retn(ctxt.index)
595
- end
596
- end
597
- class SetIndexParser < Parser
598
- init :index
599
- def _parse ctxt
600
- ctxt.index = @index
601
- end
602
- end
603
-
1
+ require 'rparsec/parser'
2
+
3
+ class FailureParser < Parser
4
+ init :msg
5
+ def _parse ctxt
6
+ return ctxt.failure(@msg)
7
+ end
8
+ end
9
+
10
+ class ValueParser < Parser
11
+ init :value
12
+ def _parse ctxt
13
+ ctxt.retn @value
14
+ end
15
+ end
16
+
17
+ class LazyParser < Parser
18
+ init :block
19
+ def _parse ctxt
20
+ @block.call._parse ctxt
21
+ end
22
+ end
23
+
24
+ def add_error(err, e)
25
+ return e if err.nil?
26
+ return err if e.nil?
27
+ cmp = compare_error(err, e)
28
+ return err if cmp > 0
29
+ return e if cmp < 0
30
+ err
31
+ # merge_error(err, e)
32
+ end
33
+
34
+ def get_first_element(err)
35
+ while err.kind_of?(Array)
36
+ err = err[0]
37
+ end
38
+ err
39
+ end
40
+
41
+ def compare_error(e1, e2)
42
+ e1, e2 = get_first_element(e1), get_first_element(e2)
43
+ return -1 if e1.index < e2.index
44
+ return 1 if e1.index > e2.index
45
+ 0
46
+ end
47
+
48
+ ###############################################
49
+ #def merge_error(e1, e2)
50
+ # return e1 << e2 if e1.kind_of?(Array)
51
+ # [e1,e2]
52
+ #end
53
+ ###############################################
54
+ class ThrowParser < Parser
55
+ init :symbol
56
+ def _parse ctxt
57
+ throw @symbol
58
+ end
59
+ end
60
+
61
+ class CatchParser < Parser
62
+ init :symbol, :parser
63
+ def _parse ctxt
64
+ interrupted = true
65
+ ok = false
66
+ catch @symbol do
67
+ ok = @parser._parse(ctxt)
68
+ interrupted = false
69
+ end
70
+ return ctxt.retn(@symbol) if interrupted
71
+ ok
72
+ end
73
+ end
74
+
75
+ class PeekParser < Parser
76
+ init :parser
77
+ def _parse ctxt
78
+ ind = ctxt.index
79
+ return false unless @parser._parse ctxt
80
+ ctxt.index = ind
81
+ return true
82
+ end
83
+ def peek
84
+ self
85
+ end
86
+ end
87
+
88
+ class AtomParser < Parser
89
+ init :parser
90
+ def _parse ctxt
91
+ ind = ctxt.index
92
+ return true if @parser._parse ctxt
93
+ ctxt.index = ind
94
+ return false
95
+ end
96
+ def atomize
97
+ self
98
+ end
99
+ end
100
+
101
+ class LookAheadSensitiveParser < Parser
102
+ def initialize(la=1)
103
+ super()
104
+ @lookahead = la
105
+ end
106
+ def visible(ctxt, n)
107
+ ctxt.index - n < @lookahead
108
+ end
109
+ def lookahead(n)
110
+ raise ArgumentError, "lookahead number #{n} should be positive" unless n>0
111
+ return self if n == @lookahead
112
+ withLookahead(n)
113
+ end
114
+ def not(msg="#{self} unexpected")
115
+ NotParser.new(self, msg, @lookahead)
116
+ end
117
+ end
118
+
119
+ class NotParser < LookAheadSensitiveParser
120
+ def initialize(parser, msg, la=1)
121
+ super(la)
122
+ @parser, @msg, @name = parser, msg, "~#{parser.name}"
123
+ end
124
+ def _parse ctxt
125
+ ind = ctxt.index
126
+ if @parser._parse ctxt
127
+ ctxt.index = ind
128
+ return ctxt.expecting(@msg)
129
+ end
130
+ return ctxt.retn(nil) if visible(ctxt, ind)
131
+ return false
132
+ end
133
+ def withLookahead(n)
134
+ NotParser.new(@parser, @msg, n)
135
+ end
136
+ def not()
137
+ @parser
138
+ end
139
+ end
140
+
141
+ class ExpectParser < Parser
142
+ def initialize(parser, msg)
143
+ super()
144
+ @parser, @msg, @name = parser, msg, msg
145
+ end
146
+ def _parse ctxt
147
+ ind = ctxt.index
148
+ return true if @parser._parse ctxt
149
+ return false unless ind == ctxt.index
150
+ ctxt.expecting(@msg)
151
+ end
152
+ end
153
+
154
+ class PlusParser < LookAheadSensitiveParser
155
+ def initialize(alts, la=1)
156
+ super(la)
157
+ @alts = alts
158
+ end
159
+ def _parse ctxt
160
+ ind, result, err = ctxt.index, ctxt.result, ctxt.error
161
+ for p in @alts
162
+ ctxt.reset_error
163
+ ctxt.index, ctxt.result = ind, result
164
+ return true if p._parse(ctxt)
165
+ return false unless visible(ctxt, ind)
166
+ err = add_error(err, ctxt.error)
167
+ end
168
+ ctxt.error = err
169
+ return false
170
+ end
171
+ def withLookahead(n)
172
+ PlusParser.new(@alts, n)
173
+ end
174
+ def plus other
175
+ PlusParser.new(@alts.dup << other, @lookahead).setName(name)
176
+ end
177
+ def_sig :plus, Parser
178
+ end
179
+
180
+
181
+ class AltParser < LookAheadSensitiveParser
182
+ def initialize(alts, la = 1)
183
+ super(la)
184
+ @alts, @lookahead = alts, la
185
+ end
186
+ def _parse ctxt
187
+ ind, result, err = ctxt.index, ctxt.result, ctxt.error
188
+ err_ind, err_pos = -1, -1
189
+ for p in @alts
190
+ ctxt.reset_error
191
+ ctxt.index, ctxt.result = ind, result
192
+ return true if p._parse(ctxt)
193
+ if ctxt.error.index > err_pos
194
+ err, err_ind, err_pos = ctxt.error, ctxt.index, ctxt.error.index
195
+ end
196
+ end
197
+ ctxt.index, ctxt.error = err_ind, err
198
+ return false
199
+ end
200
+ def withLookahead(n)
201
+ AltParser.new(@alts, n)
202
+ end
203
+ def | other
204
+ AltParser.new(@alts.dup << autobox_parser(other)).setName(name)
205
+ end
206
+ end
207
+
208
+
209
+ class BestParser < Parser
210
+ init :alts, :longer
211
+ def _parse ctxt
212
+ best_result, best_ind = nil, -1
213
+ err_ind, err_pos = -1, -1
214
+ ind, result, err = ctxt.index, ctxt.result, ctxt.error
215
+ for p in @alts
216
+ ctxt.reset_error
217
+ ctxt.index, ctxt.result = ind, result
218
+ if p._parse(ctxt)
219
+ err, now_ind = nil, ctxt.index
220
+ if best_ind==-1 || now_ind != best_ind && @longer == (now_ind>best_ind)
221
+ best_result, best_ind = ctxt.result, now_ind
222
+ end
223
+ elsif best_ind < 0 # no good match found yet.
224
+ if ctxt.error.index > err_pos
225
+ err_ind, err_pos = ctxt.index, ctxt.error.index
226
+ end
227
+ err = add_error(err, ctxt.error)
228
+ end
229
+ end
230
+ if best_ind >= 0
231
+ ctxt.index = best_ind
232
+ return ctxt.retn(best_result)
233
+ else
234
+ ctxt.error, ctxt.index = err, err_ind
235
+ return false
236
+ end
237
+ end
238
+ end
239
+
240
+ class BoundParser < Parser
241
+ init :parser, :proc
242
+ def _parse ctxt
243
+ return false unless @parser._parse(ctxt)
244
+ @proc.call(ctxt.result)._parse ctxt
245
+ end
246
+ end
247
+
248
+ class BoundnParser < Parser
249
+ init :parser, :proc
250
+ def _parse ctxt
251
+ return false unless @parser._parse(ctxt)
252
+ @proc.call(*ctxt.result)._parse ctxt
253
+ end
254
+ end
255
+
256
+ class MapParser < Parser
257
+ init :parser, :proc
258
+ def _parse ctxt
259
+ return false unless @parser._parse(ctxt)
260
+ ctxt.result = @proc.call(ctxt.result)
261
+ true
262
+ end
263
+ end
264
+
265
+ class MapnParser < Parser
266
+ init :parser, :proc
267
+ def _parse ctxt
268
+ return false unless @parser._parse(ctxt)
269
+ ctxt.result = @proc.call(*ctxt.result)
270
+ true
271
+ end
272
+ end
273
+
274
+ class SequenceParser < Parser
275
+ init :parsers, :proc
276
+ def _parse ctxt
277
+ if @proc.nil?
278
+ for p in @parsers
279
+ return false unless p._parse(ctxt)
280
+ end
281
+ else
282
+ results = []
283
+ for p in @parsers
284
+ return false unless p._parse(ctxt)
285
+ results << ctxt.result
286
+ end
287
+ ctxt.retn(@proc.call(*results))
288
+ end
289
+ return true
290
+ end
291
+ def seq(other, &block)
292
+ # TypeChecker.check_arg_type Parser, other, :seq
293
+ SequenceParser.new(@parsers.dup << other, &block)
294
+ end
295
+ def_sig :seq, Parser
296
+ end
297
+
298
+ class FollowedParser < Parser
299
+ init :p1, :p2
300
+ def _parse ctxt
301
+ return false unless @p1._parse ctxt
302
+ result = ctxt.result
303
+ return false unless @p2._parse ctxt
304
+ ctxt.retn(result)
305
+ end
306
+ end
307
+
308
+ class SatisfiesParser < Parser
309
+ init :pred, :expected
310
+ def _parse ctxt
311
+ elem = nil
312
+ if ctxt.eof || !@pred.call(elem=ctxt.current)
313
+ return ctxt.expecting(@expected)
314
+ end
315
+ ctxt.next
316
+ ctxt.retn elem
317
+ end
318
+ end
319
+
320
+ class AnyParser < Parser
321
+ def _parse ctxt
322
+ return ctxt.expecting if ctxt.eof
323
+ result = ctxt.current
324
+ ctxt.next
325
+ ctxt.retn result
326
+ end
327
+ end
328
+
329
+ class EofParser < Parser
330
+ init :msg
331
+ def _parse ctxt
332
+ return true if ctxt.eof
333
+ return ctxt.expecting(@msg)
334
+ end
335
+ end
336
+
337
+ class RegexpParser < Parser
338
+ init :ptn, :msg
339
+ def _parse ctxt
340
+ scanner = ctxt.scanner
341
+ result = scanner.check @ptn
342
+ if result.nil?
343
+ ctxt.expecting(@msg)
344
+ else
345
+ ctxt.advance(scanner.matched_size)
346
+ ctxt.retn(result)
347
+ end
348
+ end
349
+ end
350
+
351
+ class AreParser < Parser
352
+ init :vals, :msg
353
+ def _parse ctxt
354
+ if @vals.length > ctxt.available
355
+ return ctxt.expecting(@msg)
356
+ end
357
+ cur = 0
358
+ for cur in (0...@vals.length)
359
+ if @vals[cur] != ctxt.peek(cur)
360
+ return ctxt.expecting(@msg)
361
+ end
362
+ end
363
+ ctxt.advance(@vals.length)
364
+ ctxt.retn @vals
365
+ end
366
+ end
367
+
368
+ def downcase c
369
+ case when c >= ?A && c <=?Z then c + (?a - ?A) else c end
370
+ end
371
+
372
+ class StringCaseInsensitiveParser < Parser
373
+ init :str, :msg
374
+ def _parse ctxt
375
+ if @str.length > ctxt.available
376
+ return ctxt.expecting(@msg)
377
+ end
378
+ cur = 0
379
+ for cur in (0...@str.length)
380
+ if downcase(@str[cur]) != downcase(ctxt.peek(cur))
381
+ return ctxt.expecting(@msg)
382
+ end
383
+ end
384
+ result = ctxt.src[ctxt.index, @str.length]
385
+ ctxt.advance(@str.length)
386
+ ctxt.retn result
387
+ end
388
+ end
389
+
390
+ class FragmentParser < Parser
391
+ init :parser
392
+ def _parse ctxt
393
+ ind = ctxt.index
394
+ return false unless @parser._parse ctxt
395
+ ctxt.retn(ctxt.src[ind, ctxt.index-ind])
396
+ end
397
+ end
398
+
399
+ class TokenParser < Parser
400
+ init :symbol, :parser
401
+ def _parse ctxt
402
+ ind = ctxt.index
403
+ return false unless @parser._parse ctxt
404
+ raw = ctxt.result
405
+ raw = ctxt.src[ind, ctxt.index-ind] unless raw.kind_of? String
406
+ ctxt.retn(Token.new(@symbol, raw, ind))
407
+ end
408
+ end
409
+
410
+ class NestedParser < Parser
411
+ init :parser1, :parser2
412
+ def _parse ctxt
413
+ ind = ctxt.index
414
+ return false unless @parser1._parse ctxt
415
+ _run_nested(ind, ctxt, ctxt.result, @parser2)
416
+ end
417
+ private
418
+ def _run_nested(start, ctxt, src, parser)
419
+ ctxt.error = nil
420
+ new_ctxt = nil
421
+ if src.kind_of? String
422
+ new_ctxt = ParseContext.new(src)
423
+ return true if _run_parser parser, ctxt, new_ctxt
424
+ ctxt.index = start + new_ctxt.index
425
+ elsif src.kind_of? Array
426
+ new_ctxt = ParseContext.new(src)
427
+ return true if _run_parser parser, ctxt, new_ctxt
428
+ ctxt.index = start + _get_index(new_ctxt) unless new_ctxt.eof
429
+ else
430
+ new_ctxt = ParseContext.new([src])
431
+ return true if _run_parser parser, ctxt, new_ctxt
432
+ ctxt.index = ind unless new_ctxt.eof
433
+ end
434
+ ctxt.error.index = ctxt.index
435
+ false
436
+ end
437
+ def _get_index ctxt
438
+ cur = ctxt.current
439
+ return cur.index if cur.respond_to? :index
440
+ ctxt.index
441
+ end
442
+ def _run_parser parser, old_ctxt, new_ctxt
443
+ if parser._parse new_ctxt
444
+ old_ctxt.result = new_ctxt.result
445
+ true
446
+ else
447
+ old_ctxt.error = new_ctxt.error
448
+ false
449
+ end
450
+ end
451
+ end
452
+
453
+ class WatchParser < Parser
454
+ init :proc
455
+ def _parse ctxt
456
+ @proc.call(ctxt.result)
457
+ true
458
+ end
459
+ end
460
+
461
+ class WatchnParser < Parser
462
+ init :proc
463
+ def _parse ctxt
464
+ @proc.call(*ctxt.result)
465
+ true
466
+ end
467
+ end
468
+
469
+ class MapCurrentParser < Parser
470
+ init :proc
471
+ def _parse ctxt
472
+ ctxt.result = @proc.call(ctxt.result)
473
+ true
474
+ end
475
+ end
476
+
477
+ class MapnCurrentParser < Parser
478
+ init :proc
479
+ def _parse ctxt
480
+ ctxt.result = @proc.call(*ctxt.result)
481
+ true
482
+ end
483
+ end
484
+
485
+ class Repeat_Parser < Parser
486
+ init :parser, :times
487
+ def _parse ctxt
488
+ for i in (0...@times)
489
+ return false unless @parser._parse ctxt
490
+ end
491
+ return true
492
+ end
493
+ end
494
+
495
+ class RepeatParser < Parser
496
+ init :parser, :times
497
+ def _parse ctxt
498
+ result = []
499
+ for i in (0...@times)
500
+ return false unless @parser._parse ctxt
501
+ result << ctxt.result
502
+ end
503
+ return ctxt.retn(result)
504
+ end
505
+ end
506
+
507
+ class Many_Parser < Parser
508
+ init :parser, :least
509
+ def _parse ctxt
510
+ for i in (0...@least)
511
+ return false unless @parser._parse ctxt
512
+ end
513
+ while(true)
514
+ ind = ctxt.index
515
+ if @parser._parse ctxt
516
+ return true if ind==ctxt.index # infinite loop
517
+ next
518
+ end
519
+ return ind==ctxt.index
520
+ end
521
+ end
522
+ end
523
+
524
+ class ManyParser < Parser
525
+ init :parser, :least
526
+ def _parse ctxt
527
+ result = []
528
+ for i in (0...@least)
529
+ return false unless @parser._parse ctxt
530
+ result << ctxt.result
531
+ end
532
+ while(true)
533
+ ind = ctxt.index
534
+ if @parser._parse ctxt
535
+ result << ctxt.result
536
+ return ctxt.retn(result) if ind==ctxt.index # infinite loop
537
+ next
538
+ end
539
+ if ind==ctxt.index
540
+ return ctxt.retn(result)
541
+ else
542
+ return false
543
+ end
544
+ end
545
+ end
546
+ end
547
+
548
+ class Some_Parser < Parser
549
+ init :parser, :least, :max
550
+ def _parse ctxt
551
+ for i in (0...@least)
552
+ return false unless @parser._parse ctxt
553
+ end
554
+ for i in (@least...@max)
555
+ ind = ctxt.index
556
+ if @parser._parse ctxt
557
+ return true if ind==ctxt.index # infinite loop
558
+ next
559
+ end
560
+ return ind==ctxt.index
561
+ end
562
+ return true
563
+ end
564
+ end
565
+
566
+ class SomeParser < Parser
567
+ init :parser, :least, :max
568
+ def _parse ctxt
569
+ result = []
570
+ for i in (0...@least)
571
+ return false unless @parser._parse ctxt
572
+ result << ctxt.result
573
+ end
574
+ for i in (@least...@max)
575
+ ind = ctxt.index
576
+ if @parser._parse ctxt
577
+ result << ctxt.result
578
+ return ctxt.retn(result) if ind==ctxt.index # infinite loop
579
+ next
580
+ end
581
+ if ind==ctxt.index
582
+ return ctxt.retn(result)
583
+ else
584
+ return false
585
+ end
586
+ end
587
+ return ctxt.retn(result)
588
+ end
589
+ end
590
+
591
+ class OneParser < Parser
592
+ def _parse ctxt
593
+ true
594
+ end
595
+ end
596
+
597
+ class ZeroParser < Parser
598
+ def _parse ctxt
599
+ return ctxt.failure
600
+ end
601
+ end
602
+
603
+ class GetIndexParser < Parser
604
+ def _parse ctxt
605
+ ctxt.retn(ctxt.index)
606
+ end
607
+ end
608
+ class SetIndexParser < Parser
609
+ init :index
610
+ def _parse ctxt
611
+ ctxt.index = @index
612
+ end
613
+ end
614
+
604
615
  Nil = ValueParser.new(nil)