yaparc 0.0.6 → 0.0.7
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.
- data/README +8 -0
- data/lib/yaparc.rb +43 -47
- data/tests/test_parser.rb +6 -0
- metadata +1 -4
- data/lib/parser_cps.rb +0 -319
- data/tests/test_parser_cps.rb +0 -38
data/README
CHANGED
data/lib/yaparc.rb
CHANGED
@@ -106,19 +106,16 @@ module Yaparc
|
|
106
106
|
FailParser.new
|
107
107
|
else
|
108
108
|
parser = if predicate.call(item[0][0])
|
109
|
-
# input = item[0][1]
|
110
109
|
SucceedParser.new(item[0][0], item[0][1])
|
111
110
|
else
|
112
111
|
FailParser.new
|
113
112
|
end
|
114
|
-
# parser.parse(input)
|
115
113
|
end
|
116
114
|
end
|
117
115
|
end
|
118
116
|
|
119
117
|
def parse(input)
|
120
|
-
parser = @parser.call(input)
|
121
|
-
case parser
|
118
|
+
case parser = @parser.call(input)
|
122
119
|
when SucceedParser
|
123
120
|
parser.parse(parser.remaining)
|
124
121
|
when FailParser
|
@@ -138,18 +135,22 @@ module Yaparc
|
|
138
135
|
args = []
|
139
136
|
remains = parsers.inject(input) do |accumulator, parser|
|
140
137
|
result = parser.parse(accumulator)
|
141
|
-
|
138
|
+
if result == []
|
139
|
+
break []
|
140
|
+
else
|
142
141
|
args << result[0][0]
|
143
142
|
result[0][1]
|
144
|
-
else
|
145
|
-
break []
|
146
143
|
end
|
147
144
|
end
|
148
|
-
|
149
|
-
retval = yield(*args)
|
150
|
-
[[retval, remains]]
|
151
|
-
else
|
145
|
+
if remains == []
|
152
146
|
[]
|
147
|
+
else
|
148
|
+
retval = if block_given?
|
149
|
+
yield(*args)
|
150
|
+
else
|
151
|
+
args.last
|
152
|
+
end
|
153
|
+
[[retval, remains]]
|
153
154
|
end
|
154
155
|
end
|
155
156
|
end # of initialize
|
@@ -173,36 +174,6 @@ module Yaparc
|
|
173
174
|
end
|
174
175
|
|
175
176
|
|
176
|
-
class ParserBase
|
177
|
-
include Parsable
|
178
|
-
|
179
|
-
def parse(input)
|
180
|
-
@parser.parse(input)
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
class AbstractParser
|
185
|
-
include Parsable
|
186
|
-
|
187
|
-
def parse(input, &block)
|
188
|
-
tree = @parser.call.parse(input)
|
189
|
-
if block_given?
|
190
|
-
@tree = yield tree
|
191
|
-
else
|
192
|
-
@tree = tree
|
193
|
-
end
|
194
|
-
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
class CharParser < ParserBase
|
199
|
-
|
200
|
-
def initialize(char)
|
201
|
-
equal_char = lambda {|i| i == char}
|
202
|
-
@parser = SatisfyParser.new(equal_char)
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
177
|
|
207
178
|
class StringParser
|
208
179
|
include Parsable
|
@@ -281,8 +252,24 @@ module Yaparc
|
|
281
252
|
end
|
282
253
|
|
283
254
|
|
284
|
-
class
|
255
|
+
class ParserBase
|
256
|
+
include Parsable
|
257
|
+
|
258
|
+
def parse(input)
|
259
|
+
@parser.parse(input)
|
260
|
+
end
|
261
|
+
end
|
285
262
|
|
263
|
+
class CharParser < ParserBase
|
264
|
+
|
265
|
+
def initialize(char)
|
266
|
+
equal_char = lambda {|i| i == char}
|
267
|
+
@parser = SatisfyParser.new(equal_char)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
|
272
|
+
class ZeroOneParser < ParserBase
|
286
273
|
def initialize(parser)
|
287
274
|
@parser = AltParser.new(parser, SucceedParser.new([]))
|
288
275
|
end
|
@@ -290,7 +277,6 @@ module Yaparc
|
|
290
277
|
|
291
278
|
|
292
279
|
class Ident < ParserBase
|
293
|
-
|
294
280
|
def initialize
|
295
281
|
@parser = SeqParser.new(
|
296
282
|
SatisfyParser.new(IS_LOWER),
|
@@ -328,7 +314,6 @@ module Yaparc
|
|
328
314
|
end
|
329
315
|
end
|
330
316
|
|
331
|
-
|
332
317
|
class Token < ParserBase
|
333
318
|
|
334
319
|
def initialize(parser)
|
@@ -338,7 +323,6 @@ module Yaparc
|
|
338
323
|
end
|
339
324
|
end
|
340
325
|
|
341
|
-
|
342
326
|
class Identifier < ParserBase
|
343
327
|
|
344
328
|
def initialize
|
@@ -346,7 +330,6 @@ module Yaparc
|
|
346
330
|
end
|
347
331
|
end
|
348
332
|
|
349
|
-
|
350
333
|
class Natural < ParserBase
|
351
334
|
|
352
335
|
def initialize
|
@@ -354,7 +337,6 @@ module Yaparc
|
|
354
337
|
end
|
355
338
|
end
|
356
339
|
|
357
|
-
|
358
340
|
class Symbol < ParserBase
|
359
341
|
|
360
342
|
def initialize(literal)
|
@@ -362,4 +344,18 @@ module Yaparc
|
|
362
344
|
end
|
363
345
|
end
|
364
346
|
|
347
|
+
class AbstractParser
|
348
|
+
include Parsable
|
349
|
+
|
350
|
+
def parse(input, &block)
|
351
|
+
tree = @parser.call.parse(input)
|
352
|
+
if block_given?
|
353
|
+
@tree = yield tree
|
354
|
+
else
|
355
|
+
@tree = tree
|
356
|
+
end
|
357
|
+
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
365
361
|
end # of Yaparc
|
data/tests/test_parser.rb
CHANGED
@@ -87,6 +87,12 @@ class YaparcTest < Test::Unit::TestCase
|
|
87
87
|
assert_equal [[["B"], "DEF"]], result
|
88
88
|
end
|
89
89
|
|
90
|
+
def test_seq_parse_without_block
|
91
|
+
parser = SeqParser.new(ItemParser.new, ItemParser.new)
|
92
|
+
result = parser.parse("abcdef")
|
93
|
+
assert_equal [["b", "cdef"]], result
|
94
|
+
end
|
95
|
+
|
90
96
|
def test_alt_parse
|
91
97
|
parser = AltParser.new(ItemParser.new, SucceedParser.new('d'))
|
92
98
|
result = parser.parse("abc")
|
metadata
CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.9.3
|
|
3
3
|
specification_version: 1
|
4
4
|
name: yaparc
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.0.
|
6
|
+
version: 0.0.7
|
7
7
|
date: 2008-01-07 00:00:00 +09:00
|
8
8
|
summary: Yet Another Combinator Parser Library
|
9
9
|
require_paths:
|
@@ -29,14 +29,11 @@ post_install_message:
|
|
29
29
|
authors:
|
30
30
|
- Akimichi Tatsukawa
|
31
31
|
files:
|
32
|
-
- tests/test_parser_cps.rb
|
33
32
|
- tests/test_parser.rb
|
34
33
|
- tests/test_calc.rb
|
35
|
-
- lib/parser_cps.rb
|
36
34
|
- lib/yaparc.rb
|
37
35
|
- README
|
38
36
|
test_files:
|
39
|
-
- tests/test_parser_cps.rb
|
40
37
|
- tests/test_parser.rb
|
41
38
|
- tests/test_calc.rb
|
42
39
|
rdoc_options: []
|
data/lib/parser_cps.rb
DELETED
@@ -1,319 +0,0 @@
|
|
1
|
-
|
2
|
-
module Yaparc
|
3
|
-
module Parsable
|
4
|
-
include Yaparc
|
5
|
-
|
6
|
-
attr_accessor :tree
|
7
|
-
|
8
|
-
IS_LOWER = lambda {|c| c >= 'a' and c <= 'z'}
|
9
|
-
IS_ALPHANUM = lambda {|c| (c >= 'a' and c <= 'z') or (c >= '0' and c <= '9')}
|
10
|
-
IS_DIGIT = lambda {|i| i > '0' and i < '9'}
|
11
|
-
IS_SPACE = lambda {|i| i == ' '}
|
12
|
-
|
13
|
-
# def self.included(mod)
|
14
|
-
# mod.extend ClassMethods
|
15
|
-
# end
|
16
|
-
|
17
|
-
def parse(input, cont, &block)
|
18
|
-
tree = @parser.call(input, cont)
|
19
|
-
if block_given?
|
20
|
-
@tree = yield tree
|
21
|
-
else
|
22
|
-
@tree = tree
|
23
|
-
end
|
24
|
-
cont.apply(input)
|
25
|
-
end
|
26
|
-
end # of Parsable
|
27
|
-
|
28
|
-
module Continuation
|
29
|
-
class Base
|
30
|
-
def apply(input)
|
31
|
-
@proc.call(input)
|
32
|
-
end
|
33
|
-
# def apply(arg, input = '')
|
34
|
-
# @proc.call(input,val)
|
35
|
-
# end
|
36
|
-
end
|
37
|
-
|
38
|
-
class StopCont < Base
|
39
|
-
def initialize
|
40
|
-
# @proc = lambda do |input|
|
41
|
-
# lambda{|input, val|
|
42
|
-
# [[val,input]]
|
43
|
-
# }
|
44
|
-
# end
|
45
|
-
@proc = lambda do |val, input|
|
46
|
-
[[val,input]]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
class ItemHeadCont < Base
|
54
|
-
def initialize(input, cont)
|
55
|
-
@proc = lambda do |val, input|
|
56
|
-
[[val,input]]
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
class ItemTailCont < Base
|
62
|
-
def initialize(cont)
|
63
|
-
@proc = lambda do |val, input|
|
64
|
-
[[val,input]]
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end # of Continuation
|
69
|
-
|
70
|
-
module Parser
|
71
|
-
class SucceedParser
|
72
|
-
include Parsable
|
73
|
-
def initialize(val)
|
74
|
-
@parser = lambda do |input, cont|
|
75
|
-
cont.apply(val)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
class FailParser
|
81
|
-
include Parsable
|
82
|
-
def initialize
|
83
|
-
@parser = lambda do |input|
|
84
|
-
[]
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
class ItemParser
|
90
|
-
include Parsable
|
91
|
-
def initialize(cont)
|
92
|
-
@parser = lambda do |input|
|
93
|
-
if input.nil? or input.empty?
|
94
|
-
FailParser.new(StopCont.new)
|
95
|
-
else
|
96
|
-
# head = input[0..0]
|
97
|
-
# tail = input[1..input.length]
|
98
|
-
ItemHeadCont.new(input,ItemTailCont.new(cont)).apply(input)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
class SatisfyParser
|
105
|
-
include Parsable
|
106
|
-
def initialize(predicate)
|
107
|
-
@parser = lambda do |input|
|
108
|
-
item = ItemParser.new.parse(input)
|
109
|
-
if item == []
|
110
|
-
FailParser.new.parse(input)
|
111
|
-
else
|
112
|
-
if predicate.call(item[0][0])
|
113
|
-
SucceedParser.new(item[0][0]).parse(item[0][1])
|
114
|
-
else
|
115
|
-
FailParser.new.parse(input)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
class SeqParser
|
123
|
-
include Parsable
|
124
|
-
def initialize(first, second, &block)
|
125
|
-
@parser = lambda do |input, cont|
|
126
|
-
SeqCont.new(first, second, cont).apply(input)
|
127
|
-
end
|
128
|
-
end # of initialize
|
129
|
-
|
130
|
-
class SeqCont < Continuation::Base
|
131
|
-
def initialize(first, second, cont)
|
132
|
-
@proc = lambda do |input|
|
133
|
-
first.parse(input, second.parse(input, cont))
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end # of SeqParser
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
class AltParser
|
142
|
-
include Parsable
|
143
|
-
def initialize(left, right)
|
144
|
-
@parser = lambda do |input, cont|
|
145
|
-
AltCont.new(left, right, cont).apply(input)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
class AltCont < Continuation::Base
|
149
|
-
def initialize(left, right, cont)
|
150
|
-
@proc = lambda do |input|
|
151
|
-
left.parse(input, cont) or right.parse(input, cont)
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end # of AltParser
|
156
|
-
|
157
|
-
class CharParser
|
158
|
-
include Parsable
|
159
|
-
def initialize(char)
|
160
|
-
equal_char = lambda {|i| i == char}
|
161
|
-
@parser = lambda do |input|
|
162
|
-
SatisfyParser.new(equal_char).parse(input)
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
class StringParser
|
168
|
-
include Parsable
|
169
|
-
def initialize(string)
|
170
|
-
@parser = lambda do |input|
|
171
|
-
result = ItemParser.new.parse(string)
|
172
|
-
if result == []
|
173
|
-
SucceedParser.new(result).parse(input) # FailParser.new.parse(input)
|
174
|
-
else
|
175
|
-
SeqParser.new(
|
176
|
-
CharParser.new(result[0][0]),
|
177
|
-
StringParser.new(result[0][1]),
|
178
|
-
SucceedParser.new(result[0][0] + result[0][1])
|
179
|
-
) do |char_result, string_result, succeed_result|
|
180
|
-
succeed_result
|
181
|
-
end.parse(input)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
class RegexParser
|
188
|
-
include Parsable
|
189
|
-
def initialize(regex)
|
190
|
-
@parser = lambda do |input|
|
191
|
-
if match = Regexp.new(regex).match(input)
|
192
|
-
[[match[0],match.post_match]]
|
193
|
-
else
|
194
|
-
[]
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
class ManyParser
|
201
|
-
include Parsable
|
202
|
-
def initialize(predicate)
|
203
|
-
@parser = lambda do |input|
|
204
|
-
AltParser.new(ManyOneParser.new(predicate), SucceedParser.new([])).parse(input)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
class ManyOneParser
|
210
|
-
include Parsable
|
211
|
-
def initialize(predicate)
|
212
|
-
@parser = lambda do |input|
|
213
|
-
SeqParser.new(
|
214
|
-
SatisfyParser.new(predicate),
|
215
|
-
ManyParser.new(predicate)
|
216
|
-
) do |v, vs|
|
217
|
-
if vs == []
|
218
|
-
v
|
219
|
-
else
|
220
|
-
v + vs.to_s
|
221
|
-
end
|
222
|
-
end.parse(input)
|
223
|
-
end
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
class ZeroOneParser
|
228
|
-
include Parsable
|
229
|
-
def initialize(parser)
|
230
|
-
@parser = lambda do |input|
|
231
|
-
AltParser.new(parser,
|
232
|
-
SucceedParser.new([])).parse(input)
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
class Ident
|
238
|
-
include Parsable
|
239
|
-
def initialize
|
240
|
-
@parser = lambda do |input|
|
241
|
-
SeqParser.new(
|
242
|
-
SatisfyParser.new(IS_LOWER),
|
243
|
-
ManyParser.new(IS_ALPHANUM)
|
244
|
-
) do |v, vs|
|
245
|
-
if vs == []
|
246
|
-
v
|
247
|
-
else
|
248
|
-
v + vs.to_s
|
249
|
-
end
|
250
|
-
end.parse(input)
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
class Nat
|
256
|
-
include Parsable
|
257
|
-
def initialize
|
258
|
-
@parser = lambda do |input|
|
259
|
-
SeqParser.new(ManyOneParser.new(IS_DIGIT)) do |vs|
|
260
|
-
if vs == []
|
261
|
-
vs
|
262
|
-
else
|
263
|
-
vs.to_i
|
264
|
-
end
|
265
|
-
end.parse(input)
|
266
|
-
end
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
|
-
class Space
|
271
|
-
include Parsable
|
272
|
-
def initialize
|
273
|
-
@parser = lambda do |input|
|
274
|
-
SeqParser.new(ManyParser.new(IS_SPACE)) do |vs|
|
275
|
-
[]
|
276
|
-
end.parse(input)
|
277
|
-
end
|
278
|
-
end
|
279
|
-
end
|
280
|
-
|
281
|
-
class Token
|
282
|
-
include Parsable
|
283
|
-
def initialize(parser)
|
284
|
-
@parser = lambda do |input|
|
285
|
-
SeqParser.new(Space.new, parser, Space.new) do |_, vs, _|
|
286
|
-
vs
|
287
|
-
end.parse(input)
|
288
|
-
end
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
class Identifier
|
293
|
-
include Parsable
|
294
|
-
def initialize
|
295
|
-
@parser = lambda do |input|
|
296
|
-
Token.new(Ident.new).parse(input)
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
class Natural
|
302
|
-
include Parsable
|
303
|
-
def initialize
|
304
|
-
@parser = lambda do |input|
|
305
|
-
Token.new(Nat.new).parse(input)
|
306
|
-
end
|
307
|
-
end
|
308
|
-
end
|
309
|
-
|
310
|
-
class Symbol
|
311
|
-
include Parsable
|
312
|
-
def initialize(literal)
|
313
|
-
@parser = lambda do |input|
|
314
|
-
Token.new(StringParser.new(literal)).parse(input)
|
315
|
-
end
|
316
|
-
end
|
317
|
-
end
|
318
|
-
end # of Parser
|
319
|
-
end # Yaparc
|
data/tests/test_parser_cps.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'lib/parser_cps.rb'
|
2
|
-
require 'test/unit'
|
3
|
-
require 'pp'
|
4
|
-
|
5
|
-
class YaparcTest < Test::Unit::TestCase
|
6
|
-
include ::Yaparc
|
7
|
-
|
8
|
-
|
9
|
-
def setup
|
10
|
-
@stop = Continuation::StopCont.new
|
11
|
-
end
|
12
|
-
|
13
|
-
|
14
|
-
def test_succeed_parse
|
15
|
-
parser = ::Yaparc::Parser::SucceedParser.new(1)
|
16
|
-
assert_equal [[1, "abs"]], parser.parse("abs", @stop)
|
17
|
-
# assert_equal [[1, "abs"]], parser.tree
|
18
|
-
# result = parser.parse("abs") do |result|
|
19
|
-
# result[0][0]
|
20
|
-
# end
|
21
|
-
# assert_equal 1, result
|
22
|
-
end
|
23
|
-
|
24
|
-
# def test_fail_parse
|
25
|
-
# parser = ::Yaparc::Parser::FailParser.new(@stop)
|
26
|
-
# result = parser.parse("abc")
|
27
|
-
# assert_equal [], result
|
28
|
-
# end
|
29
|
-
|
30
|
-
# def test_item_parse
|
31
|
-
# parser = ::Yaparc::Parser::ItemParser.new(@stop)
|
32
|
-
# result = parser.parse("")
|
33
|
-
# assert_equal [], result
|
34
|
-
# result = parser.parse("abc")
|
35
|
-
# assert_equal [["a", "bc"]], result
|
36
|
-
# end
|
37
|
-
end
|
38
|
-
|