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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rparsec/alt_parser.rb +38 -0
  3. data/lib/rparsec/any_parser.rb +12 -0
  4. data/lib/rparsec/are_parser.rb +20 -0
  5. data/lib/rparsec/atom_parser.rb +16 -0
  6. data/lib/rparsec/best_parser.rb +44 -0
  7. data/lib/rparsec/bound_parser.rb +11 -0
  8. data/lib/rparsec/boundn_parser.rb +11 -0
  9. data/lib/rparsec/catch_parser.rb +17 -0
  10. data/lib/rparsec/context.rb +5 -3
  11. data/lib/rparsec/{misc.rb → def_helper.rb} +5 -8
  12. data/lib/rparsec/eof_parser.rb +11 -0
  13. data/lib/rparsec/error.rb +8 -12
  14. data/lib/rparsec/expect_parser.rb +18 -0
  15. data/lib/rparsec/expressions.rb +5 -19
  16. data/lib/rparsec/failure_parser.rb +10 -0
  17. data/lib/rparsec/failures.rb +31 -0
  18. data/lib/rparsec/followed_parser.rb +13 -0
  19. data/lib/rparsec/fragment_parser.rb +12 -0
  20. data/lib/rparsec/functor_mixin.rb +10 -31
  21. data/lib/rparsec/get_index_parser.rb +9 -0
  22. data/lib/rparsec/keywords.rb +9 -9
  23. data/lib/rparsec/lazy_parser.rb +10 -0
  24. data/lib/rparsec/locator.rb +9 -5
  25. data/lib/rparsec/look_ahead_sensitive_parser.rb +46 -0
  26. data/lib/rparsec/many__parser.rb +20 -0
  27. data/lib/rparsec/many_parser.rb +27 -0
  28. data/lib/rparsec/map_current_parser.rb +11 -0
  29. data/lib/rparsec/map_parser.rb +12 -0
  30. data/lib/rparsec/mapn_current_parser.rb +11 -0
  31. data/lib/rparsec/mapn_parser.rb +12 -0
  32. data/lib/rparsec/nested_parser.rb +47 -0
  33. data/lib/rparsec/not_parser.rb +27 -0
  34. data/lib/rparsec/one_parser.rb +9 -0
  35. data/lib/rparsec/operator_table.rb +29 -63
  36. data/lib/rparsec/parser.rb +14 -20
  37. data/lib/rparsec/parser_monad.rb +4 -17
  38. data/lib/rparsec/parsers.rb +52 -626
  39. data/lib/rparsec/peek_parser.rb +16 -0
  40. data/lib/rparsec/plus_parser.rb +32 -0
  41. data/lib/rparsec/regexp_parser.rb +17 -0
  42. data/lib/rparsec/repeat__parser.rb +13 -0
  43. data/lib/rparsec/repeat_parser.rb +15 -0
  44. data/lib/rparsec/satisfies_parser.rb +15 -0
  45. data/lib/rparsec/sequence_parser.rb +25 -0
  46. data/lib/rparsec/set_index_parser.rb +10 -0
  47. data/lib/rparsec/some__parser.rb +19 -0
  48. data/lib/rparsec/some_parser.rb +28 -0
  49. data/lib/rparsec/string_case_insensitive_parser.rb +26 -0
  50. data/lib/rparsec/throw_parser.rb +10 -0
  51. data/lib/rparsec/token.rb +9 -28
  52. data/lib/rparsec/token_parser.rb +14 -0
  53. data/lib/rparsec/value_parser.rb +10 -0
  54. data/lib/rparsec/watch_parser.rb +11 -0
  55. data/lib/rparsec/watchn_parser.rb +11 -0
  56. data/lib/rparsec/zero_parser.rb +9 -0
  57. data/lib/rparsec.rb +1 -1
  58. metadata +53 -8
  59. data/lib/rparsec/id_monad.rb +0 -19
@@ -1,6 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rparsec/parser'
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").setName(nm)
129
+ is(c, "'#{nm}' expected").tap { |p| p.name = nm }
91
130
  else
92
- is(c[0], "'#{c}' expected").setName(c)
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").setName("~#{nm}")
141
+ isnt(c, "'#{nm}' unexpected").tap { |p| p.name = "~#{nm}" }
103
142
  else
104
- isnt(c[0], "'#{c}' unexpected").setName("~#{c}")
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).setName('EOF')
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).setName(str)
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.setName('get_index')
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).setName('set_index')
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, to = as_num(from), as_num(to)
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).setName(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).setName(str)
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