rparsec-ruby19 1.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.
@@ -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