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,23 @@
1
+ module RParsec
2
+
3
+ class ParserMonad
4
+ def fail msg
5
+ FailureParser.new(msg)
6
+ end
7
+
8
+ def value v
9
+ return Nil if v.nil?
10
+ ValueParser.new(v);
11
+ end
12
+
13
+ def bind(v, &proc)
14
+ return v unless proc
15
+ BoundParser.new(v, proc);
16
+ end
17
+
18
+ def mplus(p1, p2)
19
+ PlusParser.new([p1,p2]);
20
+ end
21
+ end
22
+
23
+ end # module
@@ -0,0 +1,623 @@
1
+ require 'rparsec/parser'
2
+
3
+ module RParsec
4
+
5
+ class FailureParser < Parser
6
+ init :msg
7
+ def _parse ctxt
8
+ return ctxt.failure(@msg)
9
+ end
10
+ end
11
+
12
+ class ValueParser < Parser
13
+ init :value
14
+ def _parse ctxt
15
+ ctxt.retn @value
16
+ end
17
+ end
18
+
19
+ class LazyParser < Parser
20
+ init :block
21
+ def _parse ctxt
22
+ @block.call._parse ctxt
23
+ end
24
+ end
25
+
26
+ class Failures
27
+ def self.add_error(err, e)
28
+ return e if err.nil?
29
+ return err if e.nil?
30
+ cmp = compare_error(err, e)
31
+ return err if cmp > 0
32
+ return e if cmp < 0
33
+ err
34
+ # merge_error(err, e)
35
+ end
36
+
37
+ private
38
+
39
+ def self.get_first_element(err)
40
+ while err.kind_of?(Array)
41
+ err = err[0]
42
+ end
43
+ err
44
+ end
45
+
46
+ def self.compare_error(e1, e2)
47
+ e1, e2 = get_first_element(e1), get_first_element(e2)
48
+ return -1 if e1.index < e2.index
49
+ return 1 if e1.index > e2.index
50
+ 0
51
+ end
52
+ end
53
+
54
+ ###############################################
55
+ #def merge_error(e1, e2)
56
+ # return e1 << e2 if e1.kind_of?(Array)
57
+ # [e1,e2]
58
+ #end
59
+ ###############################################
60
+ class ThrowParser < Parser
61
+ init :symbol
62
+ def _parse ctxt
63
+ throw @symbol
64
+ end
65
+ end
66
+
67
+ class CatchParser < Parser
68
+ init :symbol, :parser
69
+ def _parse ctxt
70
+ interrupted = true
71
+ ok = false
72
+ catch @symbol do
73
+ ok = @parser._parse(ctxt)
74
+ interrupted = false
75
+ end
76
+ return ctxt.retn(@symbol) if interrupted
77
+ ok
78
+ end
79
+ end
80
+
81
+ class PeekParser < Parser
82
+ init :parser
83
+ def _parse ctxt
84
+ ind = ctxt.index
85
+ return false unless @parser._parse ctxt
86
+ ctxt.index = ind
87
+ return true
88
+ end
89
+ def peek
90
+ self
91
+ end
92
+ end
93
+
94
+ class AtomParser < Parser
95
+ init :parser
96
+ def _parse ctxt
97
+ ind = ctxt.index
98
+ return true if @parser._parse ctxt
99
+ ctxt.index = ind
100
+ return false
101
+ end
102
+ def atomize
103
+ self
104
+ end
105
+ end
106
+
107
+ class LookAheadSensitiveParser < Parser
108
+ def initialize(la=1)
109
+ super()
110
+ @lookahead = la
111
+ end
112
+ def visible(ctxt, n)
113
+ ctxt.index - n < @lookahead
114
+ end
115
+ def lookahead(n)
116
+ raise ArgumentError, "lookahead number #{n} should be positive" unless n>0
117
+ return self if n == @lookahead
118
+ withLookahead(n)
119
+ end
120
+ def not(msg="#{self} unexpected")
121
+ NotParser.new(self, msg, @lookahead)
122
+ end
123
+ end
124
+
125
+ class NotParser < LookAheadSensitiveParser
126
+ def initialize(parser, msg, la=1)
127
+ super(la)
128
+ @parser, @msg, @name = parser, msg, "~#{parser.name}"
129
+ end
130
+ def _parse ctxt
131
+ ind = ctxt.index
132
+ if @parser._parse ctxt
133
+ ctxt.index = ind
134
+ return ctxt.expecting(@msg)
135
+ end
136
+ return ctxt.retn(nil) if visible(ctxt, ind)
137
+ return false
138
+ end
139
+ def withLookahead(n)
140
+ NotParser.new(@parser, @msg, n)
141
+ end
142
+ def not()
143
+ @parser
144
+ end
145
+ end
146
+
147
+ class ExpectParser < Parser
148
+ def initialize(parser, msg)
149
+ super()
150
+ @parser, @msg, @name = parser, msg, msg
151
+ end
152
+ def _parse ctxt
153
+ ind = ctxt.index
154
+ return true if @parser._parse ctxt
155
+ return false unless ind == ctxt.index
156
+ ctxt.expecting(@msg)
157
+ end
158
+ end
159
+
160
+ class PlusParser < LookAheadSensitiveParser
161
+ def initialize(alts, la=1)
162
+ super(la)
163
+ @alts = alts
164
+ end
165
+ def _parse ctxt
166
+ ind, result, err = ctxt.index, ctxt.result, ctxt.error
167
+ for p in @alts
168
+ ctxt.reset_error
169
+ ctxt.index, ctxt.result = ind, result
170
+ return true if p._parse(ctxt)
171
+ return false unless visible(ctxt, ind)
172
+ err = Failures.add_error(err, ctxt.error)
173
+ end
174
+ ctxt.error = err
175
+ return false
176
+ end
177
+ def withLookahead(n)
178
+ PlusParser.new(@alts, n)
179
+ end
180
+ def plus other
181
+ PlusParser.new(@alts.dup << other, @lookahead).setName(name)
182
+ end
183
+ def_sig :plus, Parser
184
+ end
185
+
186
+
187
+ class AltParser < LookAheadSensitiveParser
188
+ def initialize(alts, la = 1)
189
+ super(la)
190
+ @alts, @lookahead = alts, la
191
+ end
192
+ def _parse ctxt
193
+ ind, result, err = ctxt.index, ctxt.result, ctxt.error
194
+ err_ind, err_pos = -1, -1
195
+ for p in @alts
196
+ ctxt.reset_error
197
+ ctxt.index, ctxt.result = ind, result
198
+ return true if p._parse(ctxt)
199
+ if ctxt.error.index > err_pos
200
+ err, err_ind, err_pos = ctxt.error, ctxt.index, ctxt.error.index
201
+ end
202
+ end
203
+ ctxt.index, ctxt.error = err_ind, err
204
+ return false
205
+ end
206
+ def withLookahead(n)
207
+ AltParser.new(@alts, n)
208
+ end
209
+ def | other
210
+ AltParser.new(@alts.dup << autobox_parser(other)).setName(name)
211
+ end
212
+ end
213
+
214
+
215
+ class BestParser < Parser
216
+ init :alts, :longer
217
+ def _parse ctxt
218
+ best_result, best_ind = nil, -1
219
+ err_ind, err_pos = -1, -1
220
+ ind, result, err = ctxt.index, ctxt.result, ctxt.error
221
+ for p in @alts
222
+ ctxt.reset_error
223
+ ctxt.index, ctxt.result = ind, result
224
+ if p._parse(ctxt)
225
+ err, now_ind = nil, ctxt.index
226
+ if best_ind==-1 || now_ind != best_ind && @longer == (now_ind>best_ind)
227
+ best_result, best_ind = ctxt.result, now_ind
228
+ end
229
+ elsif best_ind < 0 # no good match found yet.
230
+ if ctxt.error.index > err_pos
231
+ err_ind, err_pos = ctxt.index, ctxt.error.index
232
+ end
233
+ err = Failures.add_error(err, ctxt.error)
234
+ end
235
+ end
236
+ if best_ind >= 0
237
+ ctxt.index = best_ind
238
+ return ctxt.retn(best_result)
239
+ else
240
+ ctxt.error, ctxt.index = err, err_ind
241
+ return false
242
+ end
243
+ end
244
+ end
245
+
246
+ class BoundParser < Parser
247
+ init :parser, :proc
248
+ def _parse ctxt
249
+ return false unless @parser._parse(ctxt)
250
+ @proc.call(ctxt.result)._parse ctxt
251
+ end
252
+ end
253
+
254
+ class BoundnParser < Parser
255
+ init :parser, :proc
256
+ def _parse ctxt
257
+ return false unless @parser._parse(ctxt)
258
+ @proc.call(*ctxt.result)._parse ctxt
259
+ end
260
+ end
261
+
262
+ class MapParser < Parser
263
+ init :parser, :proc
264
+ def _parse ctxt
265
+ return false unless @parser._parse(ctxt)
266
+ ctxt.result = @proc.call(ctxt.result)
267
+ true
268
+ end
269
+ end
270
+
271
+ class MapnParser < Parser
272
+ init :parser, :proc
273
+ def _parse ctxt
274
+ return false unless @parser._parse(ctxt)
275
+ ctxt.result = @proc.call(*ctxt.result)
276
+ true
277
+ end
278
+ end
279
+
280
+ class SequenceParser < Parser
281
+ init :parsers, :proc
282
+ def _parse ctxt
283
+ if @proc.nil?
284
+ for p in @parsers
285
+ return false unless p._parse(ctxt)
286
+ end
287
+ else
288
+ results = []
289
+ for p in @parsers
290
+ return false unless p._parse(ctxt)
291
+ results << ctxt.result
292
+ end
293
+ ctxt.retn(@proc.call(*results))
294
+ end
295
+ return true
296
+ end
297
+ def seq(other, &block)
298
+ # TypeChecker.check_arg_type Parser, other, :seq
299
+ SequenceParser.new(@parsers.dup << other, &block)
300
+ end
301
+ def_sig :seq, Parser
302
+ end
303
+
304
+ class FollowedParser < Parser
305
+ init :p1, :p2
306
+ def _parse ctxt
307
+ return false unless @p1._parse ctxt
308
+ result = ctxt.result
309
+ return false unless @p2._parse ctxt
310
+ ctxt.retn(result)
311
+ end
312
+ end
313
+
314
+ class SatisfiesParser < Parser
315
+ init :pred, :expected
316
+ def _parse ctxt
317
+ elem = nil
318
+ if ctxt.eof || !@pred.call(elem=ctxt.current)
319
+ return ctxt.expecting(@expected)
320
+ end
321
+ ctxt.next
322
+ ctxt.retn elem
323
+ end
324
+ end
325
+
326
+ class AnyParser < Parser
327
+ def _parse ctxt
328
+ return ctxt.expecting if ctxt.eof
329
+ result = ctxt.current
330
+ ctxt.next
331
+ ctxt.retn result
332
+ end
333
+ end
334
+
335
+ class EofParser < Parser
336
+ init :msg
337
+ def _parse ctxt
338
+ return true if ctxt.eof
339
+ return ctxt.expecting(@msg)
340
+ end
341
+ end
342
+
343
+ class RegexpParser < Parser
344
+ init :ptn, :msg
345
+ def _parse ctxt
346
+ scanner = ctxt.scanner
347
+ result = scanner.check @ptn
348
+ if result.nil?
349
+ ctxt.expecting(@msg)
350
+ else
351
+ ctxt.advance(scanner.matched_size)
352
+ ctxt.retn(result)
353
+ end
354
+ end
355
+ end
356
+
357
+ class AreParser < Parser
358
+ init :vals, :msg
359
+ def _parse ctxt
360
+ if @vals.length > ctxt.available
361
+ return ctxt.expecting(@msg)
362
+ end
363
+ cur = 0
364
+ for cur in (0...@vals.length)
365
+ if @vals[cur] != ctxt.peek(cur)
366
+ return ctxt.expecting(@msg)
367
+ end
368
+ end
369
+ ctxt.advance(@vals.length)
370
+ ctxt.retn @vals
371
+ end
372
+ end
373
+
374
+ def downcase c
375
+ case when c >= ?A && c <=?Z then c + (?a - ?A) else c end
376
+ end
377
+
378
+ class StringCaseInsensitiveParser < Parser
379
+ init :str, :msg
380
+ def _parse ctxt
381
+ if @str.length > ctxt.available
382
+ return ctxt.expecting(@msg)
383
+ end
384
+ cur = 0
385
+ for cur in (0...@str.length)
386
+ if downcase(@str[cur]) != downcase(ctxt.peek(cur))
387
+ return ctxt.expecting(@msg)
388
+ end
389
+ end
390
+ result = ctxt.src[ctxt.index, @str.length]
391
+ ctxt.advance(@str.length)
392
+ ctxt.retn result
393
+ end
394
+ end
395
+
396
+ class FragmentParser < Parser
397
+ init :parser
398
+ def _parse ctxt
399
+ ind = ctxt.index
400
+ return false unless @parser._parse ctxt
401
+ ctxt.retn(ctxt.src[ind, ctxt.index-ind])
402
+ end
403
+ end
404
+
405
+ class TokenParser < Parser
406
+ init :symbol, :parser
407
+ def _parse ctxt
408
+ ind = ctxt.index
409
+ return false unless @parser._parse ctxt
410
+ raw = ctxt.result
411
+ raw = ctxt.src[ind, ctxt.index-ind] unless raw.kind_of? String
412
+ ctxt.retn(Token.new(@symbol, raw, ind))
413
+ end
414
+ end
415
+
416
+ class NestedParser < Parser
417
+ init :parser1, :parser2
418
+ def _parse ctxt
419
+ ind = ctxt.index
420
+ return false unless @parser1._parse ctxt
421
+ _run_nested(ind, ctxt, ctxt.result, @parser2)
422
+ end
423
+ private
424
+ def _run_nested(start, ctxt, src, parser)
425
+ ctxt.error = nil
426
+ new_ctxt = nil
427
+ if src.kind_of? String
428
+ new_ctxt = ParseContext.new(src)
429
+ return true if _run_parser parser, ctxt, new_ctxt
430
+ ctxt.index = start + new_ctxt.index
431
+ elsif src.kind_of? Array
432
+ new_ctxt = ParseContext.new(src)
433
+ return true if _run_parser parser, ctxt, new_ctxt
434
+ ctxt.index = start + _get_index(new_ctxt) unless new_ctxt.eof
435
+ else
436
+ new_ctxt = ParseContext.new([src])
437
+ return true if _run_parser parser, ctxt, new_ctxt
438
+ ctxt.index = ind unless new_ctxt.eof
439
+ end
440
+ ctxt.error.index = ctxt.index
441
+ false
442
+ end
443
+ def _get_index ctxt
444
+ cur = ctxt.current
445
+ return cur.index if cur.respond_to? :index
446
+ ctxt.index
447
+ end
448
+ def _run_parser parser, old_ctxt, new_ctxt
449
+ if parser._parse new_ctxt
450
+ old_ctxt.result = new_ctxt.result
451
+ true
452
+ else
453
+ old_ctxt.error = new_ctxt.error
454
+ false
455
+ end
456
+ end
457
+ end
458
+
459
+ class WatchParser < Parser
460
+ init :proc
461
+ def _parse ctxt
462
+ @proc.call(ctxt.result)
463
+ true
464
+ end
465
+ end
466
+
467
+ class WatchnParser < Parser
468
+ init :proc
469
+ def _parse ctxt
470
+ @proc.call(*ctxt.result)
471
+ true
472
+ end
473
+ end
474
+
475
+ class MapCurrentParser < Parser
476
+ init :proc
477
+ def _parse ctxt
478
+ ctxt.result = @proc.call(ctxt.result)
479
+ true
480
+ end
481
+ end
482
+
483
+ class MapnCurrentParser < Parser
484
+ init :proc
485
+ def _parse ctxt
486
+ ctxt.result = @proc.call(*ctxt.result)
487
+ true
488
+ end
489
+ end
490
+
491
+ class Repeat_Parser < Parser
492
+ init :parser, :times
493
+ def _parse ctxt
494
+ for i in (0...@times)
495
+ return false unless @parser._parse ctxt
496
+ end
497
+ return true
498
+ end
499
+ end
500
+
501
+ class RepeatParser < Parser
502
+ init :parser, :times
503
+ def _parse ctxt
504
+ result = []
505
+ for i in (0...@times)
506
+ return false unless @parser._parse ctxt
507
+ result << ctxt.result
508
+ end
509
+ return ctxt.retn(result)
510
+ end
511
+ end
512
+
513
+ class Many_Parser < Parser
514
+ init :parser, :least
515
+ def _parse ctxt
516
+ for i in (0...@least)
517
+ return false unless @parser._parse ctxt
518
+ end
519
+ while(true)
520
+ ind = ctxt.index
521
+ if @parser._parse ctxt
522
+ return true if ind==ctxt.index # infinite loop
523
+ next
524
+ end
525
+ return ind==ctxt.index
526
+ end
527
+ end
528
+ end
529
+
530
+ class ManyParser < Parser
531
+ init :parser, :least
532
+ def _parse ctxt
533
+ result = []
534
+ for i in (0...@least)
535
+ return false unless @parser._parse ctxt
536
+ result << ctxt.result
537
+ end
538
+ while(true)
539
+ ind = ctxt.index
540
+ if @parser._parse ctxt
541
+ result << ctxt.result
542
+ return ctxt.retn(result) if ind==ctxt.index # infinite loop
543
+ next
544
+ end
545
+ if ind==ctxt.index
546
+ return ctxt.retn(result)
547
+ else
548
+ return false
549
+ end
550
+ end
551
+ end
552
+ end
553
+
554
+ class Some_Parser < Parser
555
+ init :parser, :least, :max
556
+ def _parse ctxt
557
+ for i in (0...@least)
558
+ return false unless @parser._parse ctxt
559
+ end
560
+ for i in (@least...@max)
561
+ ind = ctxt.index
562
+ if @parser._parse ctxt
563
+ return true if ind==ctxt.index # infinite loop
564
+ next
565
+ end
566
+ return ind==ctxt.index
567
+ end
568
+ return true
569
+ end
570
+ end
571
+
572
+ class SomeParser < Parser
573
+ init :parser, :least, :max
574
+ def _parse ctxt
575
+ result = []
576
+ for i in (0...@least)
577
+ return false unless @parser._parse ctxt
578
+ result << ctxt.result
579
+ end
580
+ for i in (@least...@max)
581
+ ind = ctxt.index
582
+ if @parser._parse ctxt
583
+ result << ctxt.result
584
+ return ctxt.retn(result) if ind==ctxt.index # infinite loop
585
+ next
586
+ end
587
+ if ind==ctxt.index
588
+ return ctxt.retn(result)
589
+ else
590
+ return false
591
+ end
592
+ end
593
+ return ctxt.retn(result)
594
+ end
595
+ end
596
+
597
+ class OneParser < Parser
598
+ def _parse ctxt
599
+ true
600
+ end
601
+ end
602
+
603
+ class ZeroParser < Parser
604
+ def _parse ctxt
605
+ return ctxt.failure
606
+ end
607
+ end
608
+
609
+ class GetIndexParser < Parser
610
+ def _parse ctxt
611
+ ctxt.retn(ctxt.index)
612
+ end
613
+ end
614
+ class SetIndexParser < Parser
615
+ init :index
616
+ def _parse ctxt
617
+ ctxt.index = @index
618
+ end
619
+ end
620
+
621
+ Nil = ValueParser.new(nil)
622
+
623
+ end # module