rparsec2 1.1.0 → 1.2.1

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.
@@ -1,282 +1,178 @@
1
- module RParsec
2
-
3
- #
4
- # This module provides frequently used functors.
5
- #
6
- module Functors
7
- Id = proc { |x| x }
8
- Idn = proc { |*x| x }
9
- Neg = proc { |x| -x }
10
- Inc = proc { |x| x + 1 }
11
- Succ = proc { |x| x.succ }
12
- Dec = proc { |x| x - 1 }
13
- Plus = proc { |x, y| x + y }
14
- Minus = proc { |x, y| x - y }
15
- Mul = proc { |x, y| x * y }
16
- Div = proc { |x, y| x / y }
17
- Mod = proc { |x, y| x % y }
18
- Power = proc { |x, y| x**y }
19
- Not = proc { |x, _y| !x }
20
- And = proc { |x, y| x && y }
21
- Or = proc { |x, y| x || y }
22
- Xor = proc { |x, y| x ^ y }
23
- BitAnd = proc { |x, y| x & y }
24
- Union = proc { |x, y| x | y }
25
- Match = proc { |x, y| x =~ y }
26
- Eq = proc { |x, y| x == y }
27
- Ne = proc { |x, y| x != y }
28
- Lt = proc { |x, y| x < y }
29
- Gt = proc { |x, y| x > y }
30
- Le = proc { |x, y| x <= y }
31
- Ge = proc { |x, y| x >= y }
32
- Compare = proc { |x, y| x <=> y }
33
- Call = proc { |x, y| x.call(y) }
34
- Feed = proc { |x, y| y.call(x) }
35
- Fst = proc { |x, _| x }
36
- Snd = proc { |_, x| x }
37
- At = proc { |x, y| x[y] }
38
- To_a = proc { |x| x.to_a }
39
- To_s = proc { |x| x.to_s }
40
- To_i = proc { |x| x.to_i }
41
- To_sym = proc { |x| x.to_sym }
42
- To_f = proc { |x| x.to_f }
43
-
44
- #
45
- # Get a Proc, when called, always return the given value.
46
- #
47
- def const(v)
48
- proc { |_| v }
49
- end
1
+ # frozen_string_literal: true
50
2
 
51
- #
52
- # Get a Proc, when called, return the nth parameter.
53
- #
54
- def nth(n)
55
- proc { |*args| args[n] }
56
- end
57
-
58
- #
59
- # Create a Proc, which expects the two parameters
60
- # in the reverse order of _block_.
61
- #
62
- def flip(&block)
63
- proc { |x, y| block.call(y, x) }
64
- end
65
-
66
- #
67
- # Create a Proc, when called, the parameter is
68
- # first passed into _f2_, _f1_ is called in turn
69
- # with the return value from _other_.
70
- #
71
- def compose(f1, f2)
72
- proc { |*x| f1.call(f2.call(*x)) }
73
- end
74
-
75
- #
76
- # Create a Proc that's curriable.
77
- # When curried, parameters are passed in from left to right.
78
- # i.e. curry(closure).call(a).call(b) is quivalent to closure.call(a,b) .
79
- # _block_ is encapsulated under the hood to perform the actual
80
- # job when currying is done.
81
- # arity explicitly specifies the number of parameters to curry.
82
- #
83
- def curry(arity, &block)
84
- fail "cannot curry for unknown arity" if arity < 0
85
- Functors.make_curry(arity, &block)
86
- end
3
+ module RParsec
87
4
 
88
5
  #
