rparsec2 1.2.1 → 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 +52 -7
  59. data/lib/rparsec/id_monad.rb +0 -19
@@ -0,0 +1,27 @@
1
+ require "rparsec/parser"
2
+
3
+ module RParsec
4
+ class ManyParser < Parser # :nodoc:
5
+ init :parser, :least
6
+ def _parse ctxt
7
+ result = []
8
+ @least.times do
9
+ return false unless @parser._parse ctxt
10
+ result << ctxt.result
11
+ end
12
+ while true
13
+ ind = ctxt.index
14
+ if @parser._parse ctxt
15
+ result << ctxt.result
16
+ return ctxt.retn(result) if ind == ctxt.index # infinite loop
17
+ next
18
+ end
19
+ if ind == ctxt.index
20
+ return ctxt.retn(result)
21
+ else
22
+ return false
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ require "rparsec/parser"
2
+
3
+ module RParsec
4
+ class MapCurrentParser < Parser # :nodoc:
5
+ init :proc
6
+ def _parse ctxt
7
+ ctxt.result = @proc.call(ctxt.result)
8
+ true
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ require "rparsec/parser"
2
+
3
+ module RParsec
4
+ class MapParser < Parser # :nodoc:
5
+ init :parser, :proc
6
+ def _parse ctxt
7
+ return false unless @parser._parse(ctxt)
8
+ ctxt.result = @proc.call(ctxt.result)
9
+ true
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ require "rparsec/parser"
2
+
3
+ module RParsec
4
+ class MapnCurrentParser < Parser # :nodoc:
5
+ init :proc
6
+ def _parse ctxt
7
+ ctxt.result = @proc.call(*ctxt.result)
8
+ true
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ require "rparsec/parser"
2
+
3
+ module RParsec
4
+ class MapnParser < Parser # :nodoc:
5
+ init :parser, :proc
6
+ def _parse ctxt
7
+ return false unless @parser._parse(ctxt)
8
+ ctxt.result = @proc.call(*ctxt.result)
9
+ true
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,47 @@
1
+ require "rparsec/parser"
2
+ require "rparsec/context"
3
+
4
+ module RParsec
5
+ class NestedParser < Parser # :nodoc:
6
+ init :parser1, :parser2
7
+ def _parse ctxt
8
+ ind = ctxt.index
9
+ return false unless @parser1._parse ctxt
10
+ _run_nested(ind, ctxt, ctxt.result, @parser2)
11
+ end
12
+ private
13
+ def _run_nested(start, ctxt, src, parser)
14
+ ctxt.error = nil
15
+ new_ctxt = nil
16
+ if src.kind_of? String
17
+ new_ctxt = ParseContext.new(src)
18
+ return true if _run_parser parser, ctxt, new_ctxt
19
+ ctxt.index = start + new_ctxt.index
20
+ elsif src.kind_of? Array
21
+ new_ctxt = ParseContext.new(src)
22
+ return true if _run_parser parser, ctxt, new_ctxt
23
+ ctxt.index = start + _get_index(new_ctxt) unless new_ctxt.eof
24
+ else
25
+ new_ctxt = ParseContext.new([src])
26
+ return true if _run_parser parser, ctxt, new_ctxt
27
+ ctxt.index = ind unless new_ctxt.eof
28
+ end
29
+ ctxt.error.index = ctxt.index
30
+ false
31
+ end
32
+ def _get_index ctxt
33
+ cur = ctxt.current
34
+ return cur.index if cur.respond_to? :index
35
+ ctxt.index
36
+ end
37
+ def _run_parser parser, old_ctxt, new_ctxt
38
+ if parser._parse new_ctxt
39
+ old_ctxt.result = new_ctxt.result
40
+ true
41
+ else
42
+ old_ctxt.error = new_ctxt.error
43
+ false
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,27 @@
1
+ require "rparsec/look_ahead_sensitive_parser"
2
+
3
+ module RParsec
4
+ class NotParser < LookAheadSensitiveParser # :nodoc:
5
+ def initialize(parser, msg, la = 1)
6
+ super(la)
7
+ @parser = parser
8
+ @msg = msg
9
+ @name = "~#{parser.name}"
10
+ end
11
+ def _parse ctxt
12
+ ind = ctxt.index
13
+ if @parser._parse ctxt
14
+ ctxt.index = ind
15
+ return ctxt.expecting(@msg)
16
+ end
17
+ return ctxt.retn(nil) if visible(ctxt, ind)
18
+ return false
19
+ end
20
+ def withLookahead(n)
21
+ NotParser.new(@parser, @msg, n)
22
+ end
23
+ def not()
24
+ @parser
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,9 @@
1
+ require "rparsec/parser"
2
+
3
+ module RParsec
4
+ class OneParser < Parser # :nodoc:
5
+ def _parse _ctxt
6
+ true
7
+ end
8
+ end
9
+ end
@@ -1,8 +1,25 @@
1
1
  module RParsec
