yaparc 0.0.7 → 0.0.8

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.
Files changed (5) hide show
  1. data/README +172 -8
  2. data/lib/yaparc.rb +402 -69
  3. data/tests/test_calc.rb +42 -105
  4. data/tests/test_parser.rb +304 -67
  5. metadata +2 -2
data/lib/yaparc.rb CHANGED
@@ -22,13 +22,22 @@ module Yaparc
22
22
 
23
23
 
24
24
  def parse(input, &block)
25
- tree = @parser.call(input)
25
+ result = @parser.call(input)
26
26
  if block_given?
27
- @tree = yield tree
27
+ @tree = yield result.value
28
28
  else
29
- @tree = tree
29
+ @tree = result.value
30
30
  end
31
+ result
31
32
  end
33
+ # def parse(input, &block)
34
+ # result = @parser.call(input)
35
+ # if block_given?
36
+ # @tree = yield result
37
+ # else
38
+ # @tree = result
39
+ # end
40
+ # end
32
41
 
33
42
  def eval
34
43
  tree = parse(input)
@@ -52,61 +61,116 @@ module Yaparc
52
61
  # end
53
62
  # end
54
63
 
55
- def cparse(input, &block)
56
- tree = @@cparser.call.parse(input)
57
- if block_given?
58
- yield tree
59
- else
60
- tree
61
- end
62
- end
63
- module_function :cparse
64
+ # def cparse(input, &block)
65
+ # tree = @@cparser.call.parse(input)
66
+ # if block_given?
67
+ # yield tree
68
+ # else
69
+ # tree
70
+ # end
71
+ # end
72
+ # module_function :cparse
64
73
 
65
74
  end
66
75
  end # of Module Parsable
67
76
 
77
+ class Result
78
+ attr_accessor :message, :input, :value
79
+ def initialize(options = {})
80
+ @message = options[:message] if options[:message]
81
+ @input = options[:input] if options[:input]
82
+ @value = options[:value] if options[:value]
83
+ end
84
+ end
85
+
86
+ class OK < Result
87
+ end
88
+
89
+ class Fail < Result
90
+ end
91
+
92
+ class Error < Result
93
+ end
68
94
 
69
95
  class SucceedParser
70
96
  include Parsable
71
97
  attr_reader :remaining
72
98
  def initialize(value, remaining = nil)
73
- @parser = lambda {|input| [[value, input]]}
99
+ @parser = lambda do |input|
100
+ # [[value, input]]
101
+ OK.new(:value => value, :input => input)
102
+ end
74
103
  @remaining = remaining
75
104
  end
76
105
  end
106
+ # class SucceedParser
107
+ # include Parsable
108
+ # attr_reader :remaining
109
+ # def initialize(value, remaining = nil)
110
+ # @parser = lambda do |input|
111
+ # [[value, input]]
112
+ # end
113
+ # @remaining = remaining
114
+ # end
115
+ # end
77
116
 
78
117
  class FailParser
79
118
  include Parsable
80
119
  def initialize
81
- @parser = lambda {|input| []}
120
+ @parser = lambda do |input|
121
+ Fail.new
122
+ end
82
123
  end
83
124
  end
84
125
 
126
+ # class FailParser
127
+ # include Parsable
128
+ # def initialize
129
+ # @parser = lambda do |input|
130
+ # []
131
+ # end
132
+ # end
133
+ # end
134
+
85
135
  class ItemParser
86
136
  include Parsable
87
137
  def initialize
88
138
  @parser = lambda do |input|
89
139
  if input.nil? or input.empty?
90
- []
140
+ Fail.new
91
141
  else
92
- [[input[0..0],input[1..input.length]]]
142
+ # [[input[0..0],input[1..input.length]]]
143
+ OK.new(:value => input[0..0],:input => input[1..input.length])
93
144
  end
94
145
  end
95
146
  end
96
147
  end
97
148
 
149
+ # class ItemParser
150
+ # include Parsable
151
+ # def initialize
152
+ # @parser = lambda do |input|
153
+ # if input.nil? or input.empty?
154
+ # []
155
+ # else
156
+ # [[input[0..0],input[1..input.length]]]
157
+ # end
158
+ # end
159
+ # end
160
+ # end
161
+
98
162
  class SatisfyParser