89
- # Create a Proc that's curriable.
90
- # When curried, parameters are passed in from right to left.
91
- # i.e. reverse_curry(closure).call(a).call(b) is quivalent to closure.call(b,a) .
92
- # _block_ is encapsulated under the hood to perform the actual
93
- # job when currying is done.
94
- # arity explicitly specifies the number of parameters to curry.
95
- #
96
- def reverse_curry(arity, &block)
97
- fail "cannot curry for unknown arity" if arity < 0
98
- Functors.make_reverse_curry(arity, &block)
99
- end
6
+ # This module provides frequently used functors.
7
+ #
8
+ module Functors
9
+ Id = proc { |x| x }
10
+ Idn = proc { |*x| x }
11
+ Neg = proc { |x| -x }
12
+ Inc = proc { |x| x + 1 }
13
+ Succ = proc { |x| x.succ }
14
+ Dec = proc { |x| x - 1 }
15
+ Plus = proc { |x, y| x + y }
16
+ Minus = proc { |x, y| x - y }
17
+ Mul = proc { |x, y| x * y }
18
+ Div = proc { |x, y| x / y }
19
+ Mod = proc { |x, y| x % y }
20
+ Power = proc { |x, y| x**y }
21
+ Not = proc { |x, _y| !x }
22
+ And = proc { |x, y| x && y }
23
+ Or = proc { |x, y| x || y }
24
+ Xor = proc { |x, y| x ^ y }
25
+ BitAnd = proc { |x, y| x & y }
26
+ Union = proc { |x, y| x | y }
27
+ Match = proc { |x, y| x =~ y }
28
+ Eq = proc { |x, y| x == y }
29
+ Ne = proc { |x, y| x != y }
30
+ Lt = proc { |x, y| x < y }
31
+ Gt = proc { |x, y| x > y }
32
+ Le = proc { |x, y| x <= y }
33
+ Ge = proc { |x, y| x >= y }
34
+ Compare = proc { |x, y| x <=> y }
35
+ Call = proc { |x, y| x.call(y) }
36
+ Feed = proc { |x, y| y.call(x) }
37
+ Fst = proc { |x, _| x }
38
+ Snd = proc { |_, x| x }
39
+ At = proc { |x, y| x[y] }
40
+ To_a = proc { |x| x.to_a }
41
+ To_s = proc { |x| x.to_s }
42
+ To_i = proc { |x| x.to_i }
43
+ To_sym = proc { |x| x.to_sym }
44
+ To_f = proc { |x| x.to_f }
45
+
46
+ #
47
+ # Get a +Proc+, when called, always return the given value.
48
+ #
49
+ def const(v)
50
+ proc { |_| v }
51
+ end
100
52
 
101
- #
102
- # Uncurry a curried closure.
103
- #
104
- def uncurry(&block)
105
- return block unless block.arity == 1
106
- proc do |*args|
107
- result = block
108
- args.each do |a|
109
- result = result.call(a)
110
- end
111
- result
53
+ #
54
+ # Get a +Proc+, when called, return the <tt>n</tt>th parameter.
55
+ #
56
+ def nth(n)
57
+ proc { |*args| args[n] }
112
58
  end
113
- end
114
59
 
115
- #
116
- # Uncurry a reverse curried closure.
117
- #
118
- def reverse_uncurry(&block)
119
- return block unless block.arity == 1
120
- proc do |*args|
121
- result = block
122
- args.reverse_each do |a|
123
- result = result.call(a)
124
- end
125
- result
60
+ #
61
+ # Create a +Proc+, which expects the two parameters in the reverse
62
+ # order of +block+.
63
+ #
64
+ def flip(&block)
65
+ proc { |x, y| block.call(y, x) }
126
66
  end
127
- end
128
67
 
129
- #
130
- # Create a Proc, when called,
131
- # repeatedly call _block_ for _n_ times.
132
- # The same arguments are passed to each invocation.
133
- #
134
- def repeat(n, &block)
135
- proc do |*args|
136
- result = nil
137
- n.times { result = block.call(*args) }
138
- result
68
+ #
69
+ # Create a +Proc+, when called, the parameter is first passed into
70
+ # +f2+, +f1+ is called in turn with the return value from +f2+.
71
+ #
72
+ def compose(f1, f2)
73
+ proc { |*x| f1.call(f2.call(*x)) }
139
74
  end
140
- end
141
75
 
