yaparc 0.0.1 → 0.0.3
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 +7 -0
- data/lib/parser.rb +33 -5
- data/lib/parser_cps.rb +319 -0
- data/lib/yaparc.rb +299 -0
- data/tests/test_parser.rb +24 -0
- data/tests/test_parser_cps.rb +38 -0
- metadata +9 -5
data/README
CHANGED
data/lib/parser.rb
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
module Yaparc
|
3
3
|
module Parsable
|
4
4
|
include Yaparc
|
5
|
-
|
5
|
+
|
6
|
+
attr_accessor :tree
|
7
|
+
|
6
8
|
IS_LOWER = lambda {|c| c >= 'a' and c <= 'z'}
|
7
9
|
IS_ALPHANUM = lambda {|c| (c >= 'a' and c <= 'z') or (c >= '0' and c <= '9')}
|
8
10
|
IS_DIGIT = lambda {|i| i > '0' and i < '9'}
|
@@ -13,8 +15,13 @@ module Yaparc
|
|
13
15
|
end
|
14
16
|
|
15
17
|
|
16
|
-
def parse(input)
|
17
|
-
@parser.call(input)
|
18
|
+
def parse(input, &block)
|
19
|
+
tree = @parser.call(input)
|
20
|
+
if block_given?
|
21
|
+
@tree = yield tree
|
22
|
+
else
|
23
|
+
@tree = tree
|
24
|
+
end
|
18
25
|
end
|
19
26
|
|
20
27
|
def eval
|
@@ -143,8 +150,7 @@ module Yaparc
|
|
143
150
|
@parser = lambda do |input|
|
144
151
|
result = ItemParser.new.parse(string)
|
145
152
|
if result == []
|
146
|
-
SucceedParser.new(result).parse(input)
|
147
|
-
# FailParser.new.parse(input)
|
153
|
+
SucceedParser.new(result).parse(input) # FailParser.new.parse(input)
|
148
154
|
else
|
149
155
|
SeqParser.new(
|
150
156
|
CharParser.new(result[0][0]),
|
@@ -158,6 +164,19 @@ module Yaparc
|
|
158
164
|
end
|
159
165
|
end
|
160
166
|
|
167
|
+
class RegexParser
|
168
|
+
include Parsable
|
169
|
+
def initialize(regex)
|
170
|
+
@parser = lambda do |input|
|
171
|
+
if match = Regexp.new(regex).match(input)
|
172
|
+
[[match[0],match.post_match]]
|
173
|
+
else
|
174
|
+
[]
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
161
180
|
class ManyParser
|
162
181
|
include Parsable
|
163
182
|
def initialize(predicate)
|
@@ -185,6 +204,15 @@ module Yaparc
|
|
185
204
|
end
|
186
205
|
end
|
187
206
|
|
207
|
+
class ZeroOneParser
|
208
|
+
include Parsable
|
209
|
+
def initialize(parser)
|
210
|
+
@parser = lambda do |input|
|
211
|
+
AltParser.new(parser,
|
212
|
+
SucceedParser.new([])).parse(input)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
188
216
|
|
189
217
|
class Ident
|
190
218
|
include Parsable
|
data/lib/parser_cps.rb
ADDED
@@ -0,0 +1,319 @@
|
|
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/lib/yaparc.rb
ADDED
@@ -0,0 +1,299 @@
|
|
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
|
+
|
18
|
+
def parse(input, &block)
|
19
|
+
tree = @parser.call(input)
|
20
|
+
if block_given?
|
21
|
+
@tree = yield tree
|
22
|
+
else
|
23
|
+
@tree = tree
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def eval
|
28
|
+
tree = parse(input)
|
29
|
+
end
|
30
|
+
|
31
|
+
def define_parser
|
32
|
+
raise
|
33
|
+
end
|
34
|
+
|
35
|
+
module ClassMethods
|
36
|
+
def included(mod)
|
37
|
+
end
|
38
|
+
|
39
|
+
# def self.initialize
|
40
|
+
# @parser = @@parser
|
41
|
+
# end
|
42
|
+
|
43
|
+
def define_parser(&block)
|
44
|
+
@@parser = lambda do |input|
|
45
|
+
parser = yield
|
46
|
+
parser.parse(input)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end # of Parsable
|
51
|
+
|
52
|
+
class SucceedParser
|
53
|
+
include Parsable
|
54
|
+
def initialize(value)
|
55
|
+
@parser = lambda {|input| [[value, input]]}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class FailParser
|
60
|
+
include Parsable
|
61
|
+
def initialize
|
62
|
+
@parser = lambda {|input| []}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class ItemParser
|
67
|
+
include Parsable
|
68
|
+
def initialize
|
69
|
+
@parser = lambda do |input|
|
70
|
+
if input.nil? or input.empty?
|
71
|
+
[]
|
72
|
+
else
|
73
|
+
[[input[0..0],input[1..input.length]]]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class SatisfyParser
|
80
|
+
include Parsable
|
81
|
+
def initialize(predicate)
|
82
|
+
@parser = lambda do |input|
|
83
|
+
item = ItemParser.new.parse(input)
|
84
|
+
if item == []
|
85
|
+
FailParser.new.parse(input)
|
86
|
+
else
|
87
|
+
if predicate.call(item[0][0])
|
88
|
+
SucceedParser.new(item[0][0]).parse(item[0][1])
|
89
|
+
else
|
90
|
+
FailParser.new.parse(input)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class SeqParser
|
98
|
+
include Parsable
|
99
|
+
def initialize(*parsers, &block)
|
100
|
+
@parser = lambda do |input|
|
101
|
+
args = []
|
102
|
+
remains = parsers.inject(input) do |accumulator, parser|
|
103
|
+
result = parser.parse(accumulator)
|
104
|
+
unless result == []
|
105
|
+
args << result[0][0]
|
106
|
+
result[0][1]
|
107
|
+
else
|
108
|
+
break []
|
109
|
+
end
|
110
|
+
end
|
111
|
+
unless remains == []
|
112
|
+
retval = yield(*args)
|
113
|
+
[[retval, remains]]
|
114
|
+
else
|
115
|
+
[]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end # of initialize
|
119
|
+
end # of SeqParser
|
120
|
+
|
121
|
+
class AltParser
|
122
|
+
include Parsable
|
123
|
+
def initialize(*parsers)
|
124
|
+
@parser = lambda do |input|
|
125
|
+
parsers.inject([]) do |accum, parser|
|
126
|
+
result = parser.parse(input)
|
127
|
+
if result == []
|
128
|
+
result
|
129
|
+
else
|
130
|
+
break [result[0]]
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end # of initialize
|
135
|
+
end
|
136
|
+
|
137
|
+
class CharParser
|
138
|
+
include Parsable
|
139
|
+
def initialize(char)
|
140
|
+
equal_char = lambda {|i| i == char}
|
141
|
+
@parser = lambda do |input|
|
142
|
+
SatisfyParser.new(equal_char).parse(input)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
class StringParser
|
148
|
+
include Parsable
|
149
|
+
def initialize(string)
|
150
|
+
@parser = lambda do |input|
|
151
|
+
result = ItemParser.new.parse(string)
|
152
|
+
if result == []
|
153
|
+
SucceedParser.new(result).parse(input) # FailParser.new.parse(input)
|
154
|
+
else
|
155
|
+
SeqParser.new(
|
156
|
+
CharParser.new(result[0][0]),
|
157
|
+
StringParser.new(result[0][1]),
|
158
|
+
SucceedParser.new(result[0][0] + result[0][1])
|
159
|
+
) do |char_result, string_result, succeed_result|
|
160
|
+
succeed_result
|
161
|
+
end.parse(input)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
class RegexParser
|
168
|
+
include Parsable
|
169
|
+
def initialize(regex)
|
170
|
+
@parser = lambda do |input|
|
171
|
+
if match = Regexp.new(regex).match(input)
|
172
|
+
[[match[0],match.post_match]]
|
173
|
+
else
|
174
|
+
[]
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
class ManyParser
|
181
|
+
include Parsable
|
182
|
+
def initialize(predicate)
|
183
|
+
@parser = lambda do |input|
|
184
|
+
AltParser.new(ManyOneParser.new(predicate), SucceedParser.new([])).parse(input)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
class ManyOneParser
|
190
|
+
include Parsable
|
191
|
+
def initialize(predicate)
|
192
|
+
@parser = lambda do |input|
|
193
|
+
SeqParser.new(
|
194
|
+
SatisfyParser.new(predicate),
|
195
|
+
ManyParser.new(predicate)
|
196
|
+
) do |v, vs|
|
197
|
+
if vs == []
|
198
|
+
v
|
199
|
+
else
|
200
|
+
v + vs.to_s
|
201
|
+
end
|
202
|
+
end.parse(input)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
class ZeroOneParser
|
208
|
+
include Parsable
|
209
|
+
def initialize(parser)
|
210
|
+
@parser = lambda do |input|
|
211
|
+
AltParser.new(parser,
|
212
|
+
SucceedParser.new([])).parse(input)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
class Ident
|
218
|
+
include Parsable
|
219
|
+
def initialize
|
220
|
+
@parser = lambda do |input|
|
221
|
+
SeqParser.new(
|
222
|
+
SatisfyParser.new(IS_LOWER),
|
223
|
+
ManyParser.new(IS_ALPHANUM)
|
224
|
+
) do |v, vs|
|
225
|
+
if vs == []
|
226
|
+
v
|
227
|
+
else
|
228
|
+
v + vs.to_s
|
229
|
+
end
|
230
|
+
end.parse(input)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
class Nat
|
236
|
+
include Parsable
|
237
|
+
def initialize
|
238
|
+
@parser = lambda do |input|
|
239
|
+
SeqParser.new(ManyOneParser.new(IS_DIGIT)) do |vs|
|
240
|
+
if vs == []
|
241
|
+
vs
|
242
|
+
else
|
243
|
+
vs.to_i
|
244
|
+
end
|
245
|
+
end.parse(input)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
class Space
|
251
|
+
include Parsable
|
252
|
+
def initialize
|
253
|
+
@parser = lambda do |input|
|
254
|
+
SeqParser.new(ManyParser.new(IS_SPACE)) do |vs|
|
255
|
+
[]
|
256
|
+
end.parse(input)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
class Token
|
262
|
+
include Parsable
|
263
|
+
def initialize(parser)
|
264
|
+
@parser = lambda do |input|
|
265
|
+
SeqParser.new(Space.new, parser, Space.new) do |_, vs, _|
|
266
|
+
vs
|
267
|
+
end.parse(input)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
class Identifier
|
273
|
+
include Parsable
|
274
|
+
def initialize
|
275
|
+
@parser = lambda do |input|
|
276
|
+
Token.new(Ident.new).parse(input)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
class Natural
|
282
|
+
include Parsable
|
283
|
+
def initialize
|
284
|
+
@parser = lambda do |input|
|
285
|
+
Token.new(Nat.new).parse(input)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
class Symbol
|
291
|
+
include Parsable
|
292
|
+
def initialize(literal)
|
293
|
+
@parser = lambda do |input|
|
294
|
+
Token.new(StringParser.new(literal)).parse(input)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
end
|
data/tests/test_parser.rb
CHANGED
@@ -16,6 +16,11 @@ class YaparcTest < Test::Unit::TestCase
|
|
16
16
|
def test_succeed_parse
|
17
17
|
parser = ::Yaparc::SucceedParser.new(1)
|
18
18
|
assert_equal [[1, "abs"]], parser.parse("abs")
|
19
|
+
assert_equal [[1, "abs"]], parser.tree
|
20
|
+
result = parser.parse("abs") do |result|
|
21
|
+
result[0][0]
|
22
|
+
end
|
23
|
+
assert_equal 1, result
|
19
24
|
end
|
20
25
|
|
21
26
|
def test_fail_parse
|
@@ -116,6 +121,16 @@ class YaparcTest < Test::Unit::TestCase
|
|
116
121
|
assert_equal [], result
|
117
122
|
end
|
118
123
|
|
124
|
+
def test_regex_parse
|
125
|
+
parser = RegexParser.new(/[a-z]/)
|
126
|
+
result = parser.parse("abcdef")
|
127
|
+
assert_equal [["a", "bcdef"]], result
|
128
|
+
|
129
|
+
parser = RegexParser.new(/[0-9]+/)
|
130
|
+
result = parser.parse("1234ab")
|
131
|
+
assert_equal [["1234", "ab"]], result
|
132
|
+
end
|
133
|
+
|
119
134
|
def test_many_parse
|
120
135
|
is_digit = lambda {|i| i > '0' and i < '9'}
|
121
136
|
|
@@ -127,6 +142,15 @@ class YaparcTest < Test::Unit::TestCase
|
|
127
142
|
assert_equal [[[], "abcdef"]], result
|
128
143
|
end
|
129
144
|
|
145
|
+
def test_zero_one_parse
|
146
|
+
parser = ZeroOneParser.new(StringParser.new("abc"))
|
147
|
+
result = parser.parse("abc ")
|
148
|
+
assert_equal [["abc", " "]], result
|
149
|
+
parser = ZeroOneParser.new(StringParser.new("abc"))
|
150
|
+
result = parser.parse("123")
|
151
|
+
assert_equal [[[], "123"]], result
|
152
|
+
end
|
153
|
+
|
130
154
|
def test_ident
|
131
155
|
parser = Ident.new
|
132
156
|
result = parser.parse("abc def")
|
@@ -0,0 +1,38 @@
|
|
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
|
+
|
metadata
CHANGED
@@ -3,8 +3,8 @@ 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.
|
7
|
-
date: 2007-12-
|
6
|
+
version: 0.0.3
|
7
|
+
date: 2007-12-14 00:00:00 +09:00
|
8
8
|
summary: Yet Another Combinator Parser Library
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -12,7 +12,7 @@ email: akimichi_tatsukawa@nifty.com
|
|
12
12
|
homepage: http://rubyforge.org/projects/yaparc/
|
13
13
|
rubyforge_project:
|
14
14
|
description:
|
15
|
-
autorequire:
|
15
|
+
autorequire: yaparc
|
16
16
|
default_executable:
|
17
17
|
bindir: bin
|
18
18
|
has_rdoc: true
|
@@ -29,13 +29,17 @@ post_install_message:
|
|
29
29
|
authors:
|
30
30
|
- Akimichi Tatsukawa
|
31
31
|
files:
|
32
|
-
- tests/
|
32
|
+
- tests/test_parser_cps.rb
|
33
33
|
- tests/test_parser.rb
|
34
|
+
- tests/test_calc.rb
|
35
|
+
- lib/parser_cps.rb
|
36
|
+
- lib/yaparc.rb
|
34
37
|
- lib/parser.rb
|
35
38
|
- README
|
36
39
|
test_files:
|
37
|
-
- tests/
|
40
|
+
- tests/test_parser_cps.rb
|
38
41
|
- tests/test_parser.rb
|
42
|
+
- tests/test_calc.rb
|
39
43
|
rdoc_options: []
|
40
44
|
|
41
45
|
extra_rdoc_files:
|