yaparc 0.0.3 → 0.0.4
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 +0 -1
- data/lib/yaparc.rb +40 -18
- data/tests/test_calc.rb +20 -11
- data/tests/test_parser.rb +17 -3
- metadata +2 -3
- data/lib/parser.rb +0 -299
data/README
CHANGED
data/lib/yaparc.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
|
+
def assert_at(file,line, message = "")
|
2
|
+
unless yield
|
3
|
+
raise "Assertion failed !: #{file}, #{line}: #{message}"
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
1
7
|
|
2
8
|
module Yaparc
|
3
9
|
module Parsable
|
4
10
|
include Yaparc
|
5
|
-
|
11
|
+
|
6
12
|
attr_accessor :tree
|
7
|
-
|
13
|
+
|
8
14
|
IS_LOWER = lambda {|c| c >= 'a' and c <= 'z'}
|
9
15
|
IS_ALPHANUM = lambda {|c| (c >= 'a' and c <= 'z') or (c >= '0' and c <= '9')}
|
10
16
|
IS_DIGIT = lambda {|i| i > '0' and i < '9'}
|
@@ -28,24 +34,34 @@ module Yaparc
|
|
28
34
|
tree = parse(input)
|
29
35
|
end
|
30
36
|
|
31
|
-
def define_parser
|
32
|
-
raise
|
33
|
-
end
|
34
37
|
|
35
38
|
module ClassMethods
|
36
39
|
def included(mod)
|
37
40
|
end
|
38
41
|
|
39
|
-
# def self.initialize
|
40
|
-
# @parser = @@parser
|
41
|
-
# end
|
42
|
-
|
43
42
|
def define_parser(&block)
|
44
43
|
@@parser = lambda do |input|
|
45
|
-
parser = yield
|
44
|
+
parser = yield
|
46
45
|
parser.parse(input)
|
47
46
|
end
|
48
47
|
end
|
48
|
+
|
49
|
+
def parser
|
50
|
+
@@parser
|
51
|
+
end
|
52
|
+
|
53
|
+
def parse(input, &block)
|
54
|
+
tree = @@parser.call(input)
|
55
|
+
if block_given?
|
56
|
+
@@tree = yield tree
|
57
|
+
else
|
58
|
+
@@tree = tree
|
59
|
+
end
|
60
|
+
end
|
61
|
+
# def self.initialize
|
62
|
+
# @parser = @@parser
|
63
|
+
# end
|
64
|
+
|
49
65
|
end
|
50
66
|
end # of Parsable
|
51
67
|
|
@@ -79,6 +95,8 @@ module Yaparc
|
|
79
95
|
class SatisfyParser
|
80
96
|
include Parsable
|
81
97
|
def initialize(predicate)
|
98
|
+
assert_at(__FILE__,__LINE__){predicate.instance_of?(Proc)}
|
99
|
+
|
82
100
|
@parser = lambda do |input|
|
83
101
|
item = ItemParser.new.parse(input)
|
84
102
|
if item == []
|
@@ -179,20 +197,21 @@ module Yaparc
|
|
179
197
|
|
180
198
|
class ManyParser
|
181
199
|
include Parsable
|
182
|
-
def initialize(
|
200
|
+
def initialize(parser)
|
183
201
|
@parser = lambda do |input|
|
184
|
-
AltParser.new(ManyOneParser.new(
|
202
|
+
AltParser.new(ManyOneParser.new(parser), SucceedParser.new([])).parse(input)
|
185
203
|
end
|
186
204
|
end
|
187
205
|
end
|
188
206
|
|
189
207
|
class ManyOneParser
|
190
208
|
include Parsable
|
191
|
-
def initialize(
|
209
|
+
def initialize(parser)
|
192
210
|
@parser = lambda do |input|
|
193
211
|
SeqParser.new(
|
194
|
-
SatisfyParser.new(
|
195
|
-
|
212
|
+
# SatisfyParser.new(parser),
|
213
|
+
parser,
|
214
|
+
ManyParser.new(parser)
|
196
215
|
) do |v, vs|
|
197
216
|
if vs == []
|
198
217
|
v
|
@@ -220,7 +239,8 @@ module Yaparc
|
|
220
239
|
@parser = lambda do |input|
|
221
240
|
SeqParser.new(
|
222
241
|
SatisfyParser.new(IS_LOWER),
|
223
|
-
ManyParser.new(IS_ALPHANUM)
|
242
|
+
# ManyParser.new(IS_ALPHANUM)
|
243
|
+
ManyParser.new(SatisfyParser.new(IS_ALPHANUM))
|
224
244
|
) do |v, vs|
|
225
245
|
if vs == []
|
226
246
|
v
|
@@ -236,7 +256,8 @@ module Yaparc
|
|
236
256
|
include Parsable
|
237
257
|
def initialize
|
238
258
|
@parser = lambda do |input|
|
239
|
-
SeqParser.new(ManyOneParser.new(IS_DIGIT)) do |vs|
|
259
|
+
# SeqParser.new(ManyOneParser.new(IS_DIGIT)) do |vs|
|
260
|
+
SeqParser.new(ManyOneParser.new(SatisfyParser.new(IS_DIGIT))) do |vs|
|
240
261
|
if vs == []
|
241
262
|
vs
|
242
263
|
else
|
@@ -251,7 +272,8 @@ module Yaparc
|
|
251
272
|
include Parsable
|
252
273
|
def initialize
|
253
274
|
@parser = lambda do |input|
|
254
|
-
SeqParser.new(ManyParser.new(IS_SPACE)) do |vs|
|
275
|
+
# SeqParser.new(ManyParser.new(IS_SPACE)) do |vs|
|
276
|
+
SeqParser.new(ManyParser.new(SatisfyParser.new(IS_SPACE))) do |vs|
|
255
277
|
[]
|
256
278
|
end.parse(input)
|
257
279
|
end
|
data/tests/test_calc.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'lib/
|
1
|
+
require 'lib/yaparc.rb'
|
2
2
|
require 'test/unit'
|
3
3
|
require 'pp'
|
4
4
|
|
@@ -7,16 +7,16 @@ require 'pp'
|
|
7
7
|
class Expr
|
8
8
|
include Yaparc::Parsable
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
define_parser do
|
11
|
+
AltParser.new(
|
12
|
+
SeqParser.new(Term.new,
|
13
|
+
Symbol.new('+'),
|
14
|
+
Expr.new) do |term, _, expr|
|
15
|
+
['+', term,expr]
|
16
|
+
end,
|
17
|
+
Term.new
|
18
|
+
)
|
19
|
+
end
|
20
20
|
|
21
21
|
def initialize
|
22
22
|
@parser = lambda do |input|
|
@@ -119,6 +119,7 @@ class YaparcCalcTest < Test::Unit::TestCase
|
|
119
119
|
|
120
120
|
def setup
|
121
121
|
end
|
122
|
+
|
122
123
|
def test_expr
|
123
124
|
parser = Expr.new
|
124
125
|
result = parser.parse("1 + 2 ")
|
@@ -126,4 +127,12 @@ class YaparcCalcTest < Test::Unit::TestCase
|
|
126
127
|
assert_equal 3, parser.eval("1 + 2 ")
|
127
128
|
assert_equal 9, parser.eval("(1 + 2) * 3 ")
|
128
129
|
end
|
130
|
+
|
131
|
+
def test_expr_define_parser
|
132
|
+
parser = Expr.new
|
133
|
+
result = Expr.parse("1 + 2 ")
|
134
|
+
assert_equal [[["+", 1, 2], ""]], result
|
135
|
+
assert_equal 3, parser.eval("1 + 2 ")
|
136
|
+
assert_equal 9, parser.eval("(1 + 2) * 3 ")
|
137
|
+
end
|
129
138
|
end
|
data/tests/test_parser.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'lib/
|
1
|
+
require 'lib/yaparc.rb'
|
2
2
|
require 'test/unit'
|
3
3
|
require 'pp'
|
4
4
|
|
@@ -132,8 +132,8 @@ class YaparcTest < Test::Unit::TestCase
|
|
132
132
|
end
|
133
133
|
|
134
134
|
def test_many_parse
|
135
|
-
is_digit = lambda {|i| i > '0' and i < '9'}
|
136
|
-
|
135
|
+
# is_digit = lambda {|i| i > '0' and i < '9'}
|
136
|
+
is_digit = SatisfyParser.new(lambda {|i| i > '0' and i < '9'})
|
137
137
|
parser = ManyParser.new(is_digit)
|
138
138
|
result = parser.parse("123abc")
|
139
139
|
assert_equal [["123", "abc"]], result
|
@@ -163,6 +163,14 @@ class YaparcTest < Test::Unit::TestCase
|
|
163
163
|
assert_equal [[123, " abc"]], result
|
164
164
|
end
|
165
165
|
|
166
|
+
def test_nat_ident
|
167
|
+
parser = SeqParser.new(Nat.new, Ident.new) do |nat, ident|
|
168
|
+
[nat,ident]
|
169
|
+
end
|
170
|
+
result = parser.parse("123abc")
|
171
|
+
assert_equal [[[123, "abc"], ""]], result
|
172
|
+
end
|
173
|
+
|
166
174
|
def test_space
|
167
175
|
parser = Space.new
|
168
176
|
result = parser.parse(" abc")
|
@@ -187,5 +195,11 @@ class YaparcTest < Test::Unit::TestCase
|
|
187
195
|
assert_equal [["%", ""]], result
|
188
196
|
end
|
189
197
|
|
198
|
+
def test_define_parser
|
199
|
+
parser = Symbol.new('%')
|
200
|
+
result = parser.parse(" % ")
|
201
|
+
assert_equal [["%", ""]], result
|
202
|
+
end
|
203
|
+
|
190
204
|
end
|
191
205
|
|
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:
|
6
|
+
version: 0.0.4
|
7
|
+
date: 2008-01-05 00:00:00 +09:00
|
8
8
|
summary: Yet Another Combinator Parser Library
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -34,7 +34,6 @@ files:
|
|
34
34
|
- tests/test_calc.rb
|
35
35
|
- lib/parser_cps.rb
|
36
36
|
- lib/yaparc.rb
|
37
|
-
- lib/parser.rb
|
38
37
|
- README
|
39
38
|
test_files:
|
40
39
|
- tests/test_parser_cps.rb
|
data/lib/parser.rb
DELETED
@@ -1,299 +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
|
-
|
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
|