99
163
  include Parsable
100
164
  def initialize(predicate)
101
165
  assert_at(__FILE__,__LINE__){predicate.instance_of?(Proc)}
102
166
 
103
167
  @parser = lambda do |input|
104
- item = ItemParser.new.parse(input)
105
- if item == []
168
+ case result = ItemParser.new.parse(input)
169
+ when Fail
106
170
  FailParser.new
107
171
  else
108
- parser = if predicate.call(item[0][0])
109
- SucceedParser.new(item[0][0], item[0][1])
172
+ parser = if predicate.call(result.value)
173
+ SucceedParser.new(result.value, result.input)
110
174
  else
111
175
  FailParser.new
112
176
  end
@@ -124,72 +188,173 @@ module Yaparc
124
188
  raise
125
189
  end
126
190
  end
127
-
128
191
  end
129
192
 
193
+ # class SatisfyParser
194
+ # include Parsable
195
+ # def initialize(predicate)
196
+ # assert_at(__FILE__,__LINE__){predicate.instance_of?(Proc)}
197
+
198
+ # @parser = lambda do |input|
199
+ # item = ItemParser.new.parse(input)
200
+ # if item == []
201
+ # FailParser.new
202
+ # else
203
+ # parser = if predicate.call(item[0][0])
204
+ # SucceedParser.new(item[0][0], item[0][1])
205
+ # else
206
+ # FailParser.new
207
+ # end
208
+ # end
209
+ # end
210
+ # end
211
+
212
+ # def parse(input)
213
+ # case parser = @parser.call(input)
214
+ # when SucceedParser
215
+ # parser.parse(parser.remaining)
216
+ # when FailParser
217
+ # parser.parse(input)
218
+ # else
219
+ # raise
220
+ # end
221
+ # end
222
+
223
+ # end
224
+
130
225
 
131
226
  class SeqParser
132
227
  include Parsable
133
228
  def initialize(*parsers, &block)
134
229
  @parser = lambda do |input|
135
230
  args = []
136
- remains = parsers.inject(input) do |accumulator, parser|
137
- result = parser.parse(accumulator)
138
- if result == []
139
- break []
231
+ initial_result = OK.new(:input => input)
232
+ final_result = parsers.inject(initial_result) do |subsequent, parser|
233
+ case result = parser.parse(subsequent.input)
234
+ when Fail
235
+ break Fail.new
140
236
  else
141
- args << result[0][0]
142
- result[0][1]
237
+ args << result.value
238
+ result
143
239
  end
144
240
  end
145
- if remains == []
146
- []
147
- else
148
- retval = if block_given?
241
+
242
+ case final_result
243
+ when Fail
244
+ Fail.new
245
+ when OK
246
+ final_value = if block_given?
149
247
  yield(*args)
150
248
  else
151
249
  args.last
152
250
  end
153
- [[retval, remains]]
251
+ OK.new(:value => final_value, :input => final_result.input)
252
+ else
253
+ raise
154
254
  end
155
255
  end
156
256
  end # of initialize
157
-
158
257
  end # of SeqParser
159
258
 
259
+ # class SeqParser
260
+ # include Parsable
261
+ # def initialize(*parsers, &block)
262
+ # @parser = lambda do |input|
263
+ # args = []
264
+ # remains = parsers.inject(input) do |accumulator, parser|
265
+ # result = parser.parse(accumulator)
266
+ # if result == []
267
+ # break []
268
+ # else
269
+ # args << result[0][0]
270
+ # result[0][1]
271
+ # end
272
+ # end
273
+ # if remains == []
274
+ # []
275
+ # else
276
+ # retval = if block_given?
277
+ # yield(*args)
278
+ # else
279
+ # args.last
280
+ # end
281
+ # [[retval, remains]]
282
+ # end
283
+ # end
284
+ # end # of initialize
285
+
286
+ # end # of SeqParser
287
+
160
288
  class AltParser
161
289
  include Parsable
162
290
  def initialize(*parsers)
163
291
  @parser = lambda do |input|
