rparsec2 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/rparsec/alt_parser.rb +38 -0
- data/lib/rparsec/any_parser.rb +12 -0
- data/lib/rparsec/are_parser.rb +20 -0
- data/lib/rparsec/atom_parser.rb +16 -0
- data/lib/rparsec/best_parser.rb +44 -0
- data/lib/rparsec/bound_parser.rb +11 -0
- data/lib/rparsec/boundn_parser.rb +11 -0
- data/lib/rparsec/catch_parser.rb +17 -0
- data/lib/rparsec/context.rb +5 -3
- data/lib/rparsec/{misc.rb → def_helper.rb} +5 -8
- data/lib/rparsec/eof_parser.rb +11 -0
- data/lib/rparsec/error.rb +8 -12
- data/lib/rparsec/expect_parser.rb +18 -0
- data/lib/rparsec/expressions.rb +5 -19
- data/lib/rparsec/failure_parser.rb +10 -0
- data/lib/rparsec/failures.rb +31 -0
- data/lib/rparsec/followed_parser.rb +13 -0
- data/lib/rparsec/fragment_parser.rb +12 -0
- data/lib/rparsec/functor_mixin.rb +10 -31
- data/lib/rparsec/get_index_parser.rb +9 -0
- data/lib/rparsec/keywords.rb +9 -9
- data/lib/rparsec/lazy_parser.rb +10 -0
- data/lib/rparsec/locator.rb +9 -5
- data/lib/rparsec/look_ahead_sensitive_parser.rb +46 -0
- data/lib/rparsec/many__parser.rb +20 -0
- data/lib/rparsec/many_parser.rb +27 -0
- data/lib/rparsec/map_current_parser.rb +11 -0
- data/lib/rparsec/map_parser.rb +12 -0
- data/lib/rparsec/mapn_current_parser.rb +11 -0
- data/lib/rparsec/mapn_parser.rb +12 -0
- data/lib/rparsec/nested_parser.rb +47 -0
- data/lib/rparsec/not_parser.rb +27 -0
- data/lib/rparsec/one_parser.rb +9 -0
- data/lib/rparsec/operator_table.rb +29 -63
- data/lib/rparsec/parser.rb +14 -20
- data/lib/rparsec/parser_monad.rb +4 -17
- data/lib/rparsec/parsers.rb +52 -626
- data/lib/rparsec/peek_parser.rb +16 -0
- data/lib/rparsec/plus_parser.rb +32 -0
- data/lib/rparsec/regexp_parser.rb +17 -0
- data/lib/rparsec/repeat__parser.rb +13 -0
- data/lib/rparsec/repeat_parser.rb +15 -0
- data/lib/rparsec/satisfies_parser.rb +15 -0
- data/lib/rparsec/sequence_parser.rb +25 -0
- data/lib/rparsec/set_index_parser.rb +10 -0
- data/lib/rparsec/some__parser.rb +19 -0
- data/lib/rparsec/some_parser.rb +28 -0
- data/lib/rparsec/string_case_insensitive_parser.rb +26 -0
- data/lib/rparsec/throw_parser.rb +10 -0
- data/lib/rparsec/token.rb +9 -28
- data/lib/rparsec/token_parser.rb +14 -0
- data/lib/rparsec/value_parser.rb +10 -0
- data/lib/rparsec/watch_parser.rb +11 -0
- data/lib/rparsec/watchn_parser.rb +11 -0
- data/lib/rparsec/zero_parser.rb +9 -0
- data/lib/rparsec.rb +1 -1
- metadata +53 -8
- data/lib/rparsec/id_monad.rb +0 -19
data/lib/rparsec/parsers.rb
CHANGED
@@ -1,6 +1,45 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'rparsec/
|
3
|
+
require 'rparsec/alt_parser'
|
4
|
+
require 'rparsec/any_parser'
|
5
|
+
require 'rparsec/are_parser'
|
6
|
+
require 'rparsec/atom_parser'
|
7
|
+
require 'rparsec/best_parser'
|
8
|
+
require 'rparsec/bound_parser'
|
9
|
+
require 'rparsec/boundn_parser'
|
10
|
+
require 'rparsec/catch_parser'
|
11
|
+
require 'rparsec/eof_parser'
|
12
|
+
require 'rparsec/expect_parser'
|
13
|
+
require 'rparsec/failure_parser'
|
14
|
+
require 'rparsec/followed_parser'
|
15
|
+
require 'rparsec/fragment_parser'
|
16
|
+
require 'rparsec/get_index_parser'
|
17
|
+
require 'rparsec/lazy_parser'
|
18
|
+
require 'rparsec/many__parser'
|
19
|
+
require 'rparsec/many_parser'
|
20
|
+
require 'rparsec/map_current_parser'
|
21
|
+
require 'rparsec/map_parser'
|
22
|
+
require 'rparsec/mapn_current_parser'
|
23
|
+
require 'rparsec/mapn_parser'
|
24
|
+
require 'rparsec/nested_parser'
|
25
|
+
require 'rparsec/one_parser'
|
26
|
+
require 'rparsec/peek_parser'
|
27
|
+
require 'rparsec/plus_parser'
|
28
|
+
require 'rparsec/regexp_parser'
|
29
|
+
require 'rparsec/repeat__parser'
|
30
|
+
require 'rparsec/repeat_parser'
|
31
|
+
require 'rparsec/satisfies_parser'
|
32
|
+
require 'rparsec/sequence_parser'
|
33
|
+
require 'rparsec/set_index_parser'
|
34
|
+
require 'rparsec/some__parser'
|
35
|
+
require 'rparsec/some_parser'
|
36
|
+
require 'rparsec/string_case_insensitive_parser'
|
37
|
+
require 'rparsec/throw_parser'
|
38
|
+
require 'rparsec/token_parser'
|
39
|
+
require 'rparsec/value_parser'
|
40
|
+
require 'rparsec/watch_parser'
|
41
|
+
require 'rparsec/watchn_parser'
|
42
|
+
require 'rparsec/zero_parser'
|
4
43
|
|
5
44
|
module RParsec
|
6
45
|
#
|
@@ -87,9 +126,9 @@ module RParsec
|
|
87
126
|
def char(c)
|
88
127
|
if c.kind_of? Integer
|
89
128
|
nm = c.chr
|
90
|
-
is(c, "'#{nm}' expected").
|
129
|
+
is(c, "'#{nm}' expected").tap { |p| p.name = nm }
|
91
130
|
else
|
92
|
-
is(c[0], "'#{c}' expected").
|
131
|
+
is(c[0], "'#{c}' expected").tap { |p| p.name = c }
|
93
132
|
end
|
94
133
|
end
|
95
134
|
|
@@ -99,9 +138,9 @@ module RParsec
|
|
99
138
|
def not_char(c)
|
100
139
|
if c.kind_of? Integer
|
101
140
|
nm = c.chr
|
102
|
-
isnt(c, "'#{nm}' unexpected").
|
141
|
+
isnt(c, "'#{nm}' unexpected").tap { |p| p.name = "~#{nm}" }
|
103
142
|
else
|
104
|
-
isnt(c[0], "'#{c}' unexpected").
|
143
|
+
isnt(c[0], "'#{c}' unexpected").tap { |p| p.name = "~#{c}" }
|
105
144
|
end
|
106
145
|
end
|
107
146
|
|
@@ -109,7 +148,7 @@ module RParsec
|
|
109
148
|
# A parser that succeeds when there's no input available.
|
110
149
|
#
|
111
150
|
def eof(expected = "EOF expected")
|
112
|
-
EofParser.new(expected).
|
151
|
+
EofParser.new(expected).tap { |p| p.name = "EOF" }
|
113
152
|
end
|
114
153
|
|
115
154
|
#
|
@@ -134,7 +173,7 @@ module RParsec
|
|
134
173
|
# A parser that matches the given string.
|
135
174
|
#
|
136
175
|
def string(str, msg = "\"#{str}\" expected")
|
137
|
-
are(str, msg).
|
176
|
+
are(str, msg).tap { |p| p.name = str }
|
138
177
|
end
|
139
178
|
|
140
179
|
#
|
@@ -162,14 +201,14 @@ module RParsec
|
|
162
201
|
# A parser that returns the current input index (starting from 0).
|
163
202
|
#
|
164
203
|
def get_index
|
165
|
-
GetIndexParser.new.
|
204
|
+
GetIndexParser.new.tap { |p| p.name = 'get_index' }
|
166
205
|
end
|
167
206
|
|
168
207
|
#
|
169
208
|
# A parser that moves the current input pointer to a certain index.
|
170
209
|
#
|
171
210
|
def set_index ind
|
172
|
-
SetIndexParser.new(ind).
|
211
|
+
SetIndexParser.new(ind).tap { |p| p.name = "set_index" }
|
173
212
|
end
|
174
213
|
|
175
214
|
#
|
@@ -216,7 +255,8 @@ module RParsec
|
|
216
255
|
# A parser that succeeds if the current input is within a certain range.
|
217
256
|
#
|
218
257
|
def range(from, to, msg = "#{as_char from}..#{as_char to} expected")
|
219
|
-
from
|
258
|
+
from = as_num(from)
|
259
|
+
to = as_num(to)
|
220
260
|
satisfies(msg) { |c| c <= to && c >= from }
|
221
261
|
end
|
222
262
|
|
@@ -233,7 +273,7 @@ module RParsec
|
|
233
273
|
# The matched string is consumed and returned as result.
|
234
274
|
#
|
235
275
|
def regexp(ptn, expected = "/#{ptn}/ expected")
|
236
|
-
RegexpParser.new(as_regexp(ptn), expected).
|
276
|
+
RegexpParser.new(as_regexp(ptn), expected).tap { |p| p.name = expected }
|
237
277
|
end
|
238
278
|
|
239
279
|
#
|
@@ -265,7 +305,7 @@ module RParsec
|
|
265
305
|
# A parser that matches the given string, case insensitively.
|
266
306
|
#
|
267
307
|
def string_nocase(str, expected = "'#{str}' expected")
|
268
|
-
StringCaseInsensitiveParser.new(str, expected).
|
308
|
+
StringCaseInsensitiveParser.new(str, expected).tap { |p| p.name = str }
|
269
309
|
end
|
270
310
|
|
271
311
|
#
|
@@ -428,620 +468,6 @@ module RParsec
|
|
428
468
|
extend self
|
429
469
|
end
|
430
470
|
|
431
|
-
class FailureParser < Parser # :nodoc:
|
432
|
-
init :msg
|
433
|
-
def _parse ctxt
|
434
|
-
return ctxt.failure(@msg)
|
435
|
-
end
|
436
|
-
end
|
437
|
-
|
438
|
-
class ValueParser < Parser # :nodoc:
|
439
|
-
init :value
|
440
|
-
def _parse ctxt
|
441
|
-
ctxt.retn @value
|
442
|
-
end
|
443
|
-
end
|
444
|
-
|
445
|
-
class LazyParser < Parser # :nodoc:
|
446
|
-
init :block
|
447
|
-
def _parse ctxt
|
448
|
-
@block.call._parse ctxt
|
449
|
-
end
|
450
|
-
end
|
451
|
-
|
452
|
-
class Failures # :nodoc:
|
453
|
-
def self.add_error(err, e)
|
454
|
-
return e if err.nil?
|
455
|
-
return err if e.nil?
|
456
|
-
cmp = compare_error(err, e)
|
457
|
-
return err if cmp > 0
|
458
|
-
return e if cmp < 0
|
459
|
-
err
|
460
|
-
# merge_error(err, e)
|
461
|
-
end
|
462
|
-
|
463
|
-
class << self
|
464
|
-
private
|
465
|
-
|
466
|
-
def get_first_element(err)
|
467
|
-
while err.kind_of?(Array)
|
468
|
-
err = err[0]
|
469
|
-
end
|
470
|
-
err
|
471
|
-
end
|
472
|
-
|
473
|
-
def compare_error(e1, e2)
|
474
|
-
e1, e2 = get_first_element(e1), get_first_element(e2)
|
475
|
-
return -1 if e1.index < e2.index
|
476
|
-
return 1 if e1.index > e2.index
|
477
|
-
0
|
478
|
-
end
|
479
|
-
end
|
480
|
-
end
|
481
|
-
|
482
|
-
###############################################
|
483
|
-
#def merge_error(e1, e2)
|
484
|
-
# return e1 << e2 if e1.kind_of?(Array)
|
485
|
-
# [e1,e2]
|
486
|
-
#end
|
487
|
-
###############################################
|
488
|
-
class ThrowParser < Parser # :nodoc:
|
489
|
-
init :symbol
|
490
|
-
def _parse _ctxt
|
491
|
-
throw @symbol
|
492
|
-
end
|
493
|
-
end
|
494
|
-
|
495
|
-
class CatchParser < Parser # :nodoc:
|
496
|
-
init :symbol, :parser
|
497
|
-
def _parse ctxt
|
498
|
-
interrupted = true
|
499
|
-
ok = false
|
500
|
-
catch @symbol do
|
501
|
-
ok = @parser._parse(ctxt)
|
502
|
-
interrupted = false
|
503
|
-
end
|
504
|
-
return ctxt.retn(@symbol) if interrupted
|
505
|
-
ok
|
506
|
-
end
|
507
|
-
end
|
508
|
-
|
509
|
-
class PeekParser < Parser # :nodoc:
|
510
|
-
init :parser
|
511
|
-
def _parse ctxt
|
512
|
-
ind = ctxt.index
|
513
|
-
return false unless @parser._parse ctxt
|
514
|
-
ctxt.index = ind
|
515
|
-
return true
|
516
|
-
end
|
517
|
-
def peek
|
518
|
-
self
|
519
|
-
end
|
520
|
-
end
|
521
|
-
|
522
|
-
class AtomParser < Parser # :nodoc:
|
523
|
-
init :parser
|
524
|
-
def _parse ctxt
|
525
|
-
ind = ctxt.index
|
526
|
-
return true if @parser._parse ctxt
|
527
|
-
ctxt.index = ind
|
528
|
-
return false
|
529
|
-
end
|
530
|
-
def atomize
|
531
|
-
self
|
532
|
-
end
|
533
|
-
end
|
534
|
-
|
535
|
-
class LookAheadSensitiveParser < Parser # :nodoc:
|
536
|
-
def initialize(la = 1)
|
537
|
-
super()
|
538
|
-
@lookahead = la
|
539
|
-
end
|
540
|
-
def visible(ctxt, n)
|
541
|
-
ctxt.index - n < @lookahead
|
542
|
-
end
|
543
|
-
def lookahead(n)
|
544
|
-
raise ArgumentError, "lookahead number #{n} should be positive" unless n > 0
|
545
|
-
return self if n == @lookahead
|
546
|
-
withLookahead(n)
|
547
|
-
end
|
548
|
-
def not(msg = "#{self} unexpected")
|
549
|
-
NotParser.new(self, msg, @lookahead)
|
550
|
-
end
|
551
|
-
end
|
552
|
-
|
553
|
-
class NotParser < LookAheadSensitiveParser # :nodoc:
|
554
|
-
def initialize(parser, msg, la = 1)
|
555
|
-
super(la)
|
556
|
-
@parser, @msg, @name = parser, msg, "~#{parser.name}"
|
557
|
-
end
|
558
|
-
def _parse ctxt
|
559
|
-
ind = ctxt.index
|
560
|
-
if @parser._parse ctxt
|
561
|
-
ctxt.index = ind
|
562
|
-
return ctxt.expecting(@msg)
|
563
|
-
end
|
564
|
-
return ctxt.retn(nil) if visible(ctxt, ind)
|
565
|
-
return false
|
566
|
-
end
|
567
|
-
def withLookahead(n)
|
568
|
-
NotParser.new(@parser, @msg, n)
|
569
|
-
end
|
570
|
-
def not()
|
571
|
-
@parser
|
572
|
-
end
|
573
|
-
end
|
574
|
-
|
575
|
-
class ExpectParser < Parser # :nodoc:
|
576
|
-
def initialize(parser, msg)
|
577
|
-
super()
|
578
|
-
@parser, @msg, @name = parser, msg, msg
|
579
|
-
end
|
580
|
-
def _parse ctxt
|
581
|
-
ind = ctxt.index
|
582
|
-
return true if @parser._parse ctxt
|
583
|
-
return false unless ind == ctxt.index
|
584
|
-
ctxt.expecting(@msg)
|
585
|
-
end
|
586
|
-
end
|
587
|
-
|
588
|
-
class PlusParser < LookAheadSensitiveParser # :nodoc:
|
589
|
-
def initialize(alts, la = 1)
|
590
|
-
super(la)
|
591
|
-
@alts = alts
|
592
|
-
end
|
593
|
-
def _parse ctxt
|
594
|
-
ind, result, err = ctxt.index, ctxt.result, ctxt.error
|
595
|
-
for p in @alts
|
596
|
-
ctxt.reset_error
|
597
|
-
ctxt.index, ctxt.result = ind, result
|
598
|
-
return true if p._parse(ctxt)
|
599
|
-
return false unless visible(ctxt, ind)
|
600
|
-
err = Failures.add_error(err, ctxt.error)
|
601
|
-
end
|
602
|
-
ctxt.error = err
|
603
|
-
return false
|
604
|
-
end
|
605
|
-
def withLookahead(n)
|
606
|
-
PlusParser.new(@alts, n)
|
607
|
-
end
|
608
|
-
def plus other
|
609
|
-
PlusParser.new(@alts.dup << other, @lookahead).setName(name)
|
610
|
-
end
|
611
|
-
end
|
612
|
-
|
613
|
-
|
614
|
-
class AltParser < LookAheadSensitiveParser # :nodoc:
|
615
|
-
def initialize(alts, la = 1)
|
616
|
-
super(la)
|
617
|
-
@alts, @lookahead = alts, la
|
618
|
-
end
|
619
|
-
def _parse ctxt
|
620
|
-
ind, result, err = ctxt.index, ctxt.result, ctxt.error
|
621
|
-
err_ind, err_pos = -1, -1
|
622
|
-
for p in @alts
|
623
|
-
ctxt.reset_error
|
624
|
-
ctxt.index, ctxt.result = ind, result
|
625
|
-
return true if p._parse(ctxt)
|
626
|
-
if ctxt.error.index > err_pos
|
627
|
-
err, err_ind, err_pos = ctxt.error, ctxt.index, ctxt.error.index
|
628
|
-
end
|
629
|
-
end
|
630
|
-
ctxt.index, ctxt.error = err_ind, err
|
631
|
-
return false
|
632
|
-
end
|
633
|
-
def withLookahead(n)
|
634
|
-
AltParser.new(@alts, n)
|
635
|
-
end
|
636
|
-
def | other
|
637
|
-
AltParser.new(@alts.dup << autobox_parser(other)).setName(name)
|
638
|
-
end
|
639
|
-
end
|
640
|
-
|
641
|
-
|
642
|
-
class BestParser < Parser # :nodoc:
|
643
|
-
init :alts, :longer
|
644
|
-
def _parse ctxt
|
645
|
-
best_result, best_ind = nil, -1
|
646
|
-
err_ind, err_pos = -1, -1
|
647
|
-
ind, result, err = ctxt.index, ctxt.result, ctxt.error
|
648
|
-
for p in @alts
|
649
|
-
ctxt.reset_error
|
650
|
-
ctxt.index, ctxt.result = ind, result
|
651
|
-
if p._parse(ctxt)
|
652
|
-
err, now_ind = nil, ctxt.index
|
653
|
-
if best_ind == -1 || (now_ind != best_ind && @longer == (now_ind > best_ind))
|
654
|
-
best_result, best_ind = ctxt.result, now_ind
|
655
|
-
end
|
656
|
-
elsif best_ind < 0 # no good match found yet.
|
657
|
-
if ctxt.error.index > err_pos
|
658
|
-
err_ind, err_pos = ctxt.index, ctxt.error.index
|
659
|
-
end
|
660
|
-
err = Failures.add_error(err, ctxt.error)
|
661
|
-
end
|
662
|
-
end
|
663
|
-
if best_ind >= 0
|
664
|
-
ctxt.index = best_ind
|
665
|
-
return ctxt.retn(best_result)
|
666
|
-
else
|
667
|
-
ctxt.error, ctxt.index = err, err_ind
|
668
|
-
return false
|
669
|
-
end
|
670
|
-
end
|
671
|
-
end
|
672
|
-
|
673
|
-
class BoundParser < Parser # :nodoc:
|
674
|
-
init :parser, :proc
|
675
|
-
def _parse ctxt
|
676
|
-
return false unless @parser._parse(ctxt)
|
677
|
-
@proc.call(ctxt.result)._parse ctxt
|
678
|
-
end
|
679
|
-
end
|
680
|
-
|
681
|
-
class BoundnParser < Parser # :nodoc:
|
682
|
-
init :parser, :proc
|
683
|
-
def _parse ctxt
|
684
|
-
return false unless @parser._parse(ctxt)
|
685
|
-
@proc.call(*ctxt.result)._parse ctxt
|
686
|
-
end
|
687
|
-
end
|
688
|
-
|
689
|
-
class MapParser < Parser # :nodoc:
|
690
|
-
init :parser, :proc
|
691
|
-
def _parse ctxt
|
692
|
-
return false unless @parser._parse(ctxt)
|
693
|
-
ctxt.result = @proc.call(ctxt.result)
|
694
|
-
true
|
695
|
-
end
|
696
|
-
end
|
697
|
-
|
698
|
-
class MapnParser < Parser # :nodoc:
|
699
|
-
init :parser, :proc
|
700
|
-
def _parse ctxt
|
701
|
-
return false unless @parser._parse(ctxt)
|
702
|
-
ctxt.result = @proc.call(*ctxt.result)
|
703
|
-
true
|
704
|
-
end
|
705
|
-
end
|
706
|
-
|
707
|
-
class SequenceParser < Parser # :nodoc:
|
708
|
-
init :parsers, :proc
|
709
|
-
def _parse ctxt
|
710
|
-
if @proc.nil?
|
711
|
-
for p in @parsers
|
712
|
-
return false unless p._parse(ctxt)
|
713
|
-
end
|
714
|
-
else
|
715
|
-
results = []
|
716
|
-
for p in @parsers
|
717
|
-
return false unless p._parse(ctxt)
|
718
|
-
results << ctxt.result
|
719
|
-
end
|
720
|
-
ctxt.retn(@proc.call(*results))
|
721
|
-
end
|
722
|
-
return true
|
723
|
-
end
|
724
|
-
def seq(other, &block)
|
725
|
-
SequenceParser.new(@parsers.dup << other, &block)
|
726
|
-
end
|
727
|
-
end
|
728
|
-
|
729
|
-
class FollowedParser < Parser # :nodoc:
|
730
|
-
init :p1, :p2
|
731
|
-
def _parse ctxt
|
732
|
-
return false unless @p1._parse ctxt
|
733
|
-
result = ctxt.result
|
734
|
-
return false unless @p2._parse ctxt
|
735
|
-
ctxt.retn(result)
|
736
|
-
end
|
737
|
-
end
|
738
|
-
|
739
|
-
class SatisfiesParser < Parser # :nodoc:
|
740
|
-
init :pred, :expected
|
741
|
-
def _parse ctxt
|
742
|
-
elem = nil
|
743
|
-
if ctxt.eof || !@pred.call(elem = ctxt.current)
|
744
|
-
return ctxt.expecting(@expected)
|
745
|
-
end
|
746
|
-
ctxt.next
|
747
|
-
ctxt.retn elem
|
748
|
-
end
|
749
|
-
end
|
750
|
-
|
751
|
-
class AnyParser < Parser # :nodoc:
|
752
|
-
def _parse ctxt
|
753
|
-
return ctxt.expecting if ctxt.eof
|
754
|
-
result = ctxt.current
|
755
|
-
ctxt.next
|
756
|
-
ctxt.retn result
|
757
|
-
end
|
758
|
-
end
|
759
|
-
|
760
|
-
class EofParser < Parser # :nodoc:
|
761
|
-
init :msg
|
762
|
-
def _parse ctxt
|
763
|
-
return true if ctxt.eof
|
764
|
-
return ctxt.expecting(@msg)
|
765
|
-
end
|
766
|
-
end
|
767
|
-
|
768
|
-
class RegexpParser < Parser # :nodoc:
|
769
|
-
init :ptn, :msg
|
770
|
-
def _parse ctxt
|
771
|
-
scanner = ctxt.scanner
|
772
|
-
result = scanner.check @ptn
|
773
|
-
if result.nil?
|
774
|
-
ctxt.expecting(@msg)
|
775
|
-
else
|
776
|
-
ctxt.advance(scanner.matched_size)
|
777
|
-
ctxt.retn(result)
|
778
|
-
end
|
779
|
-
end
|
780
|
-
end
|
781
|
-
|
782
|
-
class AreParser < Parser # :nodoc:
|
783
|
-
init :vals, :msg
|
784
|
-
def _parse ctxt
|
785
|
-
if @vals.length > ctxt.available
|
786
|
-
return ctxt.expecting(@msg)
|
787
|
-
end
|
788
|
-
cur = 0
|
789
|
-
for cur in (0...@vals.length)
|
790
|
-
if @vals[cur] != ctxt.peek(cur)
|
791
|
-
return ctxt.expecting(@msg)
|
792
|
-
end
|
793
|
-
end
|
794
|
-
ctxt.advance(@vals.length)
|
795
|
-
ctxt.retn @vals
|
796
|
-
end
|
797
|
-
end
|
798
|
-
|
799
|
-
class StringCaseInsensitiveParser < Parser # :nodoc:
|
800
|
-
init :str, :msg
|
801
|
-
def _downcase c
|
802
|
-
case when c.ord >= ?A.ord && c.ord <= ?Z.ord then (c.ord + (?a.ord - ?A.ord)).chr else c end
|
803
|
-
end
|
804
|
-
private :_downcase
|
805
|
-
|
806
|
-
def _parse ctxt
|
807
|
-
if @str.length > ctxt.available
|
808
|
-
return ctxt.expecting(@msg)
|
809
|
-
end
|
810
|
-
cur = 0
|
811
|
-
for cur in (0...@str.length)
|
812
|
-
if _downcase(@str[cur]) != _downcase(ctxt.peek(cur))
|
813
|
-
return ctxt.expecting(@msg)
|
814
|
-
end
|
815
|
-
end
|
816
|
-
result = ctxt.src[ctxt.index, @str.length]
|
817
|
-
ctxt.advance(@str.length)
|
818
|
-
ctxt.retn result
|
819
|
-
end
|
820
|
-
end
|
821
|
-
|
822
|
-
class FragmentParser < Parser # :nodoc:
|
823
|
-
init :parser
|
824
|
-
def _parse ctxt
|
825
|
-
ind = ctxt.index
|
826
|
-
return false unless @parser._parse ctxt
|
827
|
-
ctxt.retn(ctxt.src[ind, ctxt.index - ind])
|
828
|
-
end
|
829
|
-
end
|
830
|
-
|
831
|
-
class TokenParser < Parser # :nodoc:
|
832
|
-
init :symbol, :parser
|
833
|
-
def _parse ctxt
|
834
|
-
ind = ctxt.index
|
835
|
-
return false unless @parser._parse ctxt
|
836
|
-
raw = ctxt.result
|
837
|
-
raw = ctxt.src[ind, ctxt.index - ind] unless raw.kind_of? String
|
838
|
-
ctxt.retn(Token.new(@symbol, raw, ind))
|
839
|
-
end
|
840
|
-
end
|
841
|
-
|
842
|
-
class NestedParser < Parser # :nodoc:
|
843
|
-
init :parser1, :parser2
|
844
|
-
def _parse ctxt
|
845
|
-
ind = ctxt.index
|
846
|
-
return false unless @parser1._parse ctxt
|
847
|
-
_run_nested(ind, ctxt, ctxt.result, @parser2)
|
848
|
-
end
|
849
|
-
private
|
850
|
-
def _run_nested(start, ctxt, src, parser)
|
851
|
-
ctxt.error = nil
|
852
|
-
new_ctxt = nil
|
853
|
-
if src.kind_of? String
|
854
|
-
new_ctxt = ParseContext.new(src)
|
855
|
-
return true if _run_parser parser, ctxt, new_ctxt
|
856
|
-
ctxt.index = start + new_ctxt.index
|
857
|
-
elsif src.kind_of? Array
|
858
|
-
new_ctxt = ParseContext.new(src)
|
859
|
-
return true if _run_parser parser, ctxt, new_ctxt
|
860
|
-
ctxt.index = start + _get_index(new_ctxt) unless new_ctxt.eof
|
861
|
-
else
|
862
|
-
new_ctxt = ParseContext.new([src])
|
863
|
-
return true if _run_parser parser, ctxt, new_ctxt
|
864
|
-
ctxt.index = ind unless new_ctxt.eof
|
865
|
-
end
|
866
|
-
ctxt.error.index = ctxt.index
|
867
|
-
false
|
868
|
-
end
|
869
|
-
def _get_index ctxt
|
870
|
-
cur = ctxt.current
|
871
|
-
return cur.index if cur.respond_to? :index
|
872
|
-
ctxt.index
|
873
|
-
end
|
874
|
-
def _run_parser parser, old_ctxt, new_ctxt
|
875
|
-
if parser._parse new_ctxt
|
876
|
-
old_ctxt.result = new_ctxt.result
|
877
|
-
true
|
878
|
-
else
|
879
|
-
old_ctxt.error = new_ctxt.error
|
880
|
-
false
|
881
|
-
end
|
882
|
-
end
|
883
|
-
end
|
884
|
-
|
885
|
-
class WatchParser < Parser # :nodoc:
|
886
|
-
init :proc
|
887
|
-
def _parse ctxt
|
888
|
-
@proc.call(ctxt.result)
|
889
|
-
true
|
890
|
-
end
|
891
|
-
end
|
892
|
-
|
893
|
-
class WatchnParser < Parser # :nodoc:
|
894
|
-
init :proc
|
895
|
-
def _parse ctxt
|
896
|
-
@proc.call(*ctxt.result)
|
897
|
-
true
|
898
|
-
end
|
899
|
-
end
|
900
|
-
|
901
|
-
class MapCurrentParser < Parser # :nodoc:
|
902
|
-
init :proc
|
903
|
-
def _parse ctxt
|
904
|
-
ctxt.result = @proc.call(ctxt.result)
|
905
|
-
true
|
906
|
-
end
|
907
|
-
end
|
908
|
-
|
909
|
-
class MapnCurrentParser < Parser # :nodoc:
|
910
|
-
init :proc
|
911
|
-
def _parse ctxt
|
912
|
-
ctxt.result = @proc.call(*ctxt.result)
|
913
|
-
true
|
914
|
-
end
|
915
|
-
end
|
916
|
-
|
917
|
-
class Repeat_Parser < Parser # :nodoc:
|
918
|
-
init :parser, :times
|
919
|
-
def _parse ctxt
|
920
|
-
@times.times do
|
921
|
-
return false unless @parser._parse ctxt
|
922
|
-
end
|
923
|
-
return true
|
924
|
-
end
|
925
|
-
end
|
926
|
-
|
927
|
-
class RepeatParser < Parser # :nodoc:
|
928
|
-
init :parser, :times
|
929
|
-
def _parse ctxt
|
930
|
-
result = []
|
931
|
-
@times.times do
|
932
|
-
return false unless @parser._parse ctxt
|
933
|
-
result << ctxt.result
|
934
|
-
end
|
935
|
-
return ctxt.retn(result)
|
936
|
-
end
|
937
|
-
end
|
938
|
-
|
939
|
-
class Many_Parser < Parser # :nodoc:
|
940
|
-
init :parser, :least
|
941
|
-
def _parse ctxt
|
942
|
-
@least.times do
|
943
|
-
return false unless @parser._parse ctxt
|
944
|
-
end
|
945
|
-
while true
|
946
|
-
ind = ctxt.index
|
947
|
-
if @parser._parse ctxt
|
948
|
-
return true if ind == ctxt.index # infinite loop
|
949
|
-
next
|
950
|
-
end
|
951
|
-
return ind == ctxt.index
|
952
|
-
end
|
953
|
-
end
|
954
|
-
end
|
955
|
-
|
956
|
-
class ManyParser < Parser # :nodoc:
|
957
|
-
init :parser, :least
|
958
|
-
def _parse ctxt
|
959
|
-
result = []
|
960
|
-
@least.times do
|
961
|
-
return false unless @parser._parse ctxt
|
962
|
-
result << ctxt.result
|
963
|
-
end
|
964
|
-
while true
|
965
|
-
ind = ctxt.index
|
966
|
-
if @parser._parse ctxt
|
967
|
-
result << ctxt.result
|
968
|
-
return ctxt.retn(result) if ind == ctxt.index # infinite loop
|
969
|
-
next
|
970
|
-
end
|
971
|
-
if ind == ctxt.index
|
972
|
-
return ctxt.retn(result)
|
973
|
-
else
|
974
|
-
return false
|
975
|
-
end
|
976
|
-
end
|
977
|
-
end
|
978
|
-
end
|
979
|
-
|
980
|
-
class Some_Parser < Parser # :nodoc:
|
981
|
-
init :parser, :least, :max
|
982
|
-
def _parse ctxt
|
983
|
-
@least.times { return false unless @parser._parse ctxt }
|
984
|
-
(@least...@max).each do
|
985
|
-
ind = ctxt.index
|
986
|
-
if @parser._parse ctxt
|
987
|
-
return true if ind == ctxt.index # infinite loop
|
988
|
-
next
|
989
|
-
end
|
990
|
-
return ind == ctxt.index
|
991
|
-
end
|
992
|
-
return true
|
993
|
-
end
|
994
|
-
end
|
995
|
-
|
996
|
-
class SomeParser < Parser # :nodoc:
|
997
|
-
init :parser, :least, :max
|
998
|
-
def _parse ctxt
|
999
|
-
result = []
|
1000
|
-
@least.times do
|
1001
|
-
return false unless @parser._parse ctxt
|
1002
|
-
result << ctxt.result
|
1003
|
-
end
|
1004
|
-
(@least...@max).each do
|
1005
|
-
ind = ctxt.index
|
1006
|
-
if @parser._parse ctxt
|
1007
|
-
result << ctxt.result
|
1008
|
-
return ctxt.retn(result) if ind == ctxt.index # infinite loop
|
1009
|
-
next
|
1010
|
-
end
|
1011
|
-
if ind == ctxt.index
|
1012
|
-
return ctxt.retn(result)
|
1013
|
-
else
|
1014
|
-
return false
|
1015
|
-
end
|
1016
|
-
end
|
1017
|
-
return ctxt.retn(result)
|
1018
|
-
end
|
1019
|
-
end
|
1020
|
-
|
1021
|
-
class OneParser < Parser # :nodoc:
|
1022
|
-
def _parse _ctxt
|
1023
|
-
true
|
1024
|
-
end
|
1025
|
-
end
|
1026
|
-
|
1027
|
-
class ZeroParser < Parser # :nodoc:
|
1028
|
-
def _parse ctxt
|
1029
|
-
return ctxt.failure
|
1030
|
-
end
|
1031
|
-
end
|
1032
|
-
|
1033
|
-
class GetIndexParser < Parser # :nodoc:
|
1034
|
-
def _parse ctxt
|
1035
|
-
ctxt.retn(ctxt.index)
|
1036
|
-
end
|
1037
|
-
end
|
1038
|
-
class SetIndexParser < Parser # :nodoc:
|
1039
|
-
init :index
|
1040
|
-
def _parse ctxt
|
1041
|
-
ctxt.index = @index
|
1042
|
-
end
|
1043
|
-
end
|
1044
|
-
|
1045
471
|
Nil = ValueParser.new(nil) # :nodoc:
|
1046
472
|
|
1047
473
|
end # module
|