142
- #
143
- # Create a Proc, when called,
144
- # repeatedly call _block_ for _n_ times.
145
- # At each iteration, return value from the previous iteration
146
- # is used as parameter.
147
- #
148
- def power(n, &block)
149
- return const(nil) if n <= 0
150
- return block if n == 1
151
- proc do |*args|
152
- result = block.call(*args)
153
- (n - 1).times { result = block.call(result) }
154
- result
76
+ #
77
+ # Create a +Proc+ that's curriable. When curried, parameters are
78
+ # passed in from left to right.
79
+ # i.e. <tt>curry(closure).call(a).call(b)</tt> is quivalent to
80
+ # <tt>closure.call(a,b)</tt>. +block+ is encapsulated under the
81
+ # hood to perform the actual job when currying is done. +arity+
82
+ # explicitly specifies the number of parameters to curry.
83
+ #
84
+ def curry(arity, &block)
85
+ fail "cannot curry for unknown arity" if arity < 0
86
+ Functors.make_curry(arity, &block)
155
87
  end
156
- end
157
88
 
158
- extend self
89
+ #
90
+ # Create a +Proc+ that's curriable. When curried, parameters are
91
+ # passed in from right to left.
92
+ # i.e. <tt>reverse_curry(closure).call(a).call(b)</tt> is
93
+ # quivalent to <tt>closure.call(b, a)</tt>. +block+ is
94
+ # encapsulated under the hood to perform the actual job when
95
+ # currying is done. +arity+ explicitly specifies the number of
96
+ # parameters to curry.
97
+ #
98
+ def reverse_curry(arity, &block)
99
+ fail "cannot curry for unknown arity" if arity < 0
100
+ Functors.make_reverse_curry(arity, &block)
101
+ end
159
102
 
160
- def self.make_curry(arity, &block)
161
- return block if arity <= 1
162
- proc do |x|
163
- make_curry(arity - 1) do |*rest|
164
- block.call(*rest.insert(0, x))
103
+ #
104
+ # Uncurry a curried closure.
105
+ #
106
+ def uncurry(&block)
107
+ return block unless block.arity == 1
108
+ proc do |*args|
109
+ result = block
110
+ args.each do |a|
111
+ result = result.call(a)
112
+ end
113
+ result
165
114
  end
166
115
  end
167
- end
168
116
 
169
- def self.make_reverse_curry(arity, &block)
170
- return block if arity <= 1
171
- proc do |x|
172
- make_reverse_curry(arity - 1) do |*rest|
173
- block.call(*rest << x)
117
+ #
118
+ # Uncurry a reverse curried closure.
119
+ #
120
+ def reverse_uncurry(&block)
121
+ return block unless block.arity == 1
122
+ proc do |*args|
123
+ result = block
124
+ args.reverse_each do |a|
125
+ result = result.call(a)
126
+ end
127
+ result
174
128
  end
175
129
  end
176
- end
177
- end
178
-
179
- #
180
- # This module provides instance methods that
181
- # manipulate closures in a functional style.
182
- # It is typically included in Proc and Method.
183
- #
184
- module FunctorMixin
185
- #
186
- # Create a Proc, which expects the two parameters
187
- # in the reverse order of _self_.
188
- #
189
- def flip
190
- Functors.flip(&self)
191
- end
192
-
193
- #
194
- # Create a Proc, when called, the parameter is
195
- # first passed into _other_, _self_ is called in turn
196
- # with the return value from _other_.
197
- #
198
- def compose(other)
199
- Functors.compose(self, other)
200
- end
201
-
202
- alias << compose
203
130
 
