rparsec-ruby19 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,894 @@
1
+ %w{
2
+ monad misc error context locator token functors parser_monad
3
+ }.each {|lib| require "rparsec/#{lib}"}
4
+ require 'strscan'
5
+
6
+ module RParsec
7
+
8
+ #
9
+ # Represents a parser that parses a certain grammar rule.
10
+ #
11
+ class Parser
12
+ include Functors
13
+ include Monad
14
+ extend Signature
15
+ extend DefHelper
16
+ MyMonad = ParserMonad.new
17
+ attr_accessor :name
18
+
19
+ private
20
+
21
+ def initialize
22
+ initMonad(MyMonad, self)
23
+ end
24
+
25
+ def self.init(*vars)
26
+ parser_checker = {}
27
+ vars.each_with_index do |var, i|
28
+ name = var.to_s
29
+ parser_checker[i] = var if name.include?('parser') && !name.include?('parsers')
30
+ end
31
+ define_method(:initialize) do |*params|
32
+ super()
33
+ vars.each_with_index do |var, i|
34
+ param = params[i]
35
+ if parser_checker.include? i
36
+ TypeChecker.check_arg_type Parser, param, self, i
37
+ end
38
+ instance_variable_set("@"+var.to_s, param)
39
+ end
40
+ end
41
+ end
42
+
43
+ def _display_current_input(input, code, index)
44
+ return 'EOF' if input.nil?
45
+ c = input
46
+ case c when Fixnum then "'"<<c<<"'" when Token then c.text else c.to_s end
47
+ end
48
+
49
+ def _add_encountered_error(msg, encountered)
50
+ result = msg.dup
51
+ result << ', ' unless msg.strip.length == 0 || msg =~ /.*(\.|,)\s*$/
52
+ "#{result}#{encountered}"
53
+ end
54
+
55
+ def _add_location_to_error(locator, ctxt, msg, code)
56
+ line, col = locator.locate(ctxt.error.index)
57
+ msg << " at line #{line}, col #{col}."
58
+ end
59
+
60
+ public
61
+
62
+ #
63
+ # parses a string.
64
+ #
65
+ def parse(src)
66
+ ctxt = ParseContext.new(src)
67
+ return ctxt.result if _parse ctxt
68
+ ctxt.prepare_error
69
+ locator = CodeLocator.new(src)
70
+ raise ParserException.new(ctxt.error.index),
71
+ _add_location_to_error(locator, ctxt,
72
+ _add_encountered_error(ctxt.to_msg,
73
+ _display_current_input(ctxt.error.input, src, ctxt.index)), src)
74
+ end
75
+
76
+ #
77
+ # Set name for the parser.
78
+ # self is returned.
79
+ #
80
+ def setName(nm)
81
+ @name = nm
82
+ self
83
+ end
84
+
85
+ #
86
+ # a.map{|x|x+1} will first execute parser a, when it succeeds,
87
+ # the associated block is executed to transform the result to a new value
88
+ # (increment it in this case).
89
+ #
90
+ def map(&block)
91
+ return self unless block
92
+ MapParser.new(self, block)
93
+ end
94
+
95
+ #
96
+ # _self_ is first executed, the parser result is then passed as parameter to the associated block,
97
+ # which evaluates to another Parser object at runtime. This new Parser object is then executed
98
+ # to get the final parser result.
99
+ #
100
+ # Different from _bind_, parser result of _self_ will be expanded first if it is an array.
101
+ #
102
+ def bindn(&block)
103
+ return self unless block
104
+ BoundnParser.new(self, block)
105
+ end
106
+
107
+ #
108
+ # a.mapn{|x,y|x+y} will first execute parser a, when it succeeds,
109
+ # the array result (if any) is expanded and passed as parameters
110
+ # to the associated block. The result of the block is then used
111
+ # as the parsing result.
112
+ #
113
+ def mapn(&block)
114
+ return self unless block
115
+ MapnParser.new(self, block)
116
+ end
117
+
118
+ #
119
+ # Create a new parser that's atomic.,
120
+ # meaning that when it fails, input consumption is undone.
121
+ #
122
+ def atomize
123
+ AtomParser.new(self).setName(@name)
124
+ end
125
+
126
+ #
127
+ # Create a new parser that looks at inputs whthout consuming them.
128
+ #
129
+ def peek
130
+ PeekParser.new(self).setName(@name)
131
+ end
132
+
133
+ #
134
+ # To create a new parser that succeed only if self fails.
135
+ #
136
+ def not(msg="#{self} unexpected")
137
+ NotParser.new(self, msg)
138
+ end
139
+
140
+ #
141
+ # To create a parser that does "look ahead" for n inputs.
142
+ #
143
+ def lookahead n
144
+ self
145
+ end
146
+
147
+ #
148
+ # To create a parser that fails with a given error message.
149
+ #
150
+ def expect msg
151
+ ExpectParser.new(self, msg)
152
+ end
153
+
154
+ #
155
+ # a.followed b will sequentially run a and b;
156
+ # result of a is preserved as the ultimate return value.
157
+ #
158
+ def followed(other)
159
+ FollowedParser.new(self, other)
160
+ end
161
+ def_sig :followed, Parser
162
+
163
+ #
164
+ # To create a parser that repeats self for a minimum _min_ times,
165
+ # and maximally _max_ times.
166
+ # Only the return value of the last execution is preserved.
167
+ #
168
+ def repeat_(min, max=min)
169
+ return Parsers.failure("min=#{min}, max=#{max}") if min > max
170
+ if(min==max)
171
+ return Parsers.one if max <= 0
172
+ return self if max == 1
173
+ Repeat_Parser.new(self, max)
174
+ else
175
+ Some_Parser.new(self, min, max)
176
+ end
177
+ end
178
+
179
+ #
180
+ # To create a parser that repeats self for a minimum _min_ times,
181
+ # and maximally _max_ times.
182
+ # All return values are collected in an array.
183
+ #
184
+ def repeat(min, max=min)
185
+ return Parsers.failure("min=#{min}, max=#{max}") if min > max
186
+ if(min==max)
187
+ RepeatParser.new(self, max)
188
+ else
189
+ SomeParser.new(self, min, max)
190
+ end
191
+ end
192
+
193
+ #
194
+ # To create a parser that repeats self for at least _least_ times.
195
+ # parser.many_ is equivalent to bnf notation "parser*".
196
+ # Only the return value of the last execution is preserved.
197
+ #
198
+ def many_(least=0)
199
+ Many_Parser.new(self, least)
200
+ end
201
+
202
+ #
203
+ # To create a parser that repeats self for at least _least_ times.
204
+ # All return values are collected in an array.
205
+ #
206
+ def many(least=0)
207
+ ManyParser.new(self, least)
208
+ end
209
+
210
+ #
211
+ # To create a parser that repeats self for at most _max_ times.
212
+ # Only the return value of the last execution is preserved.
213
+ #
214
+ def some_(max)
215
+ repeat_(0, max)
216
+ end
217
+
218
+ #
219
+ # To create a parser that repeats self for at most _max_ times.
220
+ # All return values are collected in an array.
221
+ #
222
+ def some(max)
223
+ repeat(0, max)
224
+ end
225
+
226
+ #
227
+ # To create a parser that repeats self for unlimited times,
228
+ # with the pattern recognized by _delim_ as separator that separates each occurrence.
229
+ # self has to match for at least once.
230
+ # Return values of self are collected in an array.
231
+ #
232
+ def separated1 delim
233
+ rest = delim >> self
234
+ self.bind do |v0|
235
+ result = [v0]
236
+ (rest.map {|v| result << v}).many_ >> value(result)
237
+ end
238
+ end
239
+
240
+ #
241
+ # To create a parser that repeats self for unlimited times,
242
+ # with the pattern recognized by _delim_ as separator that separates each occurrence.
243
+ # Return values of self are collected in an array.
244
+ #
245
+ def separated delim
246
+ separated1(delim).plus value([])
247
+ end
248
+
249
+ #
250
+ # To create a parser that repeats self for unlimited times,
251
+ # with the pattern recognized by _delim_ as separator that separates each occurrence
252
+ # and also possibly ends the pattern.
253
+ # self has to match for at least once.
254
+ # Return values of self are collected in an array.
255
+ #
256
+ def delimited1 delim
257
+ rest = delim >> (self.plus Parsers.throwp(:__end_delimiter__))
258
+ self.bind do |v0|
259
+ result = [v0]
260
+ (rest.map {|v| result << v}).many_.catchp(:__end_delimiter__) >> value(result)
261
+ end
262
+ end
263
+
264
+ #
265
+ # To create a parser that repeats self for unlimited times,
266
+ # with the pattern recognized by _delim_ as separator that separates each occurrence
267
+ # and also possibly ends the pattern.
268
+ # Return values of self are collected in an array.
269
+ #
270
+ def delimited delim
271
+ delimited1(delim).plus value([])
272
+ end
273
+
274
+ #
275
+ # String representation
276
+ #
277
+ def to_s
278
+ return name unless name.nil?
279
+ self.class.to_s
280
+ end
281
+
282
+ #
283
+ # a | b will run b when a fails.
284
+ # b is auto-boxed to Parser when it is not of type Parser.
285
+ #
286
+ def | other
287
+ AltParser.new([self, autobox_parser(other)])
288
+ end
289
+
290
+ #
291
+ # a.optional(default) is equivalent to a.plus(value(default))
292
+ #
293
+ def optional(default=nil)
294
+ self.plus(value(default))
295
+ end
296
+
297
+ #
298
+ # a.catchp(:somesymbol) will catch the :somesymbol thrown by a.
299
+ #
300
+ def catchp(symbol)
301
+ CatchParser.new(symbol, self)
302
+ end
303
+
304
+ #
305
+ # a.fragment will return the string matched by a.
306
+ #
307
+ def fragment
308
+ FragmentParser.new(self)
309
+ end
310
+
311
+ #
312
+ # a.nested b will feed the token array returned by parser a to parser b
313
+ # for a nested parsing.
314
+ #
315
+ def nested(parser)
316
+ NestedParser.new(self, parser)
317
+ end
318
+
319
+ #
320
+ # a.lexeme(delim) will parse _a_ for 0 or more times and ignore all
321
+ # patterns recognized by _delim_.
322
+ # Values returned by _a_ are collected in an array.
323
+ #
324
+ def lexeme(delim = Parsers.whitespaces)
325
+ delim = delim.many_
326
+ delim >> self.delimited(delim)
327
+ end
328
+
329
+ #
330
+ # For prefix unary operator.
331
+ # a.prefix op will run parser _op_ for 0 or more times and eventually run parser _a_
332
+ # for one time.
333
+ # _op_ should return a Proc that accepts one parameter.
334
+ # Proc objects returned by _op_ is then fed with the value returned by _a_
335
+ # from right to left.
336
+ # The final result is returned as return value.
337
+ #
338
+ def prefix(op)
339
+ Parsers.sequence(op.many, self) do |funcs, v|
340
+ funcs.reverse_each {|f|v=f.call(v)}
341
+ v
342
+ end
343
+ end
344
+
345
+ #
346
+ # For postfix unary operator.
347
+ # a.postfix op will run parser _a_ for once and then _op_ for 0 or more times.
348
+ # _op_ should return a Proc that accepts one parameter.
349
+ # Proc objects returned by _op_ is then fed with the value returned by _a_
350
+ # from left to right.
351
+ # The final result is returned as return value.
352
+ #
353
+ def postfix(op)
354
+ Parsers.sequence(self, op.many) do |v, funcs|
355
+ funcs.each{|f|v=f.call(v)}
356
+ v
357
+ end
358
+ end
359
+
360
+ #
361
+ # For non-associative infix binary operator.
362
+ # _op_ has to return a Proc that takes two parameters, who
363
+ # are returned by the _self_ parser as operands.
364
+ #
365
+ def infixn(op)
366
+ bind do |v1|
367
+ bin = Parsers.sequence(op, self) do |f, v2|
368
+ f.call(v1,v2)
369
+ end
370
+ bin | value(v1)
371
+ end
372
+ end
373
+
374
+ #
375
+ # For left-associative infix binary operator.
376
+ # _op_ has to return a Proc that takes two parameters, who
377
+ # are returned by the _self_ parser as operands.
378
+ #
379
+ def infixl(op)
380
+ Parsers.sequence(self, _infix_rest(op, self).many) do |v, rests|
381
+ rests.each do |r|
382
+ f, v1 = *r
383
+ v = f.call(v,v1)
384
+ end
385
+ v
386
+ end
387
+ end
388
+
389
+ #
390
+ # For right-associative infix binary operator.
391
+ # _op_ has to return a Proc that takes two parameters, who
392
+ # are returned by the _self_ parser as operands.
393
+ #
394
+ def infixr(op)
395
+ Parsers.sequence(self, _infix_rest(op, self).many) do |v, rests|
396
+ if rests.empty?
397
+ v
398
+ else
399
+ f, seed = *rests.last
400
+ for i in (0...rests.length-1)
401
+ cur = rests.length-2-i
402
+ f1, v1 = *rests[cur]
403
+ seed = f.call(v1, seed)
404
+ f = f1
405
+ end
406
+ f.call(v, seed)
407
+ end
408
+ end
409
+ end
410
+
411
+ #
412
+ # a.token(:word_token) will return a Token object when _a_ succeeds.
413
+ # The matched string (or the string returned by _a_, if any) is
414
+ # encapsulated in the token, together with the :word_token symbol and
415
+ # the starting index of the match.
416
+ #
417
+ def token(kind)
418
+ TokenParser.new(kind, self)
419
+ end
420
+
421
+ #
422
+ # a.seq b will sequentially run a then b.
423
+ # The result of b is preserved as return value.
424
+ # If a block is associated, values returned by _a_ and _b_
425
+ # are passed into the block and the return value of
426
+ # the block is used as the final result of the parser.
427
+ #
428
+ def seq(other, &block)
429
+ # TypeChecker.check_arg_type Parser, other, :seq
430
+ Parsers.sequence(self, other, &block)
431
+ end
432
+ def_sig :seq, Parser
433
+
434
+ #
435
+ # Similar to _seq_. _other_ is auto-boxed if it is not of type Parser.
436
+ #
437
+ def >> (other)
438
+ seq(autobox_parser(other))
439
+ end
440
+
441
+ private
442
+
443
+ def autobox_parser(val)
444
+ return Parsers.value(val) unless val.kind_of? Parser
445
+ val
446
+ end
447
+
448
+ def _infix_rest(operator, operand)
449
+ Parsers.sequence(operator, operand, &Idn)
450
+ end
451
+
452
+ public
453
+
454
+ alias ~ not
455
+ alias << followed
456
+ alias * repeat_
457
+
458
+ def_sig :plus, Parser
459
+
460
+ private
461
+
462
+ def _parse(ctxt)
463
+ false
464
+ end
465
+ end
466
+ #
467
+ # This module provides all out-of-box parser implementations.
468
+ #
469
+ module Parsers
470
+ extend Signature
471
+
472
+ #
473
+ # A parser that always fails with the given error message.
474
+ #
475
+ def failure msg
476
+ FailureParser.new(msg)
477
+ end
478
+
479
+ #
480
+ # A parser that always succeeds with the given return value.
481
+ #
482
+ def value v
483
+ ValueParser.new(v)
484
+ end
485
+
486
+ #
487
+ # A parser that calls alternative parsers until one succeed,
488
+ # or any failure with input consumption beyond the current look-ahead.
489
+ #
490
+ def sum(*alts)
491
+ # TypeChecker.check_vararg_type Parser, alts, :sum
492
+ PlusParser.new(alts)
493
+ end
494
+ def_sig :sum, [Parser]
495
+
496
+ #
497
+ # A parser that calls alternative parsers until one succeeds.
498
+ #
499
+ def alt(*alts)
500
+ AltParser.new(alts)
501
+ end
502
+ def_sig :alt, [Parser]
503
+
504
+ #
505
+ # A parser that succeeds when the given predicate returns true
506
+ # (with the current input as the parameter).
507
+ # _expected_ is the error message when _pred_ returns false.
508
+ #
509
+ def satisfies(expected, &pred)
510
+ SatisfiesParser.new(pred, expected)
511
+ end
512
+
513
+ #
514
+ # A parser that succeeds when the the current input is equal to the given value.
515
+ # _expected_ is the error message when _pred_ returns false.
516
+ #
517
+ def is(v, expected="#{v} expected")
518
+ satisfies(expected) {|c|c==v}
519
+ end
520
+
521
+ #
522
+ # A parser that succeeds when the the current input is not equal to the given value.
523
+ # _expected_ is the error message when _pred_ returns false.
524
+ #
525
+ def isnt(v, expected="#{v} unexpected")
526
+ satisfies(expected) {|c|c!=v}
527
+ end
528
+
529
+ #
530
+ # A parser that succeeds when the the current input is among the given values.
531
+ #
532
+ def among(*vals)
533
+ expected="one of [#{vals.join(', ')}] expected"
534
+ vals = as_list vals
535
+ satisfies(expected) {|c|vals.include? c}
536
+ end
537
+
538
+ #
539
+ # A parser that succeeds when the the current input is not among the given values.
540
+ #
541
+ def not_among(*vals)
542
+ expected = "one of [#{vals.join(', ')}] unexpected"
543
+ vals = as_list vals
544
+ satisfies(expected) {|c|!vals.include? c}
545
+ end
546
+
547
+ #
548
+ # A parser that succeeds when the the current input is the given character.
549
+ #
550
+ def char(c)
551
+ if c.kind_of? Fixnum
552
+ nm = c.chr
553
+ is(c, "'#{nm}' expected").setName(nm)
554
+ else
555
+ is(c[0], "'#{c}' expected").setName(c)
556
+ end
557
+ end
558
+
559
+ #
560
+ # A parser that succeeds when the the current input is not the given character.
561
+ #
562
+ def not_char(c)
563
+ if c.kind_of? Fixnum
564
+ nm = c.chr
565
+ isnt(c, "'#{nm}' unexpected").setName("~#{nm}")
566
+ else
567
+ isnt(c[0], "'#{c}' unexpected").setName("~#{c}")
568
+ end
569
+ end
570
+
571
+ #
572
+ # A parser that succeeds when there's no input available.
573
+ #
574
+ def eof(expected="EOF expected")
575
+ EofParser.new(expected).setName('EOF')
576
+ end
577
+
578
+ #
579
+ # A parser that tries to match the current inputs one by one
580
+ # with the given values.
581
+ # It succeeds only when all given values are matched, in which case all the
582
+ # matched inputs are consumed.
583
+ #
584
+ def are(vals, expected="#{vals} expected")
585
+ AreParser.new(vals, expected)
586
+ end
587
+
588
+ #
589
+ # A parser that makes sure that the given values don't match
590
+ # the current inputs. One input is consumed if it succeeds.
591
+ #
592
+ def arent(vals, expected="#{vals} unexpected")
593
+ are(vals, '').not(expected) >> any
594
+ end
595
+
596
+ #
597
+ # A parser that matches the given string.
598
+ #
599
+ def string(str, msg = "\"#{str}\" expected")
600
+ are(str, msg).setName(str)
601
+ end
602
+
603
+ #
604
+ # A parser that makes sure that the current input doesn't match a string.
605
+ # One character is consumed if it succeeds.
606
+ #
607
+ def not_string(str, msg="\"#{str}\" unexpected")
608
+ string(str).not(msg) >> any
609
+ end
610
+
611
+ alias str string
612
+
613
+ #
614
+ # A parser that sequentially run the given parsers.
615
+ # The result of the last parser is used as return value.
616
+ # If a block is given, the results of the parsers are passed
617
+ # into the block as parameters, and the block return value
618
+ # is used as result instead.
619
+ #
620
+ def sequence(*parsers, &proc)
621
+ # TypeChecker.check_vararg_type Parser, parsers, :sequence
622
+ SequenceParser.new(parsers, proc)
623
+ end
624
+ def_sig :sequence, [Parser]
625
+
626
+ #
627
+ # A parser that returns the current input index (starting from 0).
628
+ #
629
+ def get_index
630
+ GetIndexParser.new.setName('get_index')
631
+ end
632
+
633
+ #
634
+ # A parser that moves the current input pointer to a certain index.
635
+ #
636
+ def set_index ind
637
+ SetIndexParser.new(ind).setName('set_index')
638
+ end
639
+
640
+ #
641
+ # A parser that tries all given alternative parsers
642
+ # and picks the one with the longest match.
643
+ #
644
+ def longest(*parsers)
645
+ # TypeChecker.check_vararg_type Parser, parsers, :longest
646
+ BestParser.new(parsers, true)
647
+ end
648
+ def_sig :longest, [Parser]
649
+
650
+ #
651
+ # A parser that tries all given alternative parsers
652
+ # and picks the one with the shortest match.
653
+ #
654
+ def shortest(*parsers)
655
+ # TypeChecker.check_vararg_type Parser, parsers, :shortest
656
+ BestParser.new(parsers, false)
657
+ end
658
+ def_sig :shortest, [Parser]
659
+
660
+ alias shorter shortest
661
+ alias longer longest
662
+
663
+ #
664
+ # A parser that consumes one input.
665
+ #
666
+ def any
667
+ AnyParser.new
668
+ end
669
+
670
+ #
671
+ # A parser that always fails.
672
+ #
673
+ def zero
674
+ ZeroParser.new
675
+ end
676
+
677
+ #
678
+ # A parser that always succeeds.
679
+ #
680
+ def one
681
+ OneParser.new
682
+ end
683
+
684
+ #
685
+ # A parser that succeeds if the current input is within a certain range.
686
+ #
687
+ def range(from, to, msg="#{as_char from}..#{as_char to} expected")
688
+ from, to = as_num(from), as_num(to)
689
+ satisfies(msg) {|c| c <= to && c >= from}
690
+ end
691
+
692
+ #
693
+ # A parser that throws a symbol.
694
+ #
695
+ def throwp(symbol)
696
+ ThrowParser.new(symbol)
697
+ end
698
+
699
+ #
700
+ # A parser that succeeds if the current inputs match
701
+ # the given regular expression.
702
+ # The matched string is consumed and returned as result.
703
+ #
704
+ def regexp(ptn, expected="/#{ptn.to_s}/ expected")
705
+ RegexpParser.new(as_regexp(ptn), expected).setName(expected)
706
+ end
707
+
708
+ #
709
+ # A parser that parses a word
710
+ # (starting with alpha or underscore, followed by 0 or more alpha, number or underscore).
711
+ # and return the matched word as string.
712
+ #
713
+ def word(expected='word expected')
714
+ regexp(/[a-zA-Z_]\w*/, expected)
715
+ end
716
+
717
+ #
718
+ # A parser that parses an integer
719
+ # and return the matched integer as string.
720
+ #
721
+ def integer(expected='integer expected')
722
+ regexp(/\d+(?!\w)/, expected)
723
+ end
724
+
725
+ #
726
+ # A parser that parses a number (integer, or decimal number)
727
+ # and return the matched number as string.
728
+ #
729
+ def number(expected='number expected')
730
+ regexp(/\d+(\.\d+)?/, expected)
731
+ end
732
+
733
+ #
734
+ # A parser that matches the given string, case insensitively.
735
+ #
736
+ def string_nocase(str, expected="'#{str}' expected")
737
+ StringCaseInsensitiveParser.new(str, expected).setName(str)
738
+ end
739
+
740
+ #
741
+ # A parser that succeeds when the current input
742
+ # is a token with one of the the given token kinds.
743
+ # If a block is given, the token text is passed to the block
744
+ # as parameter, and the block return value is used as result.
745
+ # Otherwise, the token object is used as result.
746
+ #
747
+ def token(*kinds, &proc)
748
+ expected="#{kinds.join(' or ')} expected"
749
+ recognizer = nil
750
+ if kinds.length==1
751
+ kind = kinds[0]
752
+ recognizer = satisfies(expected) do |tok|
753
+ tok.respond_to? :kind, :text and kind == tok.kind
754
+ end
755
+ else
756
+ recognizer = satisfies(expected) do |tok|
757
+ tok.respond_to? :kind, :text and kinds.include? tok.kind
758
+ end
759
+ end
760
+ recognizer = recognizer.map{|tok|proc.call(tok.text)} if proc
761
+ recognizer
762
+ end
763
+
764
+ #
765
+ # A parser that parses a white space character.
766
+ #
767
+ def whitespace(expected="whitespace expected")
768
+ satisfies(expected) {|c| Whitespaces.include? c}
769
+ end
770
+
771
+ #
772
+ # A parser that parses 1 or more white space characters.
773
+ #
774
+ def whitespaces(expected="whitespace(s) expected")
775
+ whitespace(expected).many_(1)
776
+ end
777
+
778
+ #
779
+ # A parser that parses a line started with _start_.
780
+ # nil is the result.
781
+ #
782
+ def comment_line start
783
+ string(start) >> not_char(?\n).many_ >> char(?\n).optional >> value(nil)
784
+ end
785
+
786
+ #
787
+ # A parser that parses a chunk of text started with _open_
788
+ # and ended by _close_.
789
+ # nil is the result.
790
+ #
791
+ def comment_block open, close
792
+ string(open) >> not_string(close).many_ >> string(close) >> value(nil)
793
+ end
794
+
795
+ #
796
+ # A lazy parser, when executed, calls the given block
797
+ # to get a parser object and delegate the call to this lazily
798
+ # instantiated parser.
799
+ #
800
+ def lazy(&block)
801
+ LazyParser.new(block)
802
+ end
803
+
804
+ #
805
+ # A parser that watches the current parser result without changing it.
806
+ # The following assert will succeed:
807
+ ##
808
+ # char(?a) >> watch{|x|assert_equal(?a, x)}
809
+ ##
810
+ # watch can also be used as a handy tool to print trace information,
811
+ # for example:
812
+ ##
813
+ # some_parser >> watch {puts "some_parser succeeded."}
814
+ #
815
+ def watch(&block)
816
+ return one unless block
817
+ WatchParser.new(block)
818
+ end
819
+
820
+ #
821
+ # A parser that watches the current parser result without changing it.
822
+ # The following assert will succeed:
823
+ ##
824
+ # char(?a).repeat(2) >> watchn{|x,y|assert_equal([?a,?a], [x,y])}
825
+ ##
826
+ # Slightly different from _watch_, _watchn_ expands the current parser result
827
+ # before passing it into the associated block.
828
+ #
829
+ def watchn(&block)
830
+ return one unless block
831
+ WatchnParser.new(block)
832
+ end
833
+
834
+ #
835
+ # A parser that maps current parser result to a new result using
836
+ # the given block.
837
+ ##
838
+ # Different from Parser#map, this method does not need to be combined
839
+ # with any Parser object. It is rather an independent Parser object
840
+ # that maps the _current_ parser result.
841
+ ##
842
+ # parser1.map{|x|...} is equivalent to parser1 >> map{|x|...}
843
+ #
844
+ def map(&block)
845
+ return one unless block
846
+ MapCurrentParser.new(block)
847
+ end
848
+
849
+ #
850
+ # A parser that maps current parser result to a new result using
851
+ # the given block. If the current parser result is an array, the array
852
+ # elements are expanded and then passed as parameters to the block.
853
+ ##
854
+ # Different from Parser#mapn, this method does not need to be combined
855
+ # with any Parser object. It is rather an independent Parser object
856
+ # that maps the _current_ parser result.
857
+ ##
858
+ # parser1.mapn{|x,y|...} is equivalent to parser1 >> mapn{|x,y|...}
859
+ #
860
+ def mapn(&block)
861
+ return one unless block
862
+ MapnCurrentParser.new(block)
863
+ end
864
+
865
+ private
866
+
867
+ #
868
+ # characters considered white space.
869
+ #
870
+ Whitespaces = " \t\r\n"
871
+
872
+ def as_regexp ptn
873
+ case ptn when String then Regexp.new(ptn) else ptn end
874
+ end
875
+
876
+ def as_char c
877
+ case c when String then c else c.chr end
878
+ end
879
+
880
+ def as_num c
881
+ case c when String then c[0] else c end
882
+ end
883
+
884
+ def as_list vals
885
+ return vals unless vals.length==1
886
+ val = vals[0]
887
+ return vals unless val.kind_of? String
888
+ val
889
+ end
890
+
891
+ extend self
892
+ end
893
+
894
+ end # module