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.
- checksums.yaml +4 -4
- data/lib/rparsec/context.rb +80 -78
- data/lib/rparsec/error.rb +21 -18
- data/lib/rparsec/expressions.rb +75 -163
- data/lib/rparsec/functor_mixin.rb +102 -0
- data/lib/rparsec/functors.rb +151 -255
- data/lib/rparsec/id_monad.rb +13 -11
- data/lib/rparsec/keywords.rb +95 -93
- data/lib/rparsec/locator.rb +27 -25
- data/lib/rparsec/misc.rb +14 -97
- data/lib/rparsec/monad.rb +53 -50
- data/lib/rparsec/operator_table.rb +89 -0
- data/lib/rparsec/operators.rb +85 -81
- data/lib/rparsec/parser.rb +397 -819
- data/lib/rparsec/parser_monad.rb +18 -16
- data/lib/rparsec/parsers.rb +922 -499
- data/lib/rparsec/token.rb +32 -30
- data/lib/rparsec.rb +7 -4
- metadata +11 -3
data/lib/rparsec/functors.rb
CHANGED
@@ -1,282 +1,178 @@
|
|
1
|
-
|
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
|
-
#
|
90
|
-
#
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
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
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
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
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
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
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
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
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
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
|
-
|
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
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
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
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
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
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
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
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
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
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
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
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
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
|
data/lib/rparsec/id_monad.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RParsec
|
2
4
|
|
3
|
-
class IdMonad
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
class IdMonad # :nodoc:
|
6
|
+
def value v
|
7
|
+
v
|
8
|
+
end
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
|
10
|
+
def bind prev
|
11
|
+
yield prev
|
12
|
+
end
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
+
def mplus a, _b
|
15
|
+
a
|
16
|
+
end
|
14
17
|
end
|
15
|
-
end
|
16
18
|
|
17
|
-
end # module
|
19
|
+
end # module
|
data/lib/rparsec/keywords.rb
CHANGED
@@ -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
|
-
#
|
8
|
+
# This class helps building lexers and parsers for keywords.
|
15
9
|
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
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
|
-
|
91
|
+
alias [] parser
|
90
92
|
|
91
|
-
|
93
|
+
private
|
92
94
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
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
|
-
|
104
|
-
|
105
|
-
|
105
|
+
def canonical_name(name)
|
106
|
+
case when @case_sensitive then name else name.downcase end
|
107
|
+
end
|
106
108
|
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|