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