164
- parsers.inject([]) do |accum, parser|
165
- result = parser.parse(input)
166
- if result == []
167
- result
292
+ initial_result = OK.new(:input => input)
293
+ final_result = Fail.new
294
+ parsers.each do |parser|
295
+ case result = parser.parse(initial_result.input)
296
+ when Fail
297
+ next
298
+ when OK
299
+ break final_result = result
168
300
  else
169
- break [result[0]]
301
+ raise
170
302
  end
171
303
  end
304
+ final_result
172
305
  end
173
306
  end # of initialize
174
307
  end
175
308
 
309
+ # class AltParser
310
+ # include Parsable
311
+ # def initialize(*parsers)
312
+ # @parser = lambda do |input|
313
+ # parsers.inject([]) do |accum, parser|
314
+ # result = parser.parse(input)
315
+ # if result == []
316
+ # result
317
+ # else
318
+ # break [result[0]]
319
+ # end
320
+ # end
321
+ # end
322
+ # end # of initialize
323
+ # end
176
324
 
177
325
 
178
- class StringParser
326
+ class ApplyParser
179
327
  include Parsable
180
- def initialize(string)
328
+ def initialize(parser, &block)
181
329
  @parser = lambda do |input|
182
- result = ItemParser.new.parse(string)
330
+ args = nil
331
+ result = parser.parse(input)
183
332
  if result == []
184
- SucceedParser.new(result)
333
+ FailParser.new.parse(input)
185
334
  else
335
+ SucceedParser.new(yield(result[0][0])).parse(result[0][1])
336
+ end
337
+ end
338
+ end # of initialize
339
+ end # of ApplyParser
340
+
341
+ class StringParser
342
+ include Parsable
343
+ def initialize(string)
344
+ @parser = lambda do |input|
345
+ case result = ItemParser.new.parse(string)
346
+ when Fail
347
+ SucceedParser.new(result) # Is it OK?
348
+ when OK
186
349
  SeqParser.new(
187
- CharParser.new(result[0][0]),
188
- StringParser.new(result[0][1]),
189
- SucceedParser.new(result[0][0] + result[0][1])
350
+ CharParser.new(result.value),
351
+ StringParser.new(result.input),
352
+ SucceedParser.new(result.value + result.input)
190
353
  ) do |char_result, string_result, succeed_result|
191
354
  succeed_result
192
355
  end
356
+ else
357
+ raise
193
358
  end
194
359
  end
195
360
  end
@@ -199,6 +364,30 @@ module Yaparc
199
364
  end
200
365
  end
201
366
 
367
+ # class StringParser
368
+ # include Parsable
369
+ # def initialize(string)
370
+ # @parser = lambda do |input|
371
+ # result = ItemParser.new.parse(string)
372
+ # if result == []
373
+ # SucceedParser.new(result)
374
+ # else
375
+ # SeqParser.new(
376
+ # CharParser.new(result[0][0]),
377
+ # StringParser.new(result[0][1]),
378
+ # SucceedParser.new(result[0][0] + result[0][1])
379
+ # ) do |char_result, string_result, succeed_result|
380
+ # succeed_result
381
+ # end
382
+ # end
383
+ # end
384
+ # end
385
+
386
+ # def parse(input)
387
+ # @parser.call(input).parse(input)
388
+ # end
389
+ # end
390
+
202
391
 
203
392
  class RegexParser
204
393
  include Parsable
@@ -206,20 +395,34 @@ module Yaparc
206
395
  def initialize(regex)
207
396
  @parser = lambda do |input|
208
397
  if match = Regexp.new(regex).match(input)
209
- [[match[0],match.post_match]]
398
+ OK.new(:value => match[0], :input => match.post_match)
210
399
  else
211
- []
400
+ Fail.new
212
401
  end
213
402
  end
214
403
  end
215
404
  end
216
405
 
406
+ # class RegexParser
407
+ # include Parsable
408
+
409
+ # def initialize(regex)
410
+ # @parser = lambda do |input|
411
+ # if match = Regexp.new(regex).match(input)
412
+ # [[match[0],match.post_match]]
413
+ # else
414
+ # []
415
+ # end
416
+ # end
417
+ # end
418
+ # end
419
+
217
420
  # permits zero or more applications of parser.
