rparsec-ruby19 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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