204
- #
205
- # a >> b is equivalent to b << a
206
- #
207
- def >>(other)
208
- other << self
209
- end
210
-
211
- #
212
- # Create a Proc that's curriable.
213
- # When curried, parameters are passed in from left to right.
214
- # i.e. closure.curry.call(a).call(b) is quivalent to closure.call(a,b) .
215
- # _self_ is encapsulated under the hood to perform the actual
216
- # job when currying is done.
217
- # _ary_ explicitly specifies the number of parameters to curry.
218
- #
219
- # *IMPORTANT*
220
- # Proc and Method have built-in curry.
221
- # but the arity always return -1.
222
- # So, curry.reverse_curry does not work as expected.
223
- # You need to use the "using FunctorMixin"
224
- # See the "functor_test.rb"
225
- [Proc, Method].each do |klass|
226
- refine klass do
227
- def curry(ary = arity)
228
- Functors.curry(ary, &self)
131
+ #
132
+ # Create a +Proc+, when called, repeatedly call +block+ for +n+
133
+ # times. The same arguments are passed to each invocation.
134
+ #
135
+ def repeat(n, &block)
136
+ proc do |*args|
137
+ result = nil
138
+ n.times { result = block.call(*args) }
139
+ result
229
140
  end
230
141
  end
231
- end
232
-
233
- #
234
- # Create a Proc that's curriable.
235
- # When curried, parameters are passed in from right to left.
236
- # i.e. closure.reverse_curry.call(a).call(b) is quivalent to closure.call(b,a) .
237
- # _self_ is encapsulated under the hood to perform the actual
238
- # job when currying is done.
239
- # _ary_ explicitly specifies the number of parameters to curry.
240
- #
241
- def reverse_curry(ary = arity)
242
- Functors.reverse_curry(ary, &self)
243
- end
244
142
 
245
- #
246
- # Uncurry a curried closure.
247
- #
248
- def uncurry
249
- Functors.uncurry(&self)
250
- end
143
+ #
144
+ # Create a +Proc+, when called, repeatedly call +block+ for +n+
145
+ # times. \At each iteration, return value from the previous
146
+ # iteration is used as parameter.
147
+ #
148
+ def power(n, &block)
149
+ return const(nil) if n <= 0
150
+ return block if n == 1
151
+ proc do |*args|
152
+ result = block.call(*args)
153
+ (n - 1).times { result = block.call(result) }
154
+ result
155
+ end
156
+ end
251
157
 
252
- #
253
- # Uncurry a reverse curried closure.
254
- #
255
- def reverse_uncurry
256
- Functors.reverse_uncurry(&self)
257
- end
158
+ extend self
258
159
 
259
- #
260
- # Create a Proc, when called,
261
- # repeatedly call _self_ for _n_ times.
262
- # The same arguments are passed to each invocation.
263
- #
264
- def repeat(n)
265
- Functors.repeat(n, &self)
266
- end
267
- #
160
+ def self.make_curry(arity, &block)
161
+ return block if arity <= 1
162
+ proc do |x|
163
+ make_curry(arity - 1) do |*rest|
164
+ block.call(*rest.insert(0, x))
165
+ end
166
+ end
167
+ end
268
168
 
269
- # Create a Proc, when called,
270
- # repeatedly call _self_ for _n_ times.
271
- # At each iteration, return value from the previous iteration
272
- # is used as parameter.
273
- #
274
- def power(n)
275
- Functors.power(n, &self)
169
+ def self.make_reverse_curry(arity, &block)
170
+ return block if arity <= 1
171
+ proc do |x|
172
+ make_reverse_curry(arity - 1) do |*rest|
173
+ block.call(*rest << x)
174
+ end
175
+ end
176
+ end
276
177
  end
277
-
278
- alias ** power
279
- alias * repeat
280
- end
281
-
282
178
  end # module
@@ -1,17 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RParsec
2
4
 
3
- class IdMonad
4
- def value v
5
- v
6
- end
5
+ class IdMonad # :nodoc:
6
+ def value v
7
+ v
8
+ end
7
9
 
8
- def bind prev
9
- yield prev
10
- end
10
+ def bind prev
11
+ yield prev
12
+ end
11
13
 
12
- def mplus a, _b
13
- a
14
+ def mplus a, _b
15
+ a
16
+ end
14
17
  end
