yaparc 0.1.5 → 0.1.6
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 +1 -11
- data/lib/yaparc.rb +253 -89
- data/tests/abc20bnf.txt +264 -0
- data/tests/test_abc.rb +113 -0
- data/tests/test_calc.rb +10 -5
- data/tests/test_owl.rb +68 -0
- data/tests/test_parser.rb +89 -25
- data/tests/test_sql.rb +10 -10
- data/tests/test_uri.rb +752 -0
- metadata +9 -2
data/README
CHANGED
@@ -138,17 +138,7 @@ The ManyOneParser requires at least one successfull application of parser.
|
|
138
138
|
|
139
139
|
== Define your own parser
|
140
140
|
|
141
|
-
|
142
|
-
There are two ways to construct parser. One is to inherit from Yaparc::ParserBase class.
|
143
|
-
|
144
|
-
class StringMatch < Yaparc::ParserBase
|
145
|
-
|
146
|
-
def initialize(literal)
|
147
|
-
@parser = Yaparc::Token.new(Yaparc::StringParser.new(literal))
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
The other is to inherit from Yaparc::AbstractParser class.
|
141
|
+
In order to construct parsers, you make parser class to be inherited from Yaparc::AbstractParser class.
|
152
142
|
|
153
143
|
class Identifier < Yaparc::AbstractParser
|
154
144
|
def initialize
|
data/lib/yaparc.rb
CHANGED
@@ -39,12 +39,10 @@ module Yaparc
|
|
39
39
|
result = result.parse(input)
|
40
40
|
else
|
41
41
|
if block_given?
|
42
|
-
# @tree = yield result.value
|
43
42
|
result.value = yield result.value
|
44
43
|
@tree = result
|
45
44
|
else
|
46
45
|
@tree = result.value
|
47
|
-
# @tree = result.parse(input)
|
48
46
|
end
|
49
47
|
result
|
50
48
|
end
|
@@ -59,11 +57,11 @@ module Yaparc
|
|
59
57
|
def included(mod)
|
60
58
|
end
|
61
59
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
60
|
+
# def define_parser(&block)
|
61
|
+
# @@cparser = lambda do
|
62
|
+
# yield
|
63
|
+
# end
|
64
|
+
# end
|
67
65
|
end
|
68
66
|
end # of Module Parsable
|
69
67
|
|
@@ -104,6 +102,33 @@ module Yaparc
|
|
104
102
|
end
|
105
103
|
end
|
106
104
|
|
105
|
+
class ZeroOneParser
|
106
|
+
include Parsable
|
107
|
+
def initialize(parser, identity = [])
|
108
|
+
@parser = lambda do |input|
|
109
|
+
case result = parser.parse(input)
|
110
|
+
when Result::Fail
|
111
|
+
SucceedParser.new(identity)
|
112
|
+
when Result::Error
|
113
|
+
Result::Error.new(:value => result.value, :input => result.input)
|
114
|
+
when Result::OK
|
115
|
+
result
|
116
|
+
else
|
117
|
+
raise
|
118
|
+
end
|
119
|
+
|
120
|
+
# AltParser.new(parser, SucceedParser.new(identity))
|
121
|
+
# case result = AltParser.new(parser, SucceedParser.new(identity)).parse(input)
|
122
|
+
# if input.nil? or input.empty?
|
123
|
+
# Result::Fail.new(:input => input)
|
124
|
+
# else
|
125
|
+
# Result::OK.new(:value => input[0..0],:input => input[1..input.length])
|
126
|
+
# end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
107
132
|
class SatisfyParser
|
108
133
|
include Parsable
|
109
134
|
def initialize(predicate)
|
@@ -197,7 +222,8 @@ module Yaparc
|
|
197
222
|
initial_result = Result::OK.new(:input => input)
|
198
223
|
final_result = Result::Fail.new(:input => input)
|
199
224
|
parsers.each do |parser|
|
200
|
-
case result = parser.parse(initial_result.input)
|
225
|
+
# case result = parser.parse(initial_result.input)
|
226
|
+
case result = parser.parse(input)
|
201
227
|
when Result::Fail
|
202
228
|
next
|
203
229
|
when Result::Error
|
@@ -256,32 +282,60 @@ module Yaparc
|
|
256
282
|
|
257
283
|
class RegexParser
|
258
284
|
include Parsable
|
259
|
-
|
260
|
-
def initialize(regex)
|
285
|
+
|
286
|
+
def initialize(regex, &block)
|
287
|
+
@regex = regex
|
261
288
|
@parser = lambda do |input|
|
262
289
|
if match = Regexp.new(regex).match(input)
|
263
|
-
|
290
|
+
if block_given?
|
291
|
+
SucceedParser.new(yield(*match.to_a[1..match.to_a.length])).parse(match.post_match)
|
292
|
+
else
|
293
|
+
Result::OK.new(:value => match[0], :input => match.post_match)
|
294
|
+
end
|
264
295
|
else
|
265
296
|
Result::Fail.new(:input => input)
|
266
297
|
end
|
267
298
|
end
|
268
299
|
end
|
300
|
+
|
301
|
+
def parse_with_parameter(input)
|
302
|
+
if match = Regexp.new(@regex).match(input)
|
303
|
+
if block_given?
|
304
|
+
yield match.to_a[1..match.to_a.length]
|
305
|
+
else
|
306
|
+
Result::OK.new(:value => match, :input => match.post_match)
|
307
|
+
end
|
308
|
+
else
|
309
|
+
Result::Fail.new(:input => input)
|
310
|
+
end
|
311
|
+
end
|
269
312
|
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
|
270
326
|
|
271
327
|
# permits zero or more applications of parser.
|
272
328
|
class ManyParser
|
273
329
|
include Parsable
|
274
|
-
# def initialize(parser, identity = "")
|
275
330
|
def initialize(parser, identity = [])
|
276
331
|
@parser = lambda do |input|
|
277
|
-
# AltParser.new(ManyOneParser.new(parser, identity), SucceedParser.new(identity)).parse(input)
|
278
332
|
AltParser.new(ManyOneParser.new(parser, identity), SucceedParser.new(identity))
|
279
333
|
end
|
280
334
|
end
|
281
335
|
|
282
|
-
|
283
|
-
|
284
|
-
|
336
|
+
# def parse(input)
|
337
|
+
# @parser.call(input).parse(input)
|
338
|
+
# end
|
285
339
|
end
|
286
340
|
|
287
341
|
# requires at least one successfull application of parser.
|
@@ -303,107 +357,91 @@ module Yaparc
|
|
303
357
|
end
|
304
358
|
end
|
305
359
|
|
306
|
-
class ParserBase
|
307
|
-
include Parsable
|
308
|
-
|
309
|
-
def parse(input)
|
310
|
-
@parser.parse(input)
|
311
|
-
end
|
312
|
-
end
|
313
360
|
|
314
|
-
class CharParser < ParserBase
|
315
361
|
|
316
|
-
def initialize(char)
|
317
|
-
equal_char = lambda {|i| i == char}
|
318
|
-
@parser = SatisfyParser.new(equal_char)
|
319
|
-
end
|
320
|
-
end
|
321
|
-
|
322
|
-
class ZeroOneParser < ParserBase
|
323
|
-
def initialize(parser)
|
324
|
-
@parser = AltParser.new(parser, SucceedParser.new([])) # Is it OK?
|
325
|
-
end
|
326
|
-
end
|
327
362
|
|
328
|
-
class
|
329
|
-
|
330
|
-
@parser = SeqParser.new(
|
331
|
-
SatisfyParser.new(IS_LOWER),
|
332
|
-
ManyParser.new(SatisfyParser.new(IS_ALPHANUM),"")
|
333
|
-
) do |head, tail|
|
334
|
-
head + tail
|
335
|
-
end
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
class Nat < ParserBase
|
340
|
-
def initialize
|
341
|
-
@parser = SeqParser.new(ManyOneParser.new(SatisfyParser.new(IS_DIGIT),"")) do |vs|
|
342
|
-
if vs == ""
|
343
|
-
vs
|
344
|
-
else
|
345
|
-
vs.to_i
|
346
|
-
end
|
347
|
-
end
|
348
|
-
end
|
349
|
-
end
|
350
|
-
|
351
|
-
|
352
|
-
class Space < ParserBase
|
363
|
+
class SpaceParser
|
364
|
+
include Parsable
|
353
365
|
def initialize
|
354
|
-
@parser =
|
355
|
-
|
366
|
+
@parser = lambda do |input|
|
367
|
+
SeqParser.new(ManyParser.new(SatisfyParser.new(IS_SPACE),""))
|
356
368
|
end
|
357
369
|
end
|
358
370
|
end
|
359
371
|
|
360
|
-
class
|
372
|
+
class WhiteSpaceParser
|
373
|
+
include Parsable
|
361
374
|
def initialize
|
362
|
-
@parser =
|
363
|
-
|
375
|
+
@parser = lambda do |input|
|
376
|
+
SeqParser.new(ManyParser.new(SatisfyParser.new(IS_WHITESPACE),''))
|
364
377
|
end
|
365
378
|
end
|
366
379
|
end
|
367
380
|
|
368
|
-
class
|
381
|
+
class TokenizeParser
|
382
|
+
include Parsable
|
369
383
|
attr_accessor :prefix, :postfix
|
370
384
|
|
371
|
-
def initialize(parser,
|
372
|
-
@
|
373
|
-
|
374
|
-
|
385
|
+
def initialize(parser, args = { }, &block)
|
386
|
+
@parser = lambda do |input|
|
387
|
+
@prefix = args[:prefix] ? args[:prefix] : WhiteSpaceParser.new
|
388
|
+
@postfix = args[:postfix] ? args[:postfix] : WhiteSpaceParser.new
|
389
|
+
if block_given?
|
390
|
+
yield self
|
391
|
+
SeqParser.new(@prefix, parser, @postfix) do |_, vs, _|
|
392
|
+
vs
|
393
|
+
end
|
394
|
+
else
|
395
|
+
SeqParser.new(@prefix, parser, @postfix) do |_, vs, _|
|
396
|
+
vs
|
397
|
+
end
|
398
|
+
end
|
375
399
|
end
|
376
400
|
end
|
377
401
|
end
|
378
402
|
|
379
|
-
|
380
|
-
|
403
|
+
# class Tokenize < ParserBase
|
404
|
+
# attr_accessor :prefix, :postfix
|
381
405
|
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
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
|
416
|
+
include Parsable
|
417
|
+
def initialize(literal)
|
418
|
+
@parser = lambda do |input|
|
419
|
+
TokenizeParser.new(StringParser.new(literal))
|
387
420
|
end
|
388
421
|
end
|
389
422
|
end
|
390
423
|
|
391
424
|
# Refer to http://www.cs.nott.ac.uk/~gmh/monparsing.pdf, p.23
|
425
|
+
|
392
426
|
class Identifier
|
393
|
-
include Parsable
|
427
|
+
include Yaparc::Parsable
|
428
|
+
@@identifier_regex = ::Yaparc::RegexParser.new(/\A[a-zA-Z_]+[a-zA-Z0-9_]*/)
|
429
|
+
|
394
430
|
def initialize(*keywords)
|
395
431
|
if keywords == []
|
396
432
|
@parser = lambda do |input|
|
397
|
-
|
433
|
+
TokenizeParser.new(@@identifier_regex)
|
434
|
+
# Yaparc::Token.new(@@identifier_regex)
|
398
435
|
end
|
399
436
|
else
|
400
437
|
@parser = lambda do |input|
|
401
|
-
keyword_parsers = keywords.map {|keyword| StringParser.new(keyword)}
|
402
|
-
case result = AltParser.new(*keyword_parsers).parse(input)
|
403
|
-
when Result::OK
|
404
|
-
FailParser.new
|
438
|
+
keyword_parsers = keywords.map {|keyword| Yaparc::StringParser.new(keyword)}
|
439
|
+
case result = Yaparc::AltParser.new(*keyword_parsers).parse(input)
|
440
|
+
when Yaparc::Result::OK
|
441
|
+
Yaparc::FailParser.new
|
405
442
|
else # Result::Fail or Result::Error
|
406
|
-
|
443
|
+
TokenizeParser.new(@@identifier_regex)
|
444
|
+
# Yaparc::Token.new(@@identifier_regex)
|
407
445
|
end
|
408
446
|
end
|
409
447
|
end
|
@@ -414,22 +452,148 @@ module Yaparc
|
|
414
452
|
end
|
415
453
|
end
|
416
454
|
|
455
|
+
# class ParserBase
|
456
|
+
# include Parsable
|
457
|
+
|
458
|
+
# def parse(input)
|
459
|
+
# @parser.parse(input)
|
460
|
+
# end
|
461
|
+
# end
|
462
|
+
|
463
|
+
class CharParser
|
464
|
+
include Parsable
|
465
|
+
|
466
|
+
def initialize(char)
|
467
|
+
equal_char = lambda {|i| i == char}
|
468
|
+
@parser = lambda do |input|
|
469
|
+
SatisfyParser.new(equal_char)
|
470
|
+
end
|
471
|
+
end
|
472
|
+
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
|
417
480
|
|
418
|
-
|
481
|
+
# class ZeroOneParser < ParserBase
|
482
|
+
# def initialize(parser, identity = [])
|
483
|
+
# @parser = AltParser.new(parser, SucceedParser.new(identity)) # Is it OK?
|
484
|
+
# end
|
485
|
+
# end
|
419
486
|
|
487
|
+
class Ident
|
488
|
+
include Parsable
|
489
|
+
def initialize
|
490
|
+
@parser = lambda do |input|
|
491
|
+
SeqParser.new(
|
492
|
+
SatisfyParser.new(IS_LOWER),
|
493
|
+
ManyParser.new(SatisfyParser.new(IS_ALPHANUM),"")
|
494
|
+
) do |head, tail|
|
495
|
+
head + tail
|
496
|
+
end
|
497
|
+
end
|
498
|
+
end
|
499
|
+
end
|
500
|
+
# class Ident < ParserBase
|
501
|
+
# def initialize
|
502
|
+
# @parser = SeqParser.new(
|
503
|
+
# SatisfyParser.new(IS_LOWER),
|
504
|
+
# ManyParser.new(SatisfyParser.new(IS_ALPHANUM),"")
|
505
|
+
# ) do |head, tail|
|
506
|
+
# head + tail
|
507
|
+
# end
|
508
|
+
# end
|
509
|
+
# end
|
510
|
+
|
511
|
+
class Nat
|
512
|
+
include Parsable
|
420
513
|
def initialize
|
421
|
-
@parser =
|
514
|
+
@parser = lambda do |input|
|
515
|
+
SeqParser.new(ManyOneParser.new(SatisfyParser.new(IS_DIGIT),"")) do |vs|
|
516
|
+
if vs == ""
|
517
|
+
vs
|
518
|
+
else
|
519
|
+
vs.to_i
|
520
|
+
end
|
521
|
+
end
|
522
|
+
end
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
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
|
+
|
565
|
+
class Natural
|
566
|
+
include Parsable
|
567
|
+
def initialize(args = {})
|
568
|
+
@parser = lambda do |input|
|
569
|
+
TokenizeParser.new(Nat.new, args)
|
570
|
+
end
|
422
571
|
end
|
423
572
|
end
|
573
|
+
# class Natural < ParserBase
|
424
574
|
|
575
|
+
# def initialize
|
576
|
+
# @parser = Token.new(Nat.new)
|
577
|
+
# end
|
578
|
+
# end
|
425
579
|
|
426
|
-
class Symbol < ParserBase
|
427
580
|
|
428
|
-
|
429
|
-
|
581
|
+
class Symbol
|
582
|
+
include Parsable
|
583
|
+
def initialize(literal, args = {})
|
584
|
+
@parser = lambda do |input|
|
585
|
+
LiteralParser.new(literal)
|
586
|
+
end
|
430
587
|
end
|
431
588
|
end
|
432
589
|
|
590
|
+
# class Symbol < ParserBase
|
591
|
+
|
592
|
+
# def initialize(literal)
|
593
|
+
# @parser = Token.new(StringParser.new(literal))
|
594
|
+
# end
|
595
|
+
# end
|
596
|
+
|
433
597
|
class AbstractParser
|
434
598
|
include Parsable
|
435
599
|
|