2
2
  #
3
3
  # This class holds information about operator precedences and
4
- # associativities. #prefix, #postfix, #infixl, #infixr, #infixn can
5
- # be called to register operators.
4
+ # associativities. +prefix+, +postfix+, +infixl+, +infixr+, +infixn+ can be
5
+ # called to register operators.
6
+ #
7
+ # +prefix+ :: Defines a prefix operator that returns a unary +Proc+ object
8
+ # with a precedence associated. Returns +self+.
9
+ #
10
+ # +postfix+ :: Defines a postfix operator that returns a unary +Proc+ object
11
+ # with a precedence associated. Returns +self+.
12
+ #
13
+ # +infixl+ :: Defines a left associative infix operator that returns a
14
+ # binary +Proc+ object with a precedence associated. Returns
15
+ # +self+.
16
+ #
17
+ # +infixr+ :: Defines a right associative infix operator that returns a
18
+ # binary +Proc+ object with a precedence associated. Returns
19
+ # +self+.
20
+ #
21
+ # +infixn+ :: Defines a non-associative infix operator that returns a binary
22
+ # +Proc+ object with a precedence associated. Returns +self+.
6
23
  #
7
24
  class OperatorTable
8
25
 
@@ -12,15 +29,8 @@ module RParsec
12
29
  attr_reader :operators # :nodoc:
13
30
 
14
31
  #
15
- # Re-initialize the operator table.
16
- #
17
- def reinit # :nodoc:
18
- @operators = []
19
- end
20
-
21
- #
22
- # To create an OperatorTable instance. If a block is given, it is
23
- # invoked to do post-instantiation. For example:
32
+ # To create an OperatorTable instance. If a block is given, it is invoked
33
+ # to do post-instantiation. For example:
24
34
  #
25
35
  # OperatorTable.new do |tbl|
26
36
  # tbl.infixl(char(?+) >> Plus, 10)
@@ -30,60 +40,16 @@ module RParsec
30
40
  # tbl.prefix(char(?-) >> Neg, 50)
31
41
  # end
32
42
  #
33
- def self.new
34
- this = allocate
35
- this.reinit
36
- if block_given?
37
- yield this
38
- end
39
- this
40
- end
41
-
42
- #
43
- # Defines a prefix operator that returns a unary +Proc+ object with a precedence associated.
44
- # Returns +self+.
45
- #
46
- def prefix(op, precedence)
47
- add(:prefix, op, precedence)
48
- end
49
-
50
- #
51
- # Defines a postfix operator that returns a unary +Proc+ object with a precedence associated.
52
- # Returns +self+.
53
- #
54
- def postfix(op, precedence)
55
- add(:postfix, op, precedence)
56
- end
57
-
58
- #
59
- # Defines a left associative infix operator that returns a binary +Proc+ object with a precedence
60
- # associated. Returns +self+.
61
- #
62
- def infixl(op, precedence)
63
- add(:infixl, op, precedence)
64
- end
65
-
66
- #
67
- # Defines a right associative infix operator that returns a binary +Proc+ object with a precedence
68
- # associated. Returns +self+.
69
- #
70
- def infixr(op, precedence)
71
- add(:infixr, op, precedence)
72
- end
73
-
74
- #
75
- # Defines a non-associative infix operator that returns a binary +Proc+ object with a precedence
76
- # associated. Returns +self+.
77
- #
78
- def infixn(op, precedence)
79
- add(:infixn, op, precedence)
43
+ def initialize
44
+ @operators = []
45
+ block_given? and yield self
80
46
  end
81
47
 
82
- private
83
-
84
- def add(*entry)
85
- @operators << entry
86
- self
48
+ %i[prefix postfix infixl infixr infixn].each do |method|
49
+ define_method(method) do |op, precedence|
50
+ @operators << [method, op, precedence]
51
+ self
52
+ end
87
53
  end
