yaparc 0.2.3 → 0.4.0
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 +7 -0
- data/.document +3 -0
- data/.envrc +1 -0
- data/.rdoc_options +1 -0
- data/CHANGELOG.md +19 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README +106 -86
- data/Rakefile +27 -0
- data/TODO +11 -0
- data/lib/yaparc/abstract_parser.rb +16 -0
- data/lib/yaparc/alt.rb +22 -0
- data/lib/yaparc/apply.rb +18 -0
- data/lib/yaparc/char.rb +16 -0
- data/lib/yaparc/cr.rb +11 -0
- data/lib/yaparc/digit.rb +11 -0
- data/lib/yaparc/fail_parser.rb +11 -0
- data/lib/yaparc/ident.rb +18 -0
- data/lib/yaparc/identifier.rb +32 -0
- data/lib/yaparc/item.rb +17 -0
- data/lib/yaparc/literal.rb +13 -0
- data/lib/yaparc/many.rb +14 -0
- data/lib/yaparc/many_one.rb +27 -0
- data/lib/yaparc/nat.rb +11 -0
- data/lib/yaparc/natural.rb +12 -0
- data/lib/yaparc/no_fail.rb +20 -0
- data/lib/yaparc/parsable.rb +20 -0
- data/lib/yaparc/regex.rb +22 -0
- data/lib/yaparc/satisfy.rb +28 -0
- data/lib/yaparc/seq.rb +33 -0
- data/lib/yaparc/space.rb +11 -0
- data/lib/yaparc/string.rb +24 -0
- data/lib/yaparc/succeed.rb +14 -0
- data/lib/yaparc/symbol.rb +11 -0
- data/lib/yaparc/tokenize.rb +18 -0
- data/lib/yaparc/white_space.rb +11 -0
- data/lib/yaparc/zero_one.rb +20 -0
- data/lib/yaparc.rb +40 -605
- data/sig/yaparc.gen.rbs +217 -0
- data/sig/yaparc.rbs +4 -0
- data/yaparc.gemspec +36 -0
- metadata +115 -58
- data/test/n3-report.html +0 -169
- data/test/n3.bnf +0 -129
- data/test/test_abc.rb.bak +0 -112
- data/test/test_calc.rb +0 -112
- data/test/test_lambda.rb +0 -87
- data/test/test_metric.rb +0 -617
- data/test/test_owl.rb +0 -1039
- data/test/test_parser.rb +0 -460
- data/test/test_prolog.rb +0 -287
- data/test/test_sql.rb +0 -317
- data/test/test_uri.rb +0 -752
data/lib/yaparc.rb
CHANGED
|
@@ -1,612 +1,47 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
IS_WHITESPACE = lambda {|i| i == ' ' or i == "\n" or i == "\t"}
|
|
30
|
-
IS_CR = lambda {|i| i == "\n"}
|
|
31
|
-
|
|
32
|
-
def parse(input) #, &block)
|
|
33
|
-
result = @parser.call(input)
|
|
34
|
-
|
|
35
|
-
if result.respond_to?(:parse)
|
|
36
|
-
result.parse(input)
|
|
37
|
-
else
|
|
38
|
-
result
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
end # of Module Parsable
|
|
43
|
-
|
|
44
|
-
class Succeed
|
|
45
|
-
include Parsable
|
|
46
|
-
attr_reader :remaining
|
|
47
|
-
|
|
48
|
-
def initialize(value, remaining = nil)
|
|
49
|
-
@parser = lambda do |input|
|
|
50
|
-
Result::OK.new(:value => value, :input => input)
|
|
51
|
-
end
|
|
52
|
-
@remaining = remaining
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
class Fail
|
|
57
|
-
include Parsable
|
|
58
|
-
def initialize
|
|
59
|
-
@parser = lambda do |input|
|
|
60
|
-
Result::Fail.new(:input => input)
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
class Item
|
|
67
|
-
include Parsable
|
|
68
|
-
|
|
69
|
-
def initialize
|
|
70
|
-
@parser = lambda do |input|
|
|
71
|
-
if input.nil? or input.empty?
|
|
72
|
-
Result::Fail.new(:input => input)
|
|
73
|
-
else
|
|
74
|
-
Result::OK.new(:value => input[0..0],:input => input[1..input.length])
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
class ZeroOne
|
|
81
|
-
include Parsable
|
|
82
|
-
|
|
83
|
-
def initialize(parser, identity = [])
|
|
84
|
-
@parser = lambda do |input|
|
|
85
|
-
case result = parser.parse(input)
|
|
86
|
-
when Result::Fail
|
|
87
|
-
Result::OK.new(:value => identity, :input => input)
|
|
88
|
-
# Succeed.new(identity)
|
|
89
|
-
when Result::Error
|
|
90
|
-
Result::Error.new(:value => result.value, :input => result.input)
|
|
91
|
-
when Result::OK
|
|
92
|
-
result
|
|
93
|
-
else
|
|
94
|
-
raise
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
class Satisfy
|
|
101
|
-
include Parsable
|
|
102
|
-
|
|
103
|
-
def initialize(predicate)
|
|
104
|
-
raise unless predicate.instance_of?(Proc)
|
|
105
|
-
@parser = lambda do |input|
|
|
106
|
-
result = Item.new.parse(input)
|
|
107
|
-
if result.instance_of?(Result::OK) and predicate.call(result.value)
|
|
108
|
-
Succeed.new(result.value, result.input)
|
|
109
|
-
else
|
|
110
|
-
Fail.new
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def parse(input)
|
|
116
|
-
case parser = @parser.call(input)
|
|
117
|
-
when Succeed
|
|
118
|
-
parser.parse(parser.remaining)
|
|
119
|
-
when Fail
|
|
120
|
-
parser.parse(input)
|
|
121
|
-
else
|
|
122
|
-
raise
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
class NoFail
|
|
129
|
-
# hutton92:_higher_order_funct_parsin,p.19
|
|
130
|
-
include Parsable
|
|
131
|
-
|
|
132
|
-
def initialize(parser, &block)
|
|
133
|
-
@parser = lambda do |input|
|
|
134
|
-
result = parser.parse(input)
|
|
135
|
-
if result.instance_of?(Result::Fail)
|
|
136
|
-
Result::Error.new(:value => result.value, :input => result.input)
|
|
137
|
-
else
|
|
138
|
-
Succeed.new(result.value)
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
end # of NoFail
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
class Seq
|
|
146
|
-
include Parsable
|
|
147
|
-
|
|
148
|
-
def initialize(*parsers, &block)
|
|
149
|
-
@parser = lambda do |input|
|
|
150
|
-
args = []
|
|
151
|
-
initial_result = Result::OK.new(:input => input)
|
|
152
|
-
final_result = parsers.inject(initial_result) do |subsequent, parser|
|
|
153
|
-
result = parser.parse(subsequent.input)
|
|
154
|
-
if result.instance_of?(Result::Fail)
|
|
155
|
-
break Result::Fail.new(:input => subsequent.input)
|
|
156
|
-
else
|
|
157
|
-
args << result.value
|
|
158
|
-
result
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
case final_result
|
|
163
|
-
when Result::Fail
|
|
164
|
-
Result::Fail.new(:input => final_result.input)
|
|
165
|
-
when Result::OK
|
|
166
|
-
final_value = if block_given?
|
|
167
|
-
yield(*args)
|
|
168
|
-
else
|
|
169
|
-
args.last
|
|
170
|
-
end
|
|
171
|
-
Result::OK.new(:value => final_value, :input => final_result.input)
|
|
172
|
-
else
|
|
173
|
-
raise
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
end # of initialize
|
|
177
|
-
end # of Seq
|
|
178
|
-
|
|
179
|
-
class Alt
|
|
180
|
-
include Parsable
|
|
181
|
-
def initialize(*parsers)
|
|
182
|
-
@parser = lambda do |input|
|
|
183
|
-
final_result = Result::Fail.new(:input => input)
|
|
184
|
-
parsers.each do |parser|
|
|
185
|
-
case result = parser.parse(input)
|
|
186
|
-
when Result::Fail
|
|
187
|
-
next
|
|
188
|
-
# when Result::Error
|
|
189
|
-
# raise
|
|
190
|
-
# return Result::Error.new(:value => result.value, :input => result.input)
|
|
191
|
-
when Result::OK
|
|
192
|
-
break final_result = result
|
|
193
|
-
else
|
|
194
|
-
raise
|
|
195
|
-
end
|
|
196
|
-
end
|
|
197
|
-
final_result
|
|
198
|
-
end
|
|
199
|
-
end # of initialize
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
# class Alt
|
|
203
|
-
# include Parsable
|
|
204
|
-
# def initialize(*parsers)
|
|
205
|
-
# @parser = lambda do |input|
|
|
206
|
-
# if head = parsers[0]
|
|
207
|
-
# case result = head.parse(input)
|
|
208
|
-
# when Result::Fail
|
|
209
|
-
# if parsers.empty?
|
|
210
|
-
# result
|
|
211
|
-
# else
|
|
212
|
-
# Alt.new(*parsers[1..-1]).parse(input)
|
|
213
|
-
# end
|
|
214
|
-
# when Result::OK
|
|
215
|
-
# result
|
|
216
|
-
# else
|
|
217
|
-
# raise
|
|
218
|
-
# end
|
|
219
|
-
# else
|
|
220
|
-
# Result::Fail.new(:input => input)
|
|
221
|
-
# end
|
|
222
|
-
# end
|
|
223
|
-
# end # of initialize
|
|
224
|
-
# end
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
class Apply
|
|
228
|
-
include Parsable
|
|
229
|
-
|
|
230
|
-
def initialize(parser, &block)
|
|
231
|
-
@parser = lambda do |input|
|
|
232
|
-
result = parser.parse(input)
|
|
233
|
-
if result.instance_of?(Result::OK)
|
|
234
|
-
Succeed.new(yield(result.value)).parse(result.input)
|
|
235
|
-
else
|
|
236
|
-
Fail.new.parse(input)
|
|
237
|
-
end
|
|
238
|
-
end
|
|
239
|
-
end # of initialize
|
|
240
|
-
end # of Apply
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
class String
|
|
244
|
-
include Parsable
|
|
245
|
-
|
|
246
|
-
def initialize(string, case_sensitive = true)
|
|
247
|
-
@parser = lambda do |input|
|
|
248
|
-
result = Item.new.parse(string)
|
|
249
|
-
if result.instance_of?(Result::OK)
|
|
250
|
-
Seq.new(
|
|
251
|
-
Char.new(result.value, case_sensitive),
|
|
252
|
-
Yaparc::String.new(result.input, case_sensitive),
|
|
253
|
-
Succeed.new(result.value + result.input)
|
|
254
|
-
# ) do |char_result, string_result, succeed_result|
|
|
255
|
-
) do |_, _, succeed_result|
|
|
256
|
-
succeed_result
|
|
257
|
-
end
|
|
258
|
-
else
|
|
259
|
-
Succeed.new(result)
|
|
260
|
-
end
|
|
261
|
-
end
|
|
262
|
-
end
|
|
263
|
-
end
|
|
264
|
-
|
|
265
|
-
class Regex
|
|
266
|
-
include Parsable
|
|
267
|
-
|
|
268
|
-
def initialize(regex, &block)
|
|
269
|
-
@regex = regex
|
|
270
|
-
@parser = lambda do |input|
|
|
271
|
-
if match = Regexp.new(regex).match(input)
|
|
272
|
-
if block_given?
|
|
273
|
-
Succeed.new(yield(*match.to_a[1..match.to_a.length])).parse(match.post_match)
|
|
274
|
-
else
|
|
275
|
-
Result::OK.new(:value => match[0], :input => match.post_match)
|
|
276
|
-
end
|
|
277
|
-
else
|
|
278
|
-
Result::Fail.new(:input => input)
|
|
279
|
-
end
|
|
280
|
-
end
|
|
281
|
-
end
|
|
282
|
-
|
|
283
|
-
# def parse_with_parameter(input)
|
|
284
|
-
# raise "Deprecated!! Use Regex with block"
|
|
285
|
-
# if match = Regexp.new(@regex).match(input)
|
|
286
|
-
# if block_given?
|
|
287
|
-
# yield match.to_a[1..match.to_a.length]
|
|
288
|
-
# else
|
|
289
|
-
# Result::OK.new(:value => match, :input => match.post_match)
|
|
290
|
-
# end
|
|
291
|
-
# else
|
|
292
|
-
# Result::Fail.new(:input => input)
|
|
293
|
-
# end
|
|
294
|
-
# end
|
|
295
|
-
end
|
|
296
|
-
|
|
297
|
-
# permits zero or more applications of parser.
|
|
298
|
-
class Many
|
|
299
|
-
include Parsable
|
|
300
|
-
|
|
301
|
-
def initialize(parser, identity = [])
|
|
302
|
-
@parser = lambda do |input|
|
|
303
|
-
Alt.new(ManyOne.new(parser, identity), Succeed.new(identity))
|
|
304
|
-
end
|
|
305
|
-
end
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
# requires at least one successfull application of parser.
|
|
309
|
-
class ManyOne
|
|
310
|
-
include Parsable
|
|
311
|
-
|
|
312
|
-
def initialize(parser, identity = [])
|
|
313
|
-
@parser = lambda do |input|
|
|
314
|
-
Seq.new(parser, Many.new(parser, identity)) do |head, tail|
|
|
315
|
-
case head
|
|
316
|
-
when ::String
|
|
317
|
-
if tail.instance_of?(::String)
|
|
318
|
-
head + tail
|
|
319
|
-
else
|
|
320
|
-
raise "Incompatible type: head => #{head.inspect}, tail => #{tail.inspect}"
|
|
321
|
-
end
|
|
322
|
-
when ::Array
|
|
323
|
-
if tail.instance_of?(Array)
|
|
324
|
-
head + tail
|
|
325
|
-
else
|
|
326
|
-
raise "Incompatible type: head => #{head.inspect}, tail => #{tail.inspect}"
|
|
327
|
-
end
|
|
328
|
-
when ::Hash
|
|
329
|
-
if tail.instance_of?(Hash)
|
|
330
|
-
head.merge(tail)
|
|
331
|
-
else
|
|
332
|
-
raise "Incompatible type: head => #{head.inspect}, tail => #{tail.inspect}"
|
|
333
|
-
end
|
|
334
|
-
when ::Integer
|
|
335
|
-
if tail.kind_of?(Integer)
|
|
336
|
-
head + tail
|
|
337
|
-
else
|
|
338
|
-
raise "Incompatible type: head => #{head.inspect}, tail => #{tail.inspect}"
|
|
339
|
-
end
|
|
340
|
-
else
|
|
341
|
-
if tail.nil?
|
|
342
|
-
head
|
|
343
|
-
else
|
|
344
|
-
[head] + tail
|
|
345
|
-
end
|
|
346
|
-
end
|
|
347
|
-
end
|
|
348
|
-
end
|
|
349
|
-
end
|
|
350
|
-
end
|
|
351
|
-
|
|
352
|
-
class Space
|
|
353
|
-
include Parsable
|
|
354
|
-
def initialize
|
|
355
|
-
@parser = lambda do |input|
|
|
356
|
-
#Many.new(Satisfy.new(IS_SPACE),"")
|
|
357
|
-
Regex.new(/\A[ ]*/)
|
|
358
|
-
end
|
|
359
|
-
end
|
|
360
|
-
end
|
|
361
|
-
|
|
362
|
-
class CR
|
|
363
|
-
include Parsable
|
|
364
|
-
def initialize
|
|
365
|
-
@parser = lambda do |input|
|
|
366
|
-
Regex.new(/\A[ \t]+[\n][ \t\n]+/)
|
|
367
|
-
end
|
|
368
|
-
end
|
|
369
|
-
end
|
|
370
|
-
|
|
371
|
-
class WhiteSpace
|
|
372
|
-
include Parsable
|
|
373
|
-
|
|
374
|
-
def initialize
|
|
375
|
-
@parser = lambda do |input|
|
|
376
|
-
#Many.new(Satisfy.new(IS_WHITESPACE),'')
|
|
377
|
-
Regex.new(/\A[\t\n ]*/)
|
|
378
|
-
end
|
|
379
|
-
end
|
|
380
|
-
end
|
|
381
|
-
|
|
382
|
-
class Tokenize
|
|
383
|
-
include Parsable
|
|
384
|
-
attr_accessor :prefix, :postfix
|
|
385
|
-
|
|
386
|
-
def initialize(parser, args = {}, &block)
|
|
387
|
-
@parser = lambda do |input|
|
|
388
|
-
@prefix = args[:prefix] ? args[:prefix] : WhiteSpace.new
|
|
389
|
-
@postfix = args[:postfix] ? args[:postfix] : WhiteSpace.new
|
|
390
|
-
if block_given?
|
|
391
|
-
yield self
|
|
392
|
-
Seq.new(@prefix, parser, @postfix) do |_, vs, _|
|
|
393
|
-
vs
|
|
394
|
-
end
|
|
395
|
-
else
|
|
396
|
-
Seq.new(@prefix, parser, @postfix) do |_, vs, _|
|
|
397
|
-
vs
|
|
398
|
-
end
|
|
399
|
-
end
|
|
400
|
-
end
|
|
401
|
-
end
|
|
402
|
-
end
|
|
403
|
-
|
|
404
|
-
class Literal
|
|
405
|
-
include Parsable
|
|
406
|
-
|
|
407
|
-
def initialize(literal, case_sensitive = true)
|
|
408
|
-
@parser = lambda do |input|
|
|
409
|
-
Tokenize.new(Yaparc::String.new(literal, case_sensitive))
|
|
410
|
-
end
|
|
411
|
-
end
|
|
412
|
-
end
|
|
413
|
-
|
|
414
|
-
# class Tokenizer
|
|
415
|
-
# include Parsable
|
|
416
|
-
# attr_accessor :prefix, :postfix
|
|
417
|
-
|
|
418
|
-
# def initialize(args = {})
|
|
419
|
-
# @parser = lambda do |input|
|
|
420
|
-
# @prefix = args[:prefix] ? args[:prefix] : WhiteSpace.new
|
|
421
|
-
# @postfix = args[:postfix] ? args[:postfix] : WhiteSpace.new
|
|
422
|
-
# end
|
|
423
|
-
# end
|
|
424
|
-
|
|
425
|
-
# def tokenize(&block)
|
|
426
|
-
# parser = yield
|
|
427
|
-
|
|
428
|
-
# Seq.new(@prefix, parser, @postfix) do |_, vs, _|
|
|
429
|
-
# vs
|
|
430
|
-
# end
|
|
431
|
-
# end
|
|
432
|
-
# end
|
|
433
|
-
|
|
434
|
-
# class Literalizer
|
|
435
|
-
# include Parsable
|
|
436
|
-
|
|
437
|
-
# def initialize(literal, options = {})
|
|
438
|
-
# unless case_sensitive = options[:case_sensitive]
|
|
439
|
-
# true
|
|
440
|
-
# end
|
|
441
|
-
|
|
442
|
-
# unless tokenizer = options[:tokenizer]
|
|
443
|
-
# tokenizer = Tokenizer.new
|
|
444
|
-
# end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'yaparc/alt'
|
|
4
|
+
require_relative 'yaparc/apply'
|
|
5
|
+
require_relative 'yaparc/char'
|
|
6
|
+
require_relative 'yaparc/cr'
|
|
7
|
+
require_relative 'yaparc/digit'
|
|
8
|
+
require_relative 'yaparc/fail_parser'
|
|
9
|
+
require_relative 'yaparc/ident'
|
|
10
|
+
require_relative 'yaparc/identifier'
|
|
11
|
+
require_relative 'yaparc/item'
|
|
12
|
+
require_relative 'yaparc/literal'
|
|
13
|
+
require_relative 'yaparc/many'
|
|
14
|
+
require_relative 'yaparc/many_one'
|
|
15
|
+
require_relative 'yaparc/nat'
|
|
16
|
+
require_relative 'yaparc/natural'
|
|
17
|
+
require_relative 'yaparc/no_fail'
|
|
18
|
+
require_relative 'yaparc/parsable'
|
|
19
|
+
require_relative 'yaparc/regex'
|
|
20
|
+
require_relative 'yaparc/satisfy'
|
|
21
|
+
require_relative 'yaparc/seq'
|
|
22
|
+
require_relative 'yaparc/space'
|
|
23
|
+
require_relative 'yaparc/string'
|
|
24
|
+
require_relative 'yaparc/succeed'
|
|
25
|
+
require_relative 'yaparc/symbol'
|
|
26
|
+
require_relative 'yaparc/tokenize'
|
|
27
|
+
require_relative 'yaparc/white_space'
|
|
28
|
+
require_relative 'yaparc/zero_one'
|
|
445
29
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
# Yaparc::String.new(literal, case_sensitive)
|
|
449
|
-
# end
|
|
450
|
-
# end
|
|
451
|
-
# end
|
|
452
|
-
# end
|
|
453
|
-
|
|
454
|
-
# Refer to http://www.cs.nott.ac.uk/~gmh/monparsing.pdf, p.23
|
|
455
|
-
class Identifier
|
|
456
|
-
include Yaparc::Parsable
|
|
457
|
-
@@identifier_regex = /\A[a-zA-Z_]+[a-zA-Z0-9_]*/
|
|
458
|
-
|
|
459
|
-
def initialize(options = {})
|
|
460
|
-
identifier_regex = if regex = options[:regex]
|
|
461
|
-
::Yaparc::Regex.new(regex)
|
|
462
|
-
else
|
|
463
|
-
::Yaparc::Regex.new(@@identifier_regex)
|
|
464
|
-
end
|
|
465
|
-
|
|
466
|
-
tokenizer = Tokenize.new(identifier_regex)
|
|
467
|
-
|
|
468
|
-
if exclude = options[:exclude]
|
|
469
|
-
@parser = lambda do |input|
|
|
470
|
-
keyword_parsers = exclude.map {|keyword| Yaparc::String.new(keyword)}
|
|
471
|
-
|
|
472
|
-
case result = Yaparc::Alt.new(*keyword_parsers).parse(input)
|
|
473
|
-
when Yaparc::Result::OK
|
|
474
|
-
Yaparc::Fail.new
|
|
475
|
-
else # Result::Fail or Result::Error
|
|
476
|
-
tokenizer
|
|
477
|
-
end
|
|
478
|
-
end
|
|
479
|
-
else
|
|
480
|
-
@parser = lambda do |input|
|
|
481
|
-
tokenizer
|
|
482
|
-
end
|
|
483
|
-
end
|
|
484
|
-
end
|
|
485
|
-
end
|
|
486
|
-
|
|
487
|
-
# class Identifier
|
|
488
|
-
# include Yaparc::Parsable
|
|
489
|
-
# @@identifier_regex = ::Yaparc::Regex.new(/\A[a-zA-Z_]+[a-zA-Z0-9_]*/)
|
|
490
|
-
|
|
491
|
-
# def initialize(*keywords)
|
|
492
|
-
# # def initialize(*keywords, &block)
|
|
493
|
-
# if keywords == []
|
|
494
|
-
# @parser = lambda do |input|
|
|
495
|
-
# Tokenize.new(@@identifier_regex)
|
|
496
|
-
# # if block_given?
|
|
497
|
-
# # tokenize = Tokenize.new(@@identifier_regex)
|
|
498
|
-
# # yield tokenize
|
|
499
|
-
# # tokenize
|
|
500
|
-
# # else
|
|
501
|
-
# # Tokenize.new(@@identifier_regex)
|
|
502
|
-
# # end
|
|
503
|
-
# end
|
|
504
|
-
# else
|
|
505
|
-
# @parser = lambda do |input|
|
|
506
|
-
# keyword_parsers = keywords.map {|keyword| Yaparc::String.new(keyword)}
|
|
507
|
-
|
|
508
|
-
# case result = Yaparc::Alt.new(*keyword_parsers).parse(input)
|
|
509
|
-
# when Yaparc::Result::OK
|
|
510
|
-
# Yaparc::Fail.new
|
|
511
|
-
# else # Result::Fail or Result::Error
|
|
512
|
-
# Tokenize.new(@@identifier_regex)
|
|
513
|
-
# end
|
|
514
|
-
# end
|
|
515
|
-
# end
|
|
516
|
-
# end
|
|
517
|
-
# end
|
|
518
|
-
|
|
519
|
-
class Char
|
|
520
|
-
include Parsable
|
|
521
|
-
|
|
522
|
-
def initialize(char, case_sensitive = true)
|
|
523
|
-
raise unless char.length == 1
|
|
524
|
-
if case_sensitive
|
|
525
|
-
equal_char = lambda {|i| i == char}
|
|
526
|
-
else # in case of case-insentive
|
|
527
|
-
equal_char = lambda {|i| i.casecmp(char) == 0}
|
|
528
|
-
end
|
|
529
|
-
@parser = lambda do |input|
|
|
530
|
-
Satisfy.new(equal_char)
|
|
531
|
-
end
|
|
532
|
-
end
|
|
533
|
-
end
|
|
534
|
-
|
|
535
|
-
class Ident
|
|
536
|
-
include Parsable
|
|
537
|
-
def initialize
|
|
538
|
-
@parser = lambda do |input|
|
|
539
|
-
Seq.new(
|
|
540
|
-
Satisfy.new(IS_LOWER),
|
|
541
|
-
Many.new(Satisfy.new(IS_ALPHANUM),"")
|
|
542
|
-
) do |head, tail|
|
|
543
|
-
head + tail
|
|
544
|
-
end
|
|
545
|
-
end
|
|
546
|
-
end
|
|
547
|
-
end
|
|
548
|
-
|
|
549
|
-
class Digit
|
|
550
|
-
include Parsable
|
|
551
|
-
def initialize
|
|
552
|
-
@parser = lambda do |input|
|
|
553
|
-
Satisfy.new(IS_DIGIT)
|
|
554
|
-
end
|
|
555
|
-
end
|
|
556
|
-
end
|
|
557
|
-
|
|
558
|
-
class Nat
|
|
559
|
-
include Parsable
|
|
560
|
-
def initialize
|
|
561
|
-
@parser = lambda do |input|
|
|
562
|
-
Seq.new(ManyOne.new(Digit.new,'')) do |vs|
|
|
563
|
-
if vs == ""
|
|
564
|
-
0 # vs
|
|
565
|
-
else
|
|
566
|
-
vs.to_i
|
|
567
|
-
end
|
|
568
|
-
end
|
|
569
|
-
end
|
|
570
|
-
end
|
|
571
|
-
end
|
|
30
|
+
module Yaparc
|
|
31
|
+
VERSION = '0.4.0'
|
|
572
32
|
|
|
33
|
+
begin
|
|
34
|
+
base = Class.new do
|
|
35
|
+
attr :input, :value
|
|
573
36
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
@parser = lambda do |input|
|
|
578
|
-
Tokenize.new(Nat.new, args)
|
|
37
|
+
def initialize(input:, value: nil)
|
|
38
|
+
@input = input
|
|
39
|
+
@value = value
|
|
579
40
|
end
|
|
580
41
|
end
|
|
581
|
-
end
|
|
582
42
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
@parser = lambda do |input|
|
|
587
|
-
Literal.new(literal)
|
|
588
|
-
end
|
|
589
|
-
end
|
|
590
|
-
end
|
|
591
|
-
|
|
592
|
-
class AbstractParser
|
|
593
|
-
include Parsable
|
|
594
|
-
|
|
595
|
-
# def parse(input, &block)
|
|
596
|
-
# tree = @parser.call.parse(input)
|
|
597
|
-
# if block_given?
|
|
598
|
-
# yield tree
|
|
599
|
-
# else
|
|
600
|
-
# tree
|
|
601
|
-
# end
|
|
602
|
-
# end
|
|
603
|
-
def parse(input, &block)
|
|
604
|
-
tree = @parser.call.parse(input)
|
|
605
|
-
if block_given?
|
|
606
|
-
@tree = yield tree
|
|
607
|
-
else
|
|
608
|
-
@tree = tree
|
|
609
|
-
end
|
|
610
|
-
end
|
|
43
|
+
OK = Class.new(base)
|
|
44
|
+
Fail = Class.new(base)
|
|
45
|
+
Error = Class.new(base)
|
|
611
46
|
end
|
|
612
|
-
end
|
|
47
|
+
end
|