15
- end
16
18
 
17
- end # module
19
+ end # module
@@ -1,114 +1,116 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rparsec/parser'
2
4
 
3
5
  module RParsec
4
6
 
5
- #
6
- # This class helps building lexers and parsers for keywords.
7
- #
8
- class Keywords
9
- extend Parsers
10
-
11
- private_class_method :new
12
-
13
7
  #
14
- # The symbol used to identify a keyword token
8
+ # This class helps building lexers and parsers for keywords.
15
9
  #
16
- attr_reader :keyword_symbol
17
-
18
- #
19
- # The lexer that parses all the keywords represented
20
- #
21
- attr_reader :lexer
22
-
23
- #
24
- # Do we lex case sensitively?
25
- #
26
- def case_sensitive?
27
- @case_sensitive
28
- end
10
+ class Keywords
11
+ extend Parsers
12
+
13
+ private_class_method :new
14
+
15
+ #
16
+ # The symbol used to identify a keyword token
17
+ #
18
+ attr_reader :keyword_symbol
19
+
20
+ #
21
+ # The lexer that parses all the keywords represented
22
+ #
23
+ attr_reader :lexer
24
+
25
+ #
26
+ # Do we lex case sensitively?
27
+ #
28
+ def case_sensitive?
29
+ @case_sensitive
30
+ end
29
31
 
30
- #
31
- # To create an instance that lexes the given keywords
32
- # case sensitively.
33
- # _default_lexer_ is used to lex a token first, the token text is then compared with
34
- # the given keywords. If it matches any of the keyword, a keyword token is generated instead
35
- # using _keyword_symbol_.
36
- # The _block_ parameter, if present, is used to convert the token text to another object
37
- # when the token is recognized during grammar parsing phase.
38
- #
39
- def self.case_sensitive(words, default_lexer = word.token(:word), keyword_symbol = :keyword, &block)
40
- new(words, true, default_lexer, keyword_symbol, &block)
41
- end
32
+ #
33
+ # To create an instance that lexes the given keywords case
34
+ # sensitively. +default_lexer+ is used to lex a token first, the
35
+ # token text is then compared with the given keywords. If it
36
+ # matches any of the keyword, a keyword token is generated instead
37
+ # using +keyword_symbol+. The +block+ parameter, if present, is
38
+ # used to convert the token text to another object when the token
39
+ # is recognized during grammar parsing phase.
40
+ #
41
+ def self.case_sensitive(words, default_lexer = word.token(:word), keyword_symbol = :keyword, &block)
42
+ new(words, true, default_lexer, keyword_symbol, &block)
43
+ end
42
44
 
43
- #
44
- # To create an instance that lexes the given keywords
45
- # case insensitively.
46
- # _default_lexer_ is used to lex a token first, the token text is then compared with
47
- # the given keywords. If it matches any of the keyword, a keyword token is generated instead
48
- # using _keyword_symbol_.
49
- # The _block_ parameter, if present, is used to convert the token text to another object
50
- # when the token is recognized during parsing phase.
51
- #
52
- def self.case_insensitive(words, default_lexer = word.token(:word), keyword_symbol = :keyword, &block)
53
- new(words, false, default_lexer, keyword_symbol, &block)
54
- end
45
+ #
46
+ # To create an instance that lexes the given keywords case
47
+ # insensitively. +default_lexer+ is used to lex a token first,
48
+ # the token text is then compared with the given keywords. If it
49
+ # matches any of the keyword, a keyword token is generated instead
50
+ # using +keyword_symbol+. The +block+ parameter, if present, is
51
+ # used to convert the token text to another object when the token
52
+ # is recognized during parsing phase.
53
+ #
54
+ def self.case_insensitive(words, default_lexer = word.token(:word), keyword_symbol = :keyword, &block)
55
+ new(words, false, default_lexer, keyword_symbol, &block)
56
+ end
55
57
 
