yaparc 0.1.6 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +36 -36
- data/lib/yaparc.rb +121 -199
- data/tests/test_abc.rb +40 -41
- data/tests/test_calc.rb +24 -29
- data/tests/test_owl.rb +986 -15
- data/tests/test_parser.rb +94 -45
- data/tests/test_sql.rb +98 -106
- data/tests/test_uri.rb +100 -100
- metadata +2 -2
data/README
CHANGED
@@ -19,39 +19,39 @@ All parsers has 'parse' method, each of which takes input string as its argument
|
|
19
19
|
|
20
20
|
== Primitive Parsers
|
21
21
|
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
25
|
-
*
|
22
|
+
* Succeed
|
23
|
+
* Fail
|
24
|
+
* Item
|
25
|
+
* Satisfy
|
26
26
|
|
27
|
-
===
|
27
|
+
=== Succeed class
|
28
28
|
|
29
|
-
The parser
|
30
|
-
In the following example,
|
29
|
+
The parser Succeed always succeeds with the result value, without consuming any of the input string.
|
30
|
+
In the following example, Succeed#parse takes an input string "blah, blah, blah" and returns the singleton array [[1, "blah, blah, blah"]].
|
31
31
|
|
32
|
-
parser = Yaparc::
|
32
|
+
parser = Yaparc::Succeed.new(1)
|
33
33
|
parser.parse("blah, blah, blah")
|
34
34
|
=> #<Yaparc::Result::OK:0xb7aaaf5c @input="blah, blah, blah", @value=1>
|
35
35
|
|
36
|
-
===
|
36
|
+
=== Fail class
|
37
37
|
|
38
|
-
The parser
|
38
|
+
The parser Fail always fails, regardless of the contents of the input string.
|
39
39
|
|
40
|
-
parser = Yaparc::
|
40
|
+
parser = Yaparc::Fail.new
|
41
41
|
parser.parse("abc")
|
42
42
|
=> #<Yaparc::Result::Fail:0xb7aa56b0 @value=nil>
|
43
43
|
|
44
|
-
===
|
44
|
+
=== Item class
|
45
45
|
|
46
|
-
The parser
|
46
|
+
The parser Item fails if the input string is empty, and succeeds with the first character as the result value otherwise.
|
47
47
|
|
48
|
-
parser = Yaparc::
|
48
|
+
parser = Yaparc::Item.new
|
49
49
|
parser.parse("abc")
|
50
50
|
=> #<Yaparc::Result::OK:0xb7a9fdb4 @input="bc", @value="a">
|
51
51
|
|
52
|
-
===
|
52
|
+
=== Satisfy class
|
53
53
|
|
54
|
-
The parser
|
54
|
+
The parser Satisfy recognizes a single input via predicate which determines if an arbitrary input is suitable for the predicate.
|
55
55
|
|
56
56
|
is_integer = lambda do |i|
|
57
57
|
begin
|
@@ -61,31 +61,31 @@ The parser SatisfyParser recognizes a single input via predicate which determine
|
|
61
61
|
false
|
62
62
|
end
|
63
63
|
end
|
64
|
-
parser = Yaparc::
|
64
|
+
parser = Yaparc::Satisfy.new(is_integer)
|
65
65
|
parser.parse("123")
|
66
66
|
=> #<Yaparc::Result::OK:0xb7a8f284 @input="23", @value="1">
|
67
67
|
|
68
68
|
|
69
69
|
== Combining Parsers
|
70
70
|
|
71
|
-
*
|
72
|
-
*
|
73
|
-
*
|
74
|
-
*
|
71
|
+
* Alt
|
72
|
+
* Seq
|
73
|
+
* Many
|
74
|
+
* ManyOne
|
75
75
|
|
76
76
|
|
77
77
|
|
78
78
|
=== Sequencing parser
|
79
79
|
|
80
|
-
The
|
80
|
+
The Seq corresponds to sequencing in BNF. The following parser recognizes anything that Symbol.new('+') or Natural.new would if placed in succession.
|
81
81
|
|
82
|
-
parser =
|
82
|
+
parser = Seq.new(Symbol.new('+'), Natural.new)
|
83
83
|
parser.parse("+321")
|
84
84
|
=> #<Yaparc::Result::OK:0xb7a81ae4 @input="", @value=321>
|
85
85
|
|
86
|
-
if a block given to
|
86
|
+
if a block given to Seq, it analyses input string to construct its logical structure.
|
87
87
|
|
88
|
-
parser = Yaparc::
|
88
|
+
parser = Yaparc::Seq.new(Yaparc::Symbol.new('+'), Yaparc::Natural.new) do | plus, nat|
|
89
89
|
nat
|
90
90
|
end
|
91
91
|
parser.parse("+1234")
|
@@ -95,11 +95,11 @@ It produces a parse tree which expounds the semantic structure of the program.
|
|
95
95
|
|
96
96
|
=== Alternation parser
|
97
97
|
|
98
|
-
The parser
|
98
|
+
The parser Alt class is an alternation parser, which returns the result of the first parser to succeed, and failure if neither does.
|
99
99
|
|
100
100
|
|
101
|
-
parser = Yaparc::
|
102
|
-
Yaparc::
|
101
|
+
parser = Yaparc::Alt.new(
|
102
|
+
Yaparc::Seq.new(Yaparc::Symbol.new('+'), Yaparc::Natural.new) do | _, nat|
|
103
103
|
nat
|
104
104
|
end,
|
105
105
|
Yaparc::Natural.new
|
@@ -110,17 +110,17 @@ The parser AltParser class is an alternation parser, which returns the result of
|
|
110
110
|
=> #<Yaparc::Result::Fail:0xb7a57ba4 @value=nil>
|
111
111
|
|
112
112
|
|
113
|
-
===
|
113
|
+
=== Many
|
114
114
|
|
115
|
-
In
|
115
|
+
In Many, zero or more applications of parser are admissible.
|
116
116
|
|
117
|
-
parser = Yaparc::
|
117
|
+
parser = Yaparc::Many.new(Yaparc::Satisfy.new(lambda {|i| i > '0' and i < '9'}))
|
118
118
|
parser.parse("123abc")
|
119
119
|
=> #<Yaparc::Result::OK:0xb7a49dc4 @input="abc", @value="123">
|
120
120
|
|
121
|
-
===
|
121
|
+
=== ManyOne
|
122
122
|
|
123
|
-
The
|
123
|
+
The ManyOne requires at least one successfull application of parser.
|
124
124
|
|
125
125
|
|
126
126
|
== Tokenized parser
|
@@ -143,7 +143,7 @@ In order to construct parsers, you make parser class to be inherited from Yaparc
|
|
143
143
|
class Identifier < Yaparc::AbstractParser
|
144
144
|
def initialize
|
145
145
|
@parser = lambda do
|
146
|
-
Yaparc::
|
146
|
+
Yaparc::Tokenize.new(Yaparc::Ident.new)
|
147
147
|
end
|
148
148
|
end
|
149
149
|
end
|
@@ -154,8 +154,8 @@ In the following example, note that Expr class is instantiated inside Expr#initi
|
|
154
154
|
class Expr < Yaparc::AbstractParser
|
155
155
|
def initialize
|
156
156
|
@parser = lambda do
|
157
|
-
Yaparc::
|
158
|
-
Yaparc::
|
157
|
+
Yaparc::Alt.new(
|
158
|
+
Yaparc::Seq.new(Term.new,
|
159
159
|
Yaparc::Symbol.new('+'),
|
160
160
|
Expr.new) do |term, _, expr|
|
161
161
|
['+', term,expr]
|
data/lib/yaparc.rb
CHANGED
@@ -56,18 +56,13 @@ module Yaparc
|
|
56
56
|
module ClassMethods
|
57
57
|
def included(mod)
|
58
58
|
end
|
59
|
-
|
60
|
-
# def define_parser(&block)
|
61
|
-
# @@cparser = lambda do
|
62
|
-
# yield
|
63
|
-
# end
|
64
|
-
# end
|
65
59
|
end
|
66
60
|
end # of Module Parsable
|
67
61
|
|
68
62
|
|
69
63
|
|
70
|
-
class SucceedParser
|
64
|
+
# class SucceedParser
|
65
|
+
class Succeed
|
71
66
|
include Parsable
|
72
67
|
attr_reader :remaining
|
73
68
|
def initialize(value, remaining = nil)
|
@@ -78,7 +73,8 @@ module Yaparc
|
|
78
73
|
end
|
79
74
|
end
|
80
75
|
|
81
|
-
class FailParser
|
76
|
+
# class FailParser
|
77
|
+
class Fail
|
82
78
|
include Parsable
|
83
79
|
def initialize
|
84
80
|
@parser = lambda do |input|
|
@@ -89,7 +85,8 @@ module Yaparc
|
|
89
85
|
|
90
86
|
|
91
87
|
|
92
|
-
class ItemParser
|
88
|
+
# class ItemParser
|
89
|
+
class Item
|
93
90
|
include Parsable
|
94
91
|
def initialize
|
95
92
|
@parser = lambda do |input|
|
@@ -102,13 +99,15 @@ module Yaparc
|
|
102
99
|
end
|
103
100
|
end
|
104
101
|
|
105
|
-
class ZeroOneParser
|
102
|
+
# class ZeroOneParser
|
103
|
+
class ZeroOne
|
106
104
|
include Parsable
|
107
105
|
def initialize(parser, identity = [])
|
108
106
|
@parser = lambda do |input|
|
109
107
|
case result = parser.parse(input)
|
110
108
|
when Result::Fail
|
111
|
-
|
109
|
+
Result::OK.new(:value => identity, :input => input)
|
110
|
+
# Succeed.new(identity)
|
112
111
|
when Result::Error
|
113
112
|
Result::Error.new(:value => result.value, :input => result.input)
|
114
113
|
when Result::OK
|
@@ -117,8 +116,8 @@ module Yaparc
|
|
117
116
|
raise
|
118
117
|
end
|
119
118
|
|
120
|
-
# AltParser.new(parser,
|
121
|
-
# case result = AltParser.new(parser,
|
119
|
+
# AltParser.new(parser, Succeed.new(identity))
|
120
|
+
# case result = AltParser.new(parser, Succeed.new(identity)).parse(input)
|
122
121
|
# if input.nil? or input.empty?
|
123
122
|
# Result::Fail.new(:input => input)
|
124
123
|
# else
|
@@ -129,30 +128,31 @@ module Yaparc
|
|
129
128
|
end
|
130
129
|
end
|
131
130
|
|
132
|
-
class SatisfyParser
|
131
|
+
# class SatisfyParser
|
132
|
+
class Satisfy
|
133
133
|
include Parsable
|
134
134
|
def initialize(predicate)
|
135
135
|
raise unless predicate.instance_of?(Proc)
|
136
136
|
|
137
137
|
@parser = lambda do |input|
|
138
|
-
case result =
|
138
|
+
case result = Item.new.parse(input)
|
139
139
|
when Result::OK
|
140
140
|
parser = if predicate.call(result.value)
|
141
|
-
|
141
|
+
Succeed.new(result.value, result.input)
|
142
142
|
else
|
143
|
-
|
143
|
+
Fail.new
|
144
144
|
end
|
145
145
|
else # Result::Fail or Result::Error
|
146
|
-
|
146
|
+
Fail.new
|
147
147
|
end
|
148
148
|
end
|
149
149
|
end
|
150
150
|
|
151
151
|
def parse(input)
|
152
152
|
case parser = @parser.call(input)
|
153
|
-
when
|
153
|
+
when Succeed
|
154
154
|
parser.parse(parser.remaining)
|
155
|
-
when
|
155
|
+
when Fail
|
156
156
|
parser.parse(input)
|
157
157
|
else
|
158
158
|
raise
|
@@ -171,9 +171,9 @@ module Yaparc
|
|
171
171
|
when Result::Fail
|
172
172
|
Result::Error.new(:value => result.value, :input => result.input)
|
173
173
|
when Result::OK
|
174
|
-
|
174
|
+
Succeed.new(result.value)
|
175
175
|
else
|
176
|
-
|
176
|
+
Succeed.new(result.value)
|
177
177
|
# Result::OK.new(:value => result.value,:input => result.input)
|
178
178
|
end
|
179
179
|
end
|
@@ -181,7 +181,8 @@ module Yaparc
|
|
181
181
|
end # of NoFail
|
182
182
|
|
183
183
|
|
184
|
-
class SeqParser
|
184
|
+
# class SeqParser
|
185
|
+
class Seq
|
185
186
|
include Parsable
|
186
187
|
def initialize(*parsers, &block)
|
187
188
|
@parser = lambda do |input|
|
@@ -191,6 +192,8 @@ module Yaparc
|
|
191
192
|
case result = parser.parse(subsequent.input)
|
192
193
|
when Result::Fail
|
193
194
|
break Result::Fail.new(:input => subsequent.input)
|
195
|
+
# when Result::Error
|
196
|
+
# break Result::Error.new(:input => subsequent.input)
|
194
197
|
else
|
195
198
|
args << result.value
|
196
199
|
result
|
@@ -212,10 +215,11 @@ module Yaparc
|
|
212
215
|
end
|
213
216
|
end
|
214
217
|
end # of initialize
|
215
|
-
end # of
|
218
|
+
end # of Seq
|
216
219
|
|
217
220
|
|
218
|
-
class AltParser
|
221
|
+
# class AltParser
|
222
|
+
class Alt
|
219
223
|
include Parsable
|
220
224
|
def initialize(*parsers)
|
221
225
|
@parser = lambda do |input|
|
@@ -239,48 +243,48 @@ module Yaparc
|
|
239
243
|
end # of initialize
|
240
244
|
end
|
241
245
|
|
242
|
-
|
243
|
-
|
244
|
-
class ApplyParser
|
246
|
+
# class ApplyParser
|
247
|
+
class Apply
|
245
248
|
include Parsable
|
246
249
|
def initialize(parser, &block)
|
247
250
|
@parser = lambda do |input|
|
248
251
|
case result = parser.parse(input)
|
249
252
|
when Result::OK
|
250
|
-
|
253
|
+
Succeed.new(yield(result.value)).parse(result.input)
|
251
254
|
else
|
252
|
-
|
255
|
+
Fail.new.parse(input)
|
253
256
|
end
|
254
257
|
end
|
255
258
|
end # of initialize
|
256
|
-
end # of
|
259
|
+
end # of Apply
|
257
260
|
|
258
261
|
|
259
|
-
class
|
262
|
+
class String
|
260
263
|
include Parsable
|
261
264
|
def initialize(string)
|
262
265
|
@parser = lambda do |input|
|
263
|
-
case result =
|
266
|
+
case result = Item.new.parse(string)
|
264
267
|
when Result::OK
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
268
|
+
Seq.new(
|
269
|
+
Char.new(result.value),
|
270
|
+
Yaparc::String.new(result.input),
|
271
|
+
Succeed.new(result.value + result.input)
|
272
|
+
) do |char_result, string_result, succeed_result|
|
270
273
|
succeed_result
|
271
274
|
end
|
272
275
|
else
|
273
|
-
|
276
|
+
Succeed.new(result) # Is it OK?
|
274
277
|
end
|
275
278
|
end
|
276
279
|
end
|
277
280
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
+
# def parse(input)
|
282
|
+
# @parser.call(input).parse(input)
|
283
|
+
# end
|
281
284
|
end
|
282
285
|
|
283
|
-
class RegexParser
|
286
|
+
# class RegexParser
|
287
|
+
class Regex
|
284
288
|
include Parsable
|
285
289
|
|
286
290
|
def initialize(regex, &block)
|
@@ -288,7 +292,7 @@ module Yaparc
|
|
288
292
|
@parser = lambda do |input|
|
289
293
|
if match = Regexp.new(regex).match(input)
|
290
294
|
if block_given?
|
291
|
-
|
295
|
+
Succeed.new(yield(*match.to_a[1..match.to_a.length])).parse(match.post_match)
|
292
296
|
else
|
293
297
|
Result::OK.new(:value => match[0], :input => match.post_match)
|
294
298
|
end
|
@@ -310,89 +314,93 @@ module Yaparc
|
|
310
314
|
end
|
311
315
|
end
|
312
316
|
end
|
313
|
-
# class RegexParser
|
314
|
-
# include Parsable
|
315
|
-
|
316
|
-
# def initialize(regex)
|
317
|
-
# @parser = lambda do |input|
|
318
|
-
# if match = Regexp.new(regex).match(input)
|
319
|
-
# Result::OK.new(:value => match[0], :input => match.post_match)
|
320
|
-
# else
|
321
|
-
# Result::Fail.new(:input => input)
|
322
|
-
# end
|
323
|
-
# end
|
324
|
-
# end
|
325
|
-
# end
|
326
317
|
|
327
318
|
# permits zero or more applications of parser.
|
328
|
-
class ManyParser
|
319
|
+
# class ManyParser
|
320
|
+
class Many
|
329
321
|
include Parsable
|
330
322
|
def initialize(parser, identity = [])
|
331
323
|
@parser = lambda do |input|
|
332
|
-
|
324
|
+
Alt.new(ManyOne.new(parser, identity), Succeed.new(identity))
|
333
325
|
end
|
334
326
|
end
|
335
|
-
|
336
|
-
# def parse(input)
|
337
|
-
# @parser.call(input).parse(input)
|
338
|
-
# end
|
339
327
|
end
|
340
328
|
|
341
329
|
# requires at least one successfull application of parser.
|
342
|
-
class
|
330
|
+
# class ManyOne
|
331
|
+
class ManyOne
|
343
332
|
include Parsable
|
344
333
|
def initialize(parser, identity = [])
|
345
334
|
@parser = lambda do |input|
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
335
|
+
Seq.new(parser, Many.new(parser, identity)) do |head, tail|
|
336
|
+
case head
|
337
|
+
when ::String
|
338
|
+
if tail.instance_of?(::String)
|
339
|
+
head + tail
|
340
|
+
else
|
341
|
+
raise "Incompatible type: head => #{head}, tail => #{tail}"
|
342
|
+
end
|
343
|
+
when ::Array
|
344
|
+
if tail.instance_of?(Array)
|
345
|
+
head + tail
|
346
|
+
else
|
347
|
+
raise "Incompatible type: head => #{head}, tail => #{tail}"
|
348
|
+
end
|
349
|
+
when ::Hash
|
350
|
+
if tail.instance_of?(Hash)
|
351
|
+
head.merge(tail)
|
352
|
+
else
|
353
|
+
raise "Incompatible type: head => #{head}, tail => #{tail}"
|
354
|
+
end
|
355
|
+
when ::Integer
|
356
|
+
if tail.kind_of?(Integer)
|
357
|
+
head + tail
|
358
|
+
else
|
359
|
+
raise "Incompatible type: head => #{head}, tail => #{tail}"
|
360
|
+
end
|
361
|
+
else
|
362
|
+
raise "Incompatible type: head => #{head}"
|
363
|
+
end
|
364
|
+
#head + tail
|
351
365
|
end
|
352
366
|
end
|
353
367
|
end
|
354
|
-
|
355
|
-
def parse(input)
|
356
|
-
@parser.call(input).parse(input)
|
357
|
-
end
|
358
368
|
end
|
359
369
|
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
class SpaceParser
|
370
|
+
# class SpaceParser
|
371
|
+
class Space
|
364
372
|
include Parsable
|
365
373
|
def initialize
|
366
374
|
@parser = lambda do |input|
|
367
|
-
|
375
|
+
Seq.new(Many.new(Satisfy.new(IS_SPACE),""))
|
368
376
|
end
|
369
377
|
end
|
370
378
|
end
|
371
379
|
|
372
|
-
class
|
380
|
+
class WhiteSpace
|
373
381
|
include Parsable
|
374
382
|
def initialize
|
375
383
|
@parser = lambda do |input|
|
376
|
-
|
384
|
+
Seq.new(Many.new(Satisfy.new(IS_WHITESPACE),''))
|
377
385
|
end
|
378
386
|
end
|
379
387
|
end
|
380
388
|
|
381
|
-
class
|
389
|
+
class Tokenize
|
382
390
|
include Parsable
|
383
391
|
attr_accessor :prefix, :postfix
|
384
392
|
|
385
393
|
def initialize(parser, args = { }, &block)
|
386
394
|
@parser = lambda do |input|
|
387
|
-
@prefix = args[:prefix] ? args[:prefix] :
|
388
|
-
@postfix = args[:postfix] ? args[:postfix] :
|
395
|
+
@prefix = args[:prefix] ? args[:prefix] : WhiteSpace.new
|
396
|
+
@postfix = args[:postfix] ? args[:postfix] : WhiteSpace.new
|
389
397
|
if block_given?
|
390
398
|
yield self
|
391
|
-
|
399
|
+
Seq.new(@prefix, parser, @postfix) do |_, vs, _|
|
392
400
|
vs
|
393
401
|
end
|
394
402
|
else
|
395
|
-
|
403
|
+
Seq.new(@prefix, parser, @postfix) do |_, vs, _|
|
396
404
|
vs
|
397
405
|
end
|
398
406
|
end
|
@@ -400,23 +408,12 @@ module Yaparc
|
|
400
408
|
end
|
401
409
|
end
|
402
410
|
|
403
|
-
#
|
404
|
-
|
405
|
-
|
406
|
-
# def initialize(parser, &block)
|
407
|
-
# @prefix, @postfix = WhiteSpace.new,WhiteSpace.new
|
408
|
-
# yield self
|
409
|
-
# @parser = SeqParser.new(@prefix, parser, @postfix) do |_, vs, _|
|
410
|
-
# vs
|
411
|
-
# end
|
412
|
-
# end
|
413
|
-
# end
|
414
|
-
|
415
|
-
class LiteralParser
|
411
|
+
# class LiteralParser
|
412
|
+
class Literal
|
416
413
|
include Parsable
|
417
414
|
def initialize(literal)
|
418
415
|
@parser = lambda do |input|
|
419
|
-
|
416
|
+
Tokenize.new(Yaparc::String.new(literal))
|
420
417
|
end
|
421
418
|
end
|
422
419
|
end
|
@@ -425,23 +422,21 @@ module Yaparc
|
|
425
422
|
|
426
423
|
class Identifier
|
427
424
|
include Yaparc::Parsable
|
428
|
-
@@identifier_regex = ::Yaparc::
|
425
|
+
@@identifier_regex = ::Yaparc::Regex.new(/\A[a-zA-Z_]+[a-zA-Z0-9_]*/)
|
429
426
|
|
430
427
|
def initialize(*keywords)
|
431
428
|
if keywords == []
|
432
429
|
@parser = lambda do |input|
|
433
|
-
|
434
|
-
# Yaparc::Token.new(@@identifier_regex)
|
430
|
+
Tokenize.new(@@identifier_regex)
|
435
431
|
end
|
436
432
|
else
|
437
433
|
@parser = lambda do |input|
|
438
|
-
keyword_parsers = keywords.map {|keyword| Yaparc::
|
439
|
-
case result = Yaparc::
|
434
|
+
keyword_parsers = keywords.map {|keyword| Yaparc::String.new(keyword)}
|
435
|
+
case result = Yaparc::Alt.new(*keyword_parsers).parse(input)
|
440
436
|
when Yaparc::Result::OK
|
441
|
-
Yaparc::
|
437
|
+
Yaparc::Fail.new
|
442
438
|
else # Result::Fail or Result::Error
|
443
|
-
|
444
|
-
# Yaparc::Token.new(@@identifier_regex)
|
439
|
+
Tokenize.new(@@identifier_regex)
|
445
440
|
end
|
446
441
|
end
|
447
442
|
end
|
@@ -452,69 +447,48 @@ module Yaparc
|
|
452
447
|
end
|
453
448
|
end
|
454
449
|
|
455
|
-
#
|
456
|
-
|
457
|
-
|
458
|
-
# def parse(input)
|
459
|
-
# @parser.parse(input)
|
460
|
-
# end
|
461
|
-
# end
|
462
|
-
|
463
|
-
class CharParser
|
450
|
+
# class Char
|
451
|
+
class Char
|
464
452
|
include Parsable
|
465
453
|
|
466
454
|
def initialize(char)
|
467
455
|
equal_char = lambda {|i| i == char}
|
468
456
|
@parser = lambda do |input|
|
469
|
-
|
457
|
+
Satisfy.new(equal_char)
|
470
458
|
end
|
471
459
|
end
|
472
460
|
end
|
473
|
-
# class CharParser < ParserBase
|
474
|
-
|
475
|
-
# def initialize(char)
|
476
|
-
# equal_char = lambda {|i| i == char}
|
477
|
-
# @parser = SatisfyParser.new(equal_char)
|
478
|
-
# end
|
479
|
-
# end
|
480
|
-
|
481
|
-
# class ZeroOneParser < ParserBase
|
482
|
-
# def initialize(parser, identity = [])
|
483
|
-
# @parser = AltParser.new(parser, SucceedParser.new(identity)) # Is it OK?
|
484
|
-
# end
|
485
|
-
# end
|
486
461
|
|
487
462
|
class Ident
|
488
463
|
include Parsable
|
489
464
|
def initialize
|
490
465
|
@parser = lambda do |input|
|
491
|
-
|
492
|
-
|
493
|
-
|
466
|
+
Seq.new(
|
467
|
+
Satisfy.new(IS_LOWER),
|
468
|
+
Many.new(Satisfy.new(IS_ALPHANUM),"")
|
494
469
|
) do |head, tail|
|
495
470
|
head + tail
|
496
471
|
end
|
497
472
|
end
|
498
473
|
end
|
499
474
|
end
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
# end
|
475
|
+
|
476
|
+
class Digit
|
477
|
+
include Parsable
|
478
|
+
def initialize
|
479
|
+
@parser = lambda do |input|
|
480
|
+
Satisfy.new(IS_DIGIT)
|
481
|
+
end
|
482
|
+
end
|
483
|
+
end
|
510
484
|
|
511
485
|
class Nat
|
512
486
|
include Parsable
|
513
487
|
def initialize
|
514
488
|
@parser = lambda do |input|
|
515
|
-
|
489
|
+
Seq.new(ManyOne.new(Digit.new,'')) do |vs|
|
516
490
|
if vs == ""
|
517
|
-
vs
|
491
|
+
0 # vs
|
518
492
|
else
|
519
493
|
vs.to_i
|
520
494
|
end
|
@@ -523,77 +497,25 @@ module Yaparc
|
|
523
497
|
end
|
524
498
|
end
|
525
499
|
|
526
|
-
# class Nat < ParserBase
|
527
|
-
# def initialize
|
528
|
-
# @parser = SeqParser.new(ManyOneParser.new(SatisfyParser.new(IS_DIGIT),"")) do |vs|
|
529
|
-
# if vs == ""
|
530
|
-
# vs
|
531
|
-
# else
|
532
|
-
# vs.to_i
|
533
|
-
# end
|
534
|
-
# end
|
535
|
-
# end
|
536
|
-
# end
|
537
|
-
|
538
|
-
# class Space < ParserBase
|
539
|
-
# def initialize
|
540
|
-
# @parser = SeqParser.new(ManyParser.new(SatisfyParser.new(IS_SPACE),"")) do |vs|
|
541
|
-
# SucceedParser.new([])
|
542
|
-
# end
|
543
|
-
# end
|
544
|
-
# end
|
545
|
-
|
546
|
-
# class WhiteSpace < ParserBase
|
547
|
-
# def initialize
|
548
|
-
# @parser = SeqParser.new(ManyParser.new(SatisfyParser.new(IS_WHITESPACE),"")) do |vs|
|
549
|
-
# SucceedParser.new([])
|
550
|
-
# end
|
551
|
-
# end
|
552
|
-
# end
|
553
|
-
|
554
|
-
# class Token < ParserBase
|
555
|
-
# attr_accessor :prefix, :postfix
|
556
|
-
|
557
|
-
# def initialize(parser, prefix = WhiteSpace.new, postfix = WhiteSpace.new)
|
558
|
-
# @prefix, @postfix = prefix, postfix
|
559
|
-
# @parser = SeqParser.new(@prefix, parser, @postfix) do |_, vs, _|
|
560
|
-
# vs
|
561
|
-
# end
|
562
|
-
# end
|
563
|
-
# end
|
564
500
|
|
565
501
|
class Natural
|
566
502
|
include Parsable
|
567
503
|
def initialize(args = {})
|
568
504
|
@parser = lambda do |input|
|
569
|
-
|
505
|
+
Tokenize.new(Nat.new, args)
|
570
506
|
end
|
571
507
|
end
|
572
508
|
end
|
573
|
-
# class Natural < ParserBase
|
574
|
-
|
575
|
-
# def initialize
|
576
|
-
# @parser = Token.new(Nat.new)
|
577
|
-
# end
|
578
|
-
# end
|
579
|
-
|
580
509
|
|
581
510
|
class Symbol
|
582
511
|
include Parsable
|
583
512
|
def initialize(literal, args = {})
|
584
513
|
@parser = lambda do |input|
|
585
|
-
|
514
|
+
Literal.new(literal)
|
586
515
|
end
|
587
516
|
end
|
588
517
|
end
|
589
518
|
|
590
|
-
# class Symbol < ParserBase
|
591
|
-
|
592
|
-
# def initialize(literal)
|
593
|
-
# @parser = Token.new(StringParser.new(literal))
|
594
|
-
# end
|
595
|
-
# end
|
596
|
-
|
597
519
|
class AbstractParser
|
598
520
|
include Parsable
|
599
521
|
|