218
421
  class ManyParser
219
422
  include Parsable
220
423
  def initialize(parser)
221
424
  @parser = lambda do |input|
222
- AltParser.new(ManyOneParser.new(parser), SucceedParser.new([])).parse(input)
425
+ AltParser.new(ManyOneParser.new(parser), SucceedParser.new("")).parse(input)
223
426
  end
224
427
  end
225
428
 
@@ -228,6 +431,19 @@ module Yaparc
228
431
  end
229
432
  end
230
433
 
434
+ # class ManyParser
435
+ # include Parsable
436
+ # def initialize(parser)
437
+ # @parser = lambda do |input|
438
+ # AltParser.new(ManyOneParser.new(parser), SucceedParser.new([])).parse(input)
439
+ # end
440
+ # end
441
+
442
+ # def parse(input)
443
+ # @parser.call(input)
444
+ # end
445
+ # end
446
+
231
447
  # requires at least one successfull application of parser.
232
448
  class ManyOneParser
233
449
  include Parsable
@@ -236,12 +452,8 @@ module Yaparc
236
452
  SeqParser.new(
237
453
  parser,
238
454
  ManyParser.new(parser)
239
- ) do |v, vs|
240
- if vs == []
241
- v
242
- else
243
- v + vs.to_s
244
- end
455
+ ) do |head, tail|
456
+ head + tail
245
457
  end
246
458
  end
247
459
  end
@@ -251,6 +463,28 @@ module Yaparc
251
463
  end
252
464
  end
253
465
 
466
+ # class ManyOneParser
467
+ # include Parsable
468
+ # def initialize(parser)
469
+ # @parser = lambda do |input|
470
+ # SeqParser.new(
471
+ # parser,
472
+ # ManyParser.new(parser)
473
+ # ) do |v, vs|
474
+ # if vs == []
475
+ # v
476
+ # else
477
+ # v + vs.to_s
478
+ # end
479
+ # end
480
+ # end
481
+ # end
482
+
483
+ # def parse(input)
484
+ # @parser.call(input).parse(input)
485
+ # end
486
+ # end
487
+
254
488
 
255
489
  class ParserBase
256
490
  include Parsable
@@ -268,34 +502,58 @@ module Yaparc
268
502
  end
269
503
  end
270
504
 
505
+ # class CharParser < ParserBase
506
+
507
+ # def initialize(char)
508
+ # equal_char = lambda {|i| i == char}
509
+ # @parser = SatisfyParser.new(equal_char)
510
+ # end
511
+ # end
512
+
271
513
 
272
514
  class ZeroOneParser < ParserBase
273
515
  def initialize(parser)
274
- @parser = AltParser.new(parser, SucceedParser.new([]))
516
+ @parser = AltParser.new(parser, SucceedParser.new([])) # Is it OK?
275
517
  end
276
518
  end
277
519
 
520
+ # class ZeroOneParser < ParserBase
521
+ # def initialize(parser)
522
+ # @parser = AltParser.new(parser, SucceedParser.new([]))
523
+ # end
524
+ # end
525
+
278
526
 
279
527
  class Ident < ParserBase
280
528
  def initialize
281
529
  @parser = SeqParser.new(
282
530
  SatisfyParser.new(IS_LOWER),
283
531
  ManyParser.new(SatisfyParser.new(IS_ALPHANUM))
284
- ) do |v, vs|
285
- if vs == []
286
- v
287
- else
288
- v + vs.to_s
289
- end
532
+ ) do |head, tail|
533
+ head + tail
290
534
  end
291
535
  end
292
536
  end
293
537
 
294
- class Nat < ParserBase
538
+ # class Ident < ParserBase
539
+ # def initialize
540
+ # @parser = SeqParser.new(
541
+ # SatisfyParser.new(IS_LOWER),
542
+ # ManyParser.new(SatisfyParser.new(IS_ALPHANUM))
543
+ # ) do |v, vs|
544
+ # if vs == []
545
+ # v
546
+ # else
547
+ # v + vs.to_s
548
+ # end
549
+ # end
550
+ # end
551
+ # end
295
552
 
553
+ class Nat < ParserBase
296
554
  def initialize