56
- # scanner has to return a string
57
- def initialize(words, case_sensitive, default_lexer, keyword_symbol, &block)
58
- @default_lexer, @case_sensitive, @keyword_symbol = default_lexer, case_sensitive, keyword_symbol
59
- # this guarantees that we have copy of the words array and all the word strings.
60
- words = copy_words(words, case_sensitive)
61
- @name_map = {}
62
- @symbol_map = {}
63
- word_map = {}
64
- words.each do |w|
65
- symbol = "#{keyword_symbol}:#{w}".to_sym
66
- word_map[w] = symbol
67
- parser = Parsers.token(symbol, &block)
68
- @symbol_map["#{w}".to_sym] = parser
69
- @name_map[w] = parser
58
+ # scanner has to return a string
59
+ def initialize(words, case_sensitive, default_lexer, keyword_symbol, &block)
60
+ @default_lexer, @case_sensitive, @keyword_symbol = default_lexer, case_sensitive, keyword_symbol
61
+ # this guarantees that we have copy of the words array and all the word strings.
62
+ words = copy_words(words, case_sensitive)
63
+ @name_map = {}
64
+ @symbol_map = {}
65
+ word_map = {}
66
+ words.each do |w|
67
+ symbol = "#{keyword_symbol}:#{w}".to_sym
68
+ word_map[w] = symbol
69
+ parser = Parsers.token(symbol, &block)
70
+ @symbol_map["#{w}".to_sym] = parser
71
+ @name_map[w] = parser
72
+ end
73
+ @lexer = make_lexer(default_lexer, word_map)
70
74
  end
71
- @lexer = make_lexer(default_lexer, word_map)
72
- end
73
75
 
74
- #
75
- # Get the parser that recognizes the token of the given keyword during the parsing phase.
76
- #
77
- def parser(key)
78
- result = nil
79
- if key.kind_of? String
80
- name = canonical_name(key)
81
- result = @name_map[name]
82
- else
83
- result = @symbol_map[key]
76
+ #
77
+ # Get the parser that recognizes the token of the given keyword during the parsing phase.
78
+ #
79
+ def parser(key)
80
+ result = nil
81
+ if key.kind_of? String
82
+ name = canonical_name(key)
83
+ result = @name_map[name]
84
+ else
85
+ result = @symbol_map[key]
86
+ end
87
+ raise ArgumentError, "parser not found for #{key}" if result.nil?
88
+ result
84
89
  end
85
- raise ArgumentError, "parser not found for #{key}" if result.nil?
86
- result
87
- end
88
90
 
89
- alias [] parser
91
+ alias [] parser
90
92
 
91
- private
93
+ private
92
94
 
93
- def make_lexer(default_lexer, word_map)
94
- default_lexer.map do |tok|
95
- text, ind = tok.text, tok.index
96
- key = canonical_name(text)
97
- my_symbol = word_map[key]
98
- case when my_symbol.nil? then tok
99
- else Token.new(my_symbol, text, ind) end
95
+ def make_lexer(default_lexer, word_map)
96
+ default_lexer.map do |tok|
97
+ text, ind = tok.text, tok.index
98
+ key = canonical_name(text)
99
+ my_symbol = word_map[key]
100
+ case when my_symbol.nil? then tok
101
+ else Token.new(my_symbol, text, ind) end
102
+ end
100
103
  end
101
- end
102
104
 
103
- def canonical_name(name)
104
- case when @case_sensitive then name else name.downcase end
105
- end
105
+ def canonical_name(name)
106
+ case when @case_sensitive then name else name.downcase end
107
+ end
106
108
 
107
- def copy_words(words, case_sensitive)
108
- words.map do |w|
109
- case when case_sensitive then w.dup else w.downcase end
109
+ def copy_words(words, case_sensitive)
110
+ words.map do |w|
111
+ case when case_sensitive then w.dup else w.downcase end
112
+ end
110
113
  end
111
114
  end
112
- end
113
115
 
114
- end # module
116
+ end # module