rparsec 0.4 → 0.4.1

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