297
555
  @parser = SeqParser.new(ManyOneParser.new(SatisfyParser.new(IS_DIGIT))) do |vs|
298
- if vs == []
556
+ if vs == ""
299
557
  vs
300
558
  else
301
559
  vs.to_i
@@ -304,9 +562,21 @@ module Yaparc
304
562
  end
305
563
  end
306
564
 
565
+ # class Nat < ParserBase
566
+
567
+ # def initialize
568
+ # @parser = SeqParser.new(ManyOneParser.new(SatisfyParser.new(IS_DIGIT))) do |vs|
569
+ # if vs == []
570
+ # vs
571
+ # else
572
+ # vs.to_i
573
+ # end
574
+ # end
575
+ # end
576
+ # end
307
577
 
308
- class Space < ParserBase
309
578
 
579
+ class Space < ParserBase
310
580
  def initialize
311
581
  @parser = SeqParser.new(ManyParser.new(SatisfyParser.new(IS_SPACE))) do |vs|
312
582
  []
@@ -314,22 +584,78 @@ module Yaparc
314
584
  end
315
585
  end
316
586
 
587
+ # class Space < ParserBase
588
+
589
+ # def initialize
590
+ # @parser = SeqParser.new(ManyParser.new(SatisfyParser.new(IS_SPACE))) do |vs|
591
+ # []
592
+ # end
593
+ # end
594
+ # end
595
+
317
596
  class Token < ParserBase
318
597
 
319
- def initialize(parser)
320
- @parser = SeqParser.new(Space.new, parser, Space.new) do |_, vs, _|
598
+ def initialize(parser, prefix = Space.new, postfix = Space.new)
599
+ # @parser = SeqParser.new(Space.new, parser, Space.new) do |_, vs, _|
600
+ @parser = SeqParser.new(prefix, parser, postfix) do |_, vs, _|
321
601
  vs
322
602
  end
323
603
  end
324
604
  end
325
605
 
326
- class Identifier < ParserBase
606
+ # Refer to http://www.cs.nott.ac.uk/~gmh/monparsing.pdf, p.23
607
+ class Identifier
608
+ include Parsable
609
+ def initialize(*keywords)
610
+ if keywords == []
611
+ @parser = lambda do |input|
612
+ Token.new(Ident.new)
613
+ end
614
+ else
615
+ @parser = lambda do |input|
616
+ keyword_parsers = keywords.map {|keyword| StringParser.new(keyword)}
617
+ case result = AltParser.new(*keyword_parsers).parse(input)
618
+ when OK
619
+ FailParser.new
620
+ when Fail
621
+ Token.new(Ident.new)
622
+ else
623
+ raise
624
+ end
625
+ end
626
+ end
627
+ end
327
628
 
328
- def initialize
329
- @parser = Token.new(Ident.new)
629
+ def parse(input)
630
+ @parser.call(input).parse(input)
330
631
  end
331
632
  end
332
633
 
634
+ # class Identifier
635
+ # include Parsable
636
+ # def initialize(*keywords)
637
+ # if keywords == []
638
+ # @parser = lambda do |input|
639
+ # Token.new(Ident.new)
640
+ # end
641
+ # else
642
+ # @parser = lambda do |input|
643
+ # keyword_parsers = keywords.map {|keyword| StringParser.new(keyword)}
644
+ # result = AltParser.new(*keyword_parsers).parse(input)
645
+ # unless result == []
646
+ # FailParser.new
647
+ # else
648
+ # Token.new(Ident.new)
649
+ # end
650
+ # end
651
+ # end
652
+ # end
653
+
654
+ # def parse(input)
655
+ # @parser.call(input).parse(input)
656
+ # end
657
+ # end
658
+
333
659
  class Natural < ParserBase
334
660
 
335
661
  def initialize
@@ -337,6 +663,13 @@ module Yaparc
337
663
  end
338
664
  end
339
665
 
666
+ # class Natural < ParserBase
667
+
668
+ # def initialize
669
+ # @parser = Token.new(Nat.new)
670
+ # end
671
+ # end
672
+
340
673
  class Symbol < ParserBase
341
674
 
342
675
  def initialize(literal)