88
54
  end
89
55
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "rparsec/functors"
4
4
  require "rparsec/monad"
5
- require "rparsec/misc"
5
+ require "rparsec/def_helper"
6
6
  require "rparsec/parser_monad"
7
7
  require "rparsec/context"
8
8
  require "rparsec/error"
@@ -17,7 +17,6 @@ module RParsec
17
17
  class Parser
18
18
  include Functors
19
19
  include Monad
20
- extend DefHelper
21
20
  MyMonad = ParserMonad.new
22
21
  attr_accessor :name
23
22
 
@@ -47,8 +46,14 @@ module RParsec
47
46
 
48
47
  def _display_current_input(input, _code, _index)
49
48
  return 'EOF' if input.nil?
50
- c = input
51
- case c when Integer then "'" << c << "'" when Token then c.text else c.to_s end
49
+ case (c = input)
50
+ when Integer
51
+ "'" << c << "'"
52
+ when Token
53
+ c.text
54
+ else
55
+ c.to_s
56
+ end
52
57
  end
53
58
 
54
59
  def _add_encountered_error(msg, encountered)
@@ -78,16 +83,6 @@ module RParsec
78
83
  _display_current_input(ctxt.error.input, src, ctxt.index)), src)
79
84
  end
80
85
 
81
- #
82
- # Set name for the parser. +self+ is returned.
83
- #
84
- def set_name(nm)
85
- @name = nm
86
- self
87
- end
88
-
89
- alias setName set_name
90
-
91
86
  #
92
87
  # <tt>a.map { |x| x + 1 }</tt> will first execute parser +a+, when
93
88
  # it succeeds, the associated block is executed to transform the
@@ -128,14 +123,14 @@ module RParsec
128
123
  # input consumption is undone.
129
124
  #
130
125
  def atomize
131
- AtomParser.new(self).setName(@name)
126
+ AtomParser.new(self).tap { |p| p.name = @name }
132
127
  end
133
128
 
134
129
  #
135
130
  # Create a new parser that looks at inputs whthout consuming them.
136
131
  #
137
132
  def peek
138
- PeekParser.new(self).setName(@name)
133
+ PeekParser.new(self).tap { |p| p.name = @name }
139
134
  end
140
135
 
141
136
  #
@@ -144,6 +139,7 @@ module RParsec
144
139
  def not(msg = "#{self} unexpected")
145
140
  NotParser.new(self, msg)
146
141
  end
142
+ alias ~ not
147
143
 
148
144
  #
149
145
  # To create a parser that does "look ahead" for _n_ inputs.
@@ -168,6 +164,7 @@ module RParsec
168
164
  def followed(other)
169
165
  FollowedParser.new(self, other)
170
166
  end
167
+ alias << followed
171
168
 
172
169
  #
173
170
  # To create a parser that repeats +self+ for a minimum +min+
@@ -184,6 +181,7 @@ module RParsec
184
181
  Some_Parser.new(self, min, max)
185
182
  end
186
183
  end
184
+ alias * repeat_
187
185
 
188
186
  #
189
187
  # To create a parser that repeats +self+ for a minimum +min+
@@ -460,10 +458,6 @@ module RParsec
460
458
  Parsers.sequence(operator, operand, &Idn)
461
459
  end
462
460
 
463
- alias ~ not
464
- alias << followed
465
- alias * repeat_
466
-
467
461
  def _parse(_ctxt)
468
462
  false
469
463
  end
@@ -3,23 +3,10 @@
3
3
  module RParsec
4
4
 
5
5
  class ParserMonad # :nodoc:
6
- def fail msg
7
- FailureParser.new(msg)
8
- end
9
-
10
- def value v
11
- return Nil if v.nil?
12
- ValueParser.new(v);
13
- end
14
-
15
- def bind(v, &proc)
16
- return v unless proc
17
- BoundParser.new(v, proc);
18
- end
19
-
20
- def mplus(p1, p2)
21
- PlusParser.new([p1, p2]);
22
- end
6
+ def fail(msg) = FailureParser.new(msg)
7
+ def value(v) = v.nil? ? Nil : ValueParser.new(v)
8
+ def bind(v, &block) = block_given? ? BoundParser.new(v, block) : v
9
+ def mplus(p1, p2) = PlusParser.new([p1, p2])
23
10
  end
24
11
 
25
12
  end # module