json-kpeg 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,21 @@
1
+ module JsonKpeg::StringEscaper
2
+ def process_escapes (str)
3
+ str.gsub! /\\(u\d{4}|\D)/m do
4
+ seq = $1
5
+ case seq
6
+ when '/' then "\/"
7
+ when 'b' then "\b"
8
+ when 'f' then "\f"
9
+ when 'n' then "\n"
10
+ when 'r' then "\r"
11
+ when 't' then "\t"
12
+ when '"' then '"'
13
+ when '\\' then '\\'
14
+ when /u\d{4}/ then seq[1..-1].to_i.chr
15
+ else seq
16
+ end
17
+ end
18
+
19
+ str
20
+ end
21
+ end
@@ -0,0 +1,48 @@
1
+ %% name = JsonKpeg::Parser
2
+ %% {
3
+ require "json-kpeg/escaper"
4
+ include JsonKpeg::StringEscaper
5
+
6
+ attr_reader :result
7
+ attr_accessor :strict
8
+ }
9
+
10
+
11
+ value = object
12
+ | array
13
+ | string
14
+ | number
15
+ | "true" { true }
16
+ | "false" { false }
17
+ | "null" { nil }
18
+
19
+ object = "{" - "}" { {} }
20
+ | "{" - object-body:obj - "}" { obj }
21
+ object-body = object-pair:x (- "," - object-pair)*:xs { Hash[[x].concat(xs)] }
22
+ object-pair = string:k - ":" - value:v { [k, v] }
23
+
24
+ array = "[" - "]" { [] }
25
+ | "[" - array-body:arr - "]" { arr }
26
+ array-body = value:x (- "," - value)*:xs { [x].concat(xs) }
27
+
28
+ string = "\"" <string-char+> "\"" { process_escapes(text) }
29
+ string-char = !/["\\]/ .
30
+ | "\\" string-char-escape
31
+ string-char-escape = /[\/\"bfnrt]/
32
+ | "u" /\d{4}/
33
+
34
+ number = number-base:b number-exponent:e { b * (10 ** e) }
35
+ | number-base:b { b }
36
+ number-base = <number-base-whole number-base-frac> { text.to_f }
37
+ | <number-base-whole> { text.to_i }
38
+ number-base-whole = "0" | /-?[1-9]\d*/
39
+ number-base-frac = /\.\d+/
40
+ number-exponent = ("E"|"e") </[+-]?\d+/> { text.to_i }
41
+
42
+ - = /[ \t]*/
43
+
44
+ strict-root = object | array
45
+ root = ( &{self.strict} strict-root:v
46
+ | !{self.strict} value:v
47
+ )
48
+ { @result = v }
@@ -0,0 +1,1199 @@
1
+ class JsonKpeg::Parser
2
+ # STANDALONE START
3
+ def setup_parser(str, debug=false)
4
+ @string = str
5
+ @pos = 0
6
+ @memoizations = Hash.new { |h,k| h[k] = {} }
7
+ @result = nil
8
+ @failed_rule = nil
9
+ @failing_rule_offset = -1
10
+
11
+ setup_foreign_grammar
12
+ end
13
+
14
+ # This is distinct from setup_parser so that a standalone parser
15
+ # can redefine #initialize and still have access to the proper
16
+ # parser setup code.
17
+ #
18
+ def initialize(str, debug=false)
19
+ setup_parser(str, debug)
20
+ end
21
+
22
+ attr_reader :string
23
+ attr_reader :failing_rule_offset
24
+ attr_accessor :result, :pos
25
+
26
+ # STANDALONE START
27
+ def current_column(target=pos)
28
+ if c = string.rindex("\n", target-1)
29
+ return target - c - 1
30
+ end
31
+
32
+ target + 1
33
+ end
34
+
35
+ def current_line(target=pos)
36
+ cur_offset = 0
37
+ cur_line = 0
38
+
39
+ string.each_line do |line|
40
+ cur_line += 1
41
+ cur_offset += line.size
42
+ return cur_line if cur_offset >= target
43
+ end
44
+
45
+ -1
46
+ end
47
+
48
+ def lines
49
+ lines = []
50
+ string.each_line { |l| lines << l }
51
+ lines
52
+ end
53
+
54
+ #
55
+
56
+ def get_text(start)
57
+ @string[start..@pos-1]
58
+ end
59
+
60
+ def show_pos
61
+ width = 10
62
+ if @pos < width
63
+ "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")"
64
+ else
65
+ "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")"
66
+ end
67
+ end
68
+
69
+ def failure_info
70
+ l = current_line @failing_rule_offset
71
+ c = current_column @failing_rule_offset
72
+
73
+ if @failed_rule.kind_of? Symbol
74
+ info = self.class::Rules[@failed_rule]
75
+ "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'"
76
+ else
77
+ "line #{l}, column #{c}: failed rule '#{@failed_rule}'"
78
+ end
79
+ end
80
+
81
+ def failure_caret
82
+ l = current_line @failing_rule_offset
83
+ c = current_column @failing_rule_offset
84
+
85
+ line = lines[l-1]
86
+ "#{line}\n#{' ' * (c - 1)}^"
87
+ end
88
+
89
+ def failure_character
90
+ l = current_line @failing_rule_offset
91
+ c = current_column @failing_rule_offset
92
+ lines[l-1][c-1, 1]
93
+ end
94
+
95
+ def failure_oneline
96
+ l = current_line @failing_rule_offset
97
+ c = current_column @failing_rule_offset
98
+
99
+ char = lines[l-1][c-1, 1]
100
+
101
+ if @failed_rule.kind_of? Symbol
102
+ info = self.class::Rules[@failed_rule]
103
+ "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'"
104
+ else
105
+ "@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'"
106
+ end
107
+ end
108
+
109
+ class ParseError < RuntimeError
110
+ end
111
+
112
+ def raise_error
113
+ raise ParseError, failure_oneline
114
+ end
115
+
116
+ def show_error(io=STDOUT)
117
+ error_pos = @failing_rule_offset
118
+ line_no = current_line(error_pos)
119
+ col_no = current_column(error_pos)
120
+
121
+ io.puts "On line #{line_no}, column #{col_no}:"
122
+
123
+ if @failed_rule.kind_of? Symbol
124
+ info = self.class::Rules[@failed_rule]
125
+ io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')"
126
+ else
127
+ io.puts "Failed to match rule '#{@failed_rule}'"
128
+ end
129
+
130
+ io.puts "Got: #{string[error_pos,1].inspect}"
131
+ line = lines[line_no-1]
132
+ io.puts "=> #{line}"
133
+ io.print(" " * (col_no + 3))
134
+ io.puts "^"
135
+ end
136
+
137
+ def set_failed_rule(name)
138
+ if @pos > @failing_rule_offset
139
+ @failed_rule = name
140
+ @failing_rule_offset = @pos
141
+ end
142
+ end
143
+
144
+ attr_reader :failed_rule
145
+
146
+ def match_string(str)
147
+ len = str.size
148
+ if @string[pos,len] == str
149
+ @pos += len
150
+ return str
151
+ end
152
+
153
+ return nil
154
+ end
155
+
156
+ def scan(reg)
157
+ if m = reg.match(@string[@pos..-1])
158
+ width = m.end(0)
159
+ @pos += width
160
+ return true
161
+ end
162
+
163
+ return nil
164
+ end
165
+
166
+ if "".respond_to? :getbyte
167
+ def get_byte
168
+ if @pos >= @string.size
169
+ return nil
170
+ end
171
+
172
+ s = @string.getbyte @pos
173
+ @pos += 1
174
+ s
175
+ end
176
+ else
177
+ def get_byte
178
+ if @pos >= @string.size
179
+ return nil
180
+ end
181
+
182
+ s = @string[@pos]
183
+ @pos += 1
184
+ s
185
+ end
186
+ end
187
+
188
+ def parse(rule=nil)
189
+ if !rule
190
+ _root ? true : false
191
+ else
192
+ # This is not shared with code_generator.rb so this can be standalone
193
+ method = rule.gsub("-","_hyphen_")
194
+ __send__("_#{method}") ? true : false
195
+ end
196
+ end
197
+
198
+ class LeftRecursive
199
+ def initialize(detected=false)
200
+ @detected = detected
201
+ end
202
+
203
+ attr_accessor :detected
204
+ end
205
+
206
+ class MemoEntry
207
+ def initialize(ans, pos)
208
+ @ans = ans
209
+ @pos = pos
210
+ @uses = 1
211
+ @result = nil
212
+ end
213
+
214
+ attr_reader :ans, :pos, :uses, :result
215
+
216
+ def inc!
217
+ @uses += 1
218
+ end
219
+
220
+ def move!(ans, pos, result)
221
+ @ans = ans
222
+ @pos = pos
223
+ @result = result
224
+ end
225
+ end
226
+
227
+ def external_invoke(other, rule, *args)
228
+ old_pos = @pos
229
+ old_string = @string
230
+
231
+ @pos = other.pos
232
+ @string = other.string
233
+
234
+ begin
235
+ if val = __send__(rule, *args)
236
+ other.pos = @pos
237
+ other.result = @result
238
+ else
239
+ other.set_failed_rule "#{self.class}##{rule}"
240
+ end
241
+ val
242
+ ensure
243
+ @pos = old_pos
244
+ @string = old_string
245
+ end
246
+ end
247
+
248
+ def apply_with_args(rule, *args)
249
+ memo_key = [rule, args]
250
+ if m = @memoizations[memo_key][@pos]
251
+ m.inc!
252
+
253
+ prev = @pos
254
+ @pos = m.pos
255
+ if m.ans.kind_of? LeftRecursive
256
+ m.ans.detected = true
257
+ return nil
258
+ end
259
+
260
+ @result = m.result
261
+
262
+ return m.ans
263
+ else
264
+ lr = LeftRecursive.new(false)
265
+ m = MemoEntry.new(lr, @pos)
266
+ @memoizations[memo_key][@pos] = m
267
+ start_pos = @pos
268
+
269
+ ans = __send__ rule, *args
270
+
271
+ m.move! ans, @pos, @result
272
+
273
+ # Don't bother trying to grow the left recursion
274
+ # if it's failing straight away (thus there is no seed)
275
+ if ans and lr.detected
276
+ return grow_lr(rule, args, start_pos, m)
277
+ else
278
+ return ans
279
+ end
280
+
281
+ return ans
282
+ end
283
+ end
284
+
285
+ def apply(rule)
286
+ if m = @memoizations[rule][@pos]
287
+ m.inc!
288
+
289
+ prev = @pos
290
+ @pos = m.pos
291
+ if m.ans.kind_of? LeftRecursive
292
+ m.ans.detected = true
293
+ return nil
294
+ end
295
+
296
+ @result = m.result
297
+
298
+ return m.ans
299
+ else
300
+ lr = LeftRecursive.new(false)
301
+ m = MemoEntry.new(lr, @pos)
302
+ @memoizations[rule][@pos] = m
303
+ start_pos = @pos
304
+
305
+ ans = __send__ rule
306
+
307
+ m.move! ans, @pos, @result
308
+
309
+ # Don't bother trying to grow the left recursion
310
+ # if it's failing straight away (thus there is no seed)
311
+ if ans and lr.detected
312
+ return grow_lr(rule, nil, start_pos, m)
313
+ else
314
+ return ans
315
+ end
316
+
317
+ return ans
318
+ end
319
+ end
320
+
321
+ def grow_lr(rule, args, start_pos, m)
322
+ while true
323
+ @pos = start_pos
324
+ @result = m.result
325
+
326
+ if args
327
+ ans = __send__ rule, *args
328
+ else
329
+ ans = __send__ rule
330
+ end
331
+ return nil unless ans
332
+
333
+ break if @pos <= m.pos
334
+
335
+ m.move! ans, @pos, @result
336
+ end
337
+
338
+ @result = m.result
339
+ @pos = m.pos
340
+ return m.ans
341
+ end
342
+
343
+ class RuleInfo
344
+ def initialize(name, rendered)
345
+ @name = name
346
+ @rendered = rendered
347
+ end
348
+
349
+ attr_reader :name, :rendered
350
+ end
351
+
352
+ def self.rule_info(name, rendered)
353
+ RuleInfo.new(name, rendered)
354
+ end
355
+
356
+ #
357
+
358
+
359
+ require "json-kpeg/escaper"
360
+ include JsonKpeg::StringEscaper
361
+
362
+ attr_reader :result
363
+ attr_accessor :strict
364
+
365
+
366
+ def setup_foreign_grammar; end
367
+
368
+ # value = (object | array | string | number | "true" { true } | "false" { false } | "null" { nil })
369
+ def _value
370
+
371
+ _save = self.pos
372
+ while true # choice
373
+ _tmp = apply(:_object)
374
+ break if _tmp
375
+ self.pos = _save
376
+ _tmp = apply(:_array)
377
+ break if _tmp
378
+ self.pos = _save
379
+ _tmp = apply(:_string)
380
+ break if _tmp
381
+ self.pos = _save
382
+ _tmp = apply(:_number)
383
+ break if _tmp
384
+ self.pos = _save
385
+
386
+ _save1 = self.pos
387
+ while true # sequence
388
+ _tmp = match_string("true")
389
+ unless _tmp
390
+ self.pos = _save1
391
+ break
392
+ end
393
+ @result = begin; true ; end
394
+ _tmp = true
395
+ unless _tmp
396
+ self.pos = _save1
397
+ end
398
+ break
399
+ end # end sequence
400
+
401
+ break if _tmp
402
+ self.pos = _save
403
+
404
+ _save2 = self.pos
405
+ while true # sequence
406
+ _tmp = match_string("false")
407
+ unless _tmp
408
+ self.pos = _save2
409
+ break
410
+ end
411
+ @result = begin; false ; end
412
+ _tmp = true
413
+ unless _tmp
414
+ self.pos = _save2
415
+ end
416
+ break
417
+ end # end sequence
418
+
419
+ break if _tmp
420
+ self.pos = _save
421
+
422
+ _save3 = self.pos
423
+ while true # sequence
424
+ _tmp = match_string("null")
425
+ unless _tmp
426
+ self.pos = _save3
427
+ break
428
+ end
429
+ @result = begin; nil ; end
430
+ _tmp = true
431
+ unless _tmp
432
+ self.pos = _save3
433
+ end
434
+ break
435
+ end # end sequence
436
+
437
+ break if _tmp
438
+ self.pos = _save
439
+ break
440
+ end # end choice
441
+
442
+ set_failed_rule :_value unless _tmp
443
+ return _tmp
444
+ end
445
+
446
+ # object = ("{" - "}" { {} } | "{" - object-body:obj - "}" { obj })
447
+ def _object
448
+
449
+ _save = self.pos
450
+ while true # choice
451
+
452
+ _save1 = self.pos
453
+ while true # sequence
454
+ _tmp = match_string("{")
455
+ unless _tmp
456
+ self.pos = _save1
457
+ break
458
+ end
459
+ _tmp = apply(:__hyphen_)
460
+ unless _tmp
461
+ self.pos = _save1
462
+ break
463
+ end
464
+ _tmp = match_string("}")
465
+ unless _tmp
466
+ self.pos = _save1
467
+ break
468
+ end
469
+ @result = begin; {} ; end
470
+ _tmp = true
471
+ unless _tmp
472
+ self.pos = _save1
473
+ end
474
+ break
475
+ end # end sequence
476
+
477
+ break if _tmp
478
+ self.pos = _save
479
+
480
+ _save2 = self.pos
481
+ while true # sequence
482
+ _tmp = match_string("{")
483
+ unless _tmp
484
+ self.pos = _save2
485
+ break
486
+ end
487
+ _tmp = apply(:__hyphen_)
488
+ unless _tmp
489
+ self.pos = _save2
490
+ break
491
+ end
492
+ _tmp = apply(:_object_hyphen_body)
493
+ obj = @result
494
+ unless _tmp
495
+ self.pos = _save2
496
+ break
497
+ end
498
+ _tmp = apply(:__hyphen_)
499
+ unless _tmp
500
+ self.pos = _save2
501
+ break
502
+ end
503
+ _tmp = match_string("}")
504
+ unless _tmp
505
+ self.pos = _save2
506
+ break
507
+ end
508
+ @result = begin; obj ; end
509
+ _tmp = true
510
+ unless _tmp
511
+ self.pos = _save2
512
+ end
513
+ break
514
+ end # end sequence
515
+
516
+ break if _tmp
517
+ self.pos = _save
518
+ break
519
+ end # end choice
520
+
521
+ set_failed_rule :_object unless _tmp
522
+ return _tmp
523
+ end
524
+
525
+ # object-body = object-pair:x (- "," - object-pair)*:xs { Hash[[x].concat(xs)] }
526
+ def _object_hyphen_body
527
+
528
+ _save = self.pos
529
+ while true # sequence
530
+ _tmp = apply(:_object_hyphen_pair)
531
+ x = @result
532
+ unless _tmp
533
+ self.pos = _save
534
+ break
535
+ end
536
+ _ary = []
537
+ while true
538
+
539
+ _save2 = self.pos
540
+ while true # sequence
541
+ _tmp = apply(:__hyphen_)
542
+ unless _tmp
543
+ self.pos = _save2
544
+ break
545
+ end
546
+ _tmp = match_string(",")
547
+ unless _tmp
548
+ self.pos = _save2
549
+ break
550
+ end
551
+ _tmp = apply(:__hyphen_)
552
+ unless _tmp
553
+ self.pos = _save2
554
+ break
555
+ end
556
+ _tmp = apply(:_object_hyphen_pair)
557
+ unless _tmp
558
+ self.pos = _save2
559
+ end
560
+ break
561
+ end # end sequence
562
+
563
+ _ary << @result if _tmp
564
+ break unless _tmp
565
+ end
566
+ _tmp = true
567
+ @result = _ary
568
+ xs = @result
569
+ unless _tmp
570
+ self.pos = _save
571
+ break
572
+ end
573
+ @result = begin; Hash[[x].concat(xs)] ; end
574
+ _tmp = true
575
+ unless _tmp
576
+ self.pos = _save
577
+ end
578
+ break
579
+ end # end sequence
580
+
581
+ set_failed_rule :_object_hyphen_body unless _tmp
582
+ return _tmp
583
+ end
584
+
585
+ # object-pair = string:k - ":" - value:v { [k, v] }
586
+ def _object_hyphen_pair
587
+
588
+ _save = self.pos
589
+ while true # sequence
590
+ _tmp = apply(:_string)
591
+ k = @result
592
+ unless _tmp
593
+ self.pos = _save
594
+ break
595
+ end
596
+ _tmp = apply(:__hyphen_)
597
+ unless _tmp
598
+ self.pos = _save
599
+ break
600
+ end
601
+ _tmp = match_string(":")
602
+ unless _tmp
603
+ self.pos = _save
604
+ break
605
+ end
606
+ _tmp = apply(:__hyphen_)
607
+ unless _tmp
608
+ self.pos = _save
609
+ break
610
+ end
611
+ _tmp = apply(:_value)
612
+ v = @result
613
+ unless _tmp
614
+ self.pos = _save
615
+ break
616
+ end
617
+ @result = begin; [k, v] ; end
618
+ _tmp = true
619
+ unless _tmp
620
+ self.pos = _save
621
+ end
622
+ break
623
+ end # end sequence
624
+
625
+ set_failed_rule :_object_hyphen_pair unless _tmp
626
+ return _tmp
627
+ end
628
+
629
+ # array = ("[" - "]" { [] } | "[" - array-body:arr - "]" { arr })
630
+ def _array
631
+
632
+ _save = self.pos
633
+ while true # choice
634
+
635
+ _save1 = self.pos
636
+ while true # sequence
637
+ _tmp = match_string("[")
638
+ unless _tmp
639
+ self.pos = _save1
640
+ break
641
+ end
642
+ _tmp = apply(:__hyphen_)
643
+ unless _tmp
644
+ self.pos = _save1
645
+ break
646
+ end
647
+ _tmp = match_string("]")
648
+ unless _tmp
649
+ self.pos = _save1
650
+ break
651
+ end
652
+ @result = begin; [] ; end
653
+ _tmp = true
654
+ unless _tmp
655
+ self.pos = _save1
656
+ end
657
+ break
658
+ end # end sequence
659
+
660
+ break if _tmp
661
+ self.pos = _save
662
+
663
+ _save2 = self.pos
664
+ while true # sequence
665
+ _tmp = match_string("[")
666
+ unless _tmp
667
+ self.pos = _save2
668
+ break
669
+ end
670
+ _tmp = apply(:__hyphen_)
671
+ unless _tmp
672
+ self.pos = _save2
673
+ break
674
+ end
675
+ _tmp = apply(:_array_hyphen_body)
676
+ arr = @result
677
+ unless _tmp
678
+ self.pos = _save2
679
+ break
680
+ end
681
+ _tmp = apply(:__hyphen_)
682
+ unless _tmp
683
+ self.pos = _save2
684
+ break
685
+ end
686
+ _tmp = match_string("]")
687
+ unless _tmp
688
+ self.pos = _save2
689
+ break
690
+ end
691
+ @result = begin; arr ; end
692
+ _tmp = true
693
+ unless _tmp
694
+ self.pos = _save2
695
+ end
696
+ break
697
+ end # end sequence
698
+
699
+ break if _tmp
700
+ self.pos = _save
701
+ break
702
+ end # end choice
703
+
704
+ set_failed_rule :_array unless _tmp
705
+ return _tmp
706
+ end
707
+
708
+ # array-body = value:x (- "," - value)*:xs { [x].concat(xs) }
709
+ def _array_hyphen_body
710
+
711
+ _save = self.pos
712
+ while true # sequence
713
+ _tmp = apply(:_value)
714
+ x = @result
715
+ unless _tmp
716
+ self.pos = _save
717
+ break
718
+ end
719
+ _ary = []
720
+ while true
721
+
722
+ _save2 = self.pos
723
+ while true # sequence
724
+ _tmp = apply(:__hyphen_)
725
+ unless _tmp
726
+ self.pos = _save2
727
+ break
728
+ end
729
+ _tmp = match_string(",")
730
+ unless _tmp
731
+ self.pos = _save2
732
+ break
733
+ end
734
+ _tmp = apply(:__hyphen_)
735
+ unless _tmp
736
+ self.pos = _save2
737
+ break
738
+ end
739
+ _tmp = apply(:_value)
740
+ unless _tmp
741
+ self.pos = _save2
742
+ end
743
+ break
744
+ end # end sequence
745
+
746
+ _ary << @result if _tmp
747
+ break unless _tmp
748
+ end
749
+ _tmp = true
750
+ @result = _ary
751
+ xs = @result
752
+ unless _tmp
753
+ self.pos = _save
754
+ break
755
+ end
756
+ @result = begin; [x].concat(xs) ; end
757
+ _tmp = true
758
+ unless _tmp
759
+ self.pos = _save
760
+ end
761
+ break
762
+ end # end sequence
763
+
764
+ set_failed_rule :_array_hyphen_body unless _tmp
765
+ return _tmp
766
+ end
767
+
768
+ # string = "\"" < string-char+ > "\"" { process_escapes(text) }
769
+ def _string
770
+
771
+ _save = self.pos
772
+ while true # sequence
773
+ _tmp = match_string("\"")
774
+ unless _tmp
775
+ self.pos = _save
776
+ break
777
+ end
778
+ _text_start = self.pos
779
+ _save1 = self.pos
780
+ _tmp = apply(:_string_hyphen_char)
781
+ if _tmp
782
+ while true
783
+ _tmp = apply(:_string_hyphen_char)
784
+ break unless _tmp
785
+ end
786
+ _tmp = true
787
+ else
788
+ self.pos = _save1
789
+ end
790
+ if _tmp
791
+ text = get_text(_text_start)
792
+ end
793
+ unless _tmp
794
+ self.pos = _save
795
+ break
796
+ end
797
+ _tmp = match_string("\"")
798
+ unless _tmp
799
+ self.pos = _save
800
+ break
801
+ end
802
+ @result = begin; process_escapes(text) ; end
803
+ _tmp = true
804
+ unless _tmp
805
+ self.pos = _save
806
+ end
807
+ break
808
+ end # end sequence
809
+
810
+ set_failed_rule :_string unless _tmp
811
+ return _tmp
812
+ end
813
+
814
+ # string-char = (!/["\\]/ . | "\\" string-char-escape)
815
+ def _string_hyphen_char
816
+
817
+ _save = self.pos
818
+ while true # choice
819
+
820
+ _save1 = self.pos
821
+ while true # sequence
822
+ _save2 = self.pos
823
+ _tmp = scan(/\A(?-mix:["\\])/)
824
+ _tmp = _tmp ? nil : true
825
+ self.pos = _save2
826
+ unless _tmp
827
+ self.pos = _save1
828
+ break
829
+ end
830
+ _tmp = get_byte
831
+ unless _tmp
832
+ self.pos = _save1
833
+ end
834
+ break
835
+ end # end sequence
836
+
837
+ break if _tmp
838
+ self.pos = _save
839
+
840
+ _save3 = self.pos
841
+ while true # sequence
842
+ _tmp = match_string("\\")
843
+ unless _tmp
844
+ self.pos = _save3
845
+ break
846
+ end
847
+ _tmp = apply(:_string_hyphen_char_hyphen_escape)
848
+ unless _tmp
849
+ self.pos = _save3
850
+ end
851
+ break
852
+ end # end sequence
853
+
854
+ break if _tmp
855
+ self.pos = _save
856
+ break
857
+ end # end choice
858
+
859
+ set_failed_rule :_string_hyphen_char unless _tmp
860
+ return _tmp
861
+ end
862
+
863
+ # string-char-escape = (/[\/\"bfnrt]/ | "u" /\d{4}/)
864
+ def _string_hyphen_char_hyphen_escape
865
+
866
+ _save = self.pos
867
+ while true # choice
868
+ _tmp = scan(/\A(?-mix:[\/\"bfnrt])/)
869
+ break if _tmp
870
+ self.pos = _save
871
+
872
+ _save1 = self.pos
873
+ while true # sequence
874
+ _tmp = match_string("u")
875
+ unless _tmp
876
+ self.pos = _save1
877
+ break
878
+ end
879
+ _tmp = scan(/\A(?-mix:\d{4})/)
880
+ unless _tmp
881
+ self.pos = _save1
882
+ end
883
+ break
884
+ end # end sequence
885
+
886
+ break if _tmp
887
+ self.pos = _save
888
+ break
889
+ end # end choice
890
+
891
+ set_failed_rule :_string_hyphen_char_hyphen_escape unless _tmp
892
+ return _tmp
893
+ end
894
+
895
+ # number = (number-base:b number-exponent:e { b * (10 ** e) } | number-base:b { b })
896
+ def _number
897
+
898
+ _save = self.pos
899
+ while true # choice
900
+
901
+ _save1 = self.pos
902
+ while true # sequence
903
+ _tmp = apply(:_number_hyphen_base)
904
+ b = @result
905
+ unless _tmp
906
+ self.pos = _save1
907
+ break
908
+ end
909
+ _tmp = apply(:_number_hyphen_exponent)
910
+ e = @result
911
+ unless _tmp
912
+ self.pos = _save1
913
+ break
914
+ end
915
+ @result = begin; b * (10 ** e) ; end
916
+ _tmp = true
917
+ unless _tmp
918
+ self.pos = _save1
919
+ end
920
+ break
921
+ end # end sequence
922
+
923
+ break if _tmp
924
+ self.pos = _save
925
+
926
+ _save2 = self.pos
927
+ while true # sequence
928
+ _tmp = apply(:_number_hyphen_base)
929
+ b = @result
930
+ unless _tmp
931
+ self.pos = _save2
932
+ break
933
+ end
934
+ @result = begin; b ; end
935
+ _tmp = true
936
+ unless _tmp
937
+ self.pos = _save2
938
+ end
939
+ break
940
+ end # end sequence
941
+
942
+ break if _tmp
943
+ self.pos = _save
944
+ break
945
+ end # end choice
946
+
947
+ set_failed_rule :_number unless _tmp
948
+ return _tmp
949
+ end
950
+
951
+ # number-base = (< number-base-whole number-base-frac > { text.to_f } | < number-base-whole > { text.to_i })
952
+ def _number_hyphen_base
953
+
954
+ _save = self.pos
955
+ while true # choice
956
+
957
+ _save1 = self.pos
958
+ while true # sequence
959
+ _text_start = self.pos
960
+
961
+ _save2 = self.pos
962
+ while true # sequence
963
+ _tmp = apply(:_number_hyphen_base_hyphen_whole)
964
+ unless _tmp
965
+ self.pos = _save2
966
+ break
967
+ end
968
+ _tmp = apply(:_number_hyphen_base_hyphen_frac)
969
+ unless _tmp
970
+ self.pos = _save2
971
+ end
972
+ break
973
+ end # end sequence
974
+
975
+ if _tmp
976
+ text = get_text(_text_start)
977
+ end
978
+ unless _tmp
979
+ self.pos = _save1
980
+ break
981
+ end
982
+ @result = begin; text.to_f ; end
983
+ _tmp = true
984
+ unless _tmp
985
+ self.pos = _save1
986
+ end
987
+ break
988
+ end # end sequence
989
+
990
+ break if _tmp
991
+ self.pos = _save
992
+
993
+ _save3 = self.pos
994
+ while true # sequence
995
+ _text_start = self.pos
996
+ _tmp = apply(:_number_hyphen_base_hyphen_whole)
997
+ if _tmp
998
+ text = get_text(_text_start)
999
+ end
1000
+ unless _tmp
1001
+ self.pos = _save3
1002
+ break
1003
+ end
1004
+ @result = begin; text.to_i ; end
1005
+ _tmp = true
1006
+ unless _tmp
1007
+ self.pos = _save3
1008
+ end
1009
+ break
1010
+ end # end sequence
1011
+
1012
+ break if _tmp
1013
+ self.pos = _save
1014
+ break
1015
+ end # end choice
1016
+
1017
+ set_failed_rule :_number_hyphen_base unless _tmp
1018
+ return _tmp
1019
+ end
1020
+
1021
+ # number-base-whole = ("0" | /-?[1-9]\d*/)
1022
+ def _number_hyphen_base_hyphen_whole
1023
+
1024
+ _save = self.pos
1025
+ while true # choice
1026
+ _tmp = match_string("0")
1027
+ break if _tmp
1028
+ self.pos = _save
1029
+ _tmp = scan(/\A(?-mix:-?[1-9]\d*)/)
1030
+ break if _tmp
1031
+ self.pos = _save
1032
+ break
1033
+ end # end choice
1034
+
1035
+ set_failed_rule :_number_hyphen_base_hyphen_whole unless _tmp
1036
+ return _tmp
1037
+ end
1038
+
1039
+ # number-base-frac = /\.\d+/
1040
+ def _number_hyphen_base_hyphen_frac
1041
+ _tmp = scan(/\A(?-mix:\.\d+)/)
1042
+ set_failed_rule :_number_hyphen_base_hyphen_frac unless _tmp
1043
+ return _tmp
1044
+ end
1045
+
1046
+ # number-exponent = ("E" | "e") < /[+-]?\d+/ > { text.to_i }
1047
+ def _number_hyphen_exponent
1048
+
1049
+ _save = self.pos
1050
+ while true # sequence
1051
+
1052
+ _save1 = self.pos
1053
+ while true # choice
1054
+ _tmp = match_string("E")
1055
+ break if _tmp
1056
+ self.pos = _save1
1057
+ _tmp = match_string("e")
1058
+ break if _tmp
1059
+ self.pos = _save1
1060
+ break
1061
+ end # end choice
1062
+
1063
+ unless _tmp
1064
+ self.pos = _save
1065
+ break
1066
+ end
1067
+ _text_start = self.pos
1068
+ _tmp = scan(/\A(?-mix:[+-]?\d+)/)
1069
+ if _tmp
1070
+ text = get_text(_text_start)
1071
+ end
1072
+ unless _tmp
1073
+ self.pos = _save
1074
+ break
1075
+ end
1076
+ @result = begin; text.to_i ; end
1077
+ _tmp = true
1078
+ unless _tmp
1079
+ self.pos = _save
1080
+ end
1081
+ break
1082
+ end # end sequence
1083
+
1084
+ set_failed_rule :_number_hyphen_exponent unless _tmp
1085
+ return _tmp
1086
+ end
1087
+
1088
+ # - = /[ \t]*/
1089
+ def __hyphen_
1090
+ _tmp = scan(/\A(?-mix:[ \t]*)/)
1091
+ set_failed_rule :__hyphen_ unless _tmp
1092
+ return _tmp
1093
+ end
1094
+
1095
+ # strict-root = (object | array)
1096
+ def _strict_hyphen_root
1097
+
1098
+ _save = self.pos
1099
+ while true # choice
1100
+ _tmp = apply(:_object)
1101
+ break if _tmp
1102
+ self.pos = _save
1103
+ _tmp = apply(:_array)
1104
+ break if _tmp
1105
+ self.pos = _save
1106
+ break
1107
+ end # end choice
1108
+
1109
+ set_failed_rule :_strict_hyphen_root unless _tmp
1110
+ return _tmp
1111
+ end
1112
+
1113
+ # root = (&{self.strict} strict-root:v | !{self.strict} value:v) { @result = v }
1114
+ def _root
1115
+
1116
+ _save = self.pos
1117
+ while true # sequence
1118
+
1119
+ _save1 = self.pos
1120
+ while true # choice
1121
+
1122
+ _save2 = self.pos
1123
+ while true # sequence
1124
+ _save3 = self.pos
1125
+ _tmp = begin; self.strict; end
1126
+ self.pos = _save3
1127
+ unless _tmp
1128
+ self.pos = _save2
1129
+ break
1130
+ end
1131
+ _tmp = apply(:_strict_hyphen_root)
1132
+ v = @result
1133
+ unless _tmp
1134
+ self.pos = _save2
1135
+ end
1136
+ break
1137
+ end # end sequence
1138
+
1139
+ break if _tmp
1140
+ self.pos = _save1
1141
+
1142
+ _save4 = self.pos
1143
+ while true # sequence
1144
+ _save5 = self.pos
1145
+ _tmp = begin; self.strict; end
1146
+ _tmp = _tmp ? nil : true
1147
+ self.pos = _save5
1148
+ unless _tmp
1149
+ self.pos = _save4
1150
+ break
1151
+ end
1152
+ _tmp = apply(:_value)
1153
+ v = @result
1154
+ unless _tmp
1155
+ self.pos = _save4
1156
+ end
1157
+ break
1158
+ end # end sequence
1159
+
1160
+ break if _tmp
1161
+ self.pos = _save1
1162
+ break
1163
+ end # end choice
1164
+
1165
+ unless _tmp
1166
+ self.pos = _save
1167
+ break
1168
+ end
1169
+ @result = begin; @result = v ; end
1170
+ _tmp = true
1171
+ unless _tmp
1172
+ self.pos = _save
1173
+ end
1174
+ break
1175
+ end # end sequence
1176
+
1177
+ set_failed_rule :_root unless _tmp
1178
+ return _tmp
1179
+ end
1180
+
1181
+ Rules = {}
1182
+ Rules[:_value] = rule_info("value", "(object | array | string | number | \"true\" { true } | \"false\" { false } | \"null\" { nil })")
1183
+ Rules[:_object] = rule_info("object", "(\"{\" - \"}\" { {} } | \"{\" - object-body:obj - \"}\" { obj })")
1184
+ Rules[:_object_hyphen_body] = rule_info("object-body", "object-pair:x (- \",\" - object-pair)*:xs { Hash[[x].concat(xs)] }")
1185
+ Rules[:_object_hyphen_pair] = rule_info("object-pair", "string:k - \":\" - value:v { [k, v] }")
1186
+ Rules[:_array] = rule_info("array", "(\"[\" - \"]\" { [] } | \"[\" - array-body:arr - \"]\" { arr })")
1187
+ Rules[:_array_hyphen_body] = rule_info("array-body", "value:x (- \",\" - value)*:xs { [x].concat(xs) }")
1188
+ Rules[:_string] = rule_info("string", "\"\\\"\" < string-char+ > \"\\\"\" { process_escapes(text) }")
1189
+ Rules[:_string_hyphen_char] = rule_info("string-char", "(!/[\"\\\\]/ . | \"\\\\\" string-char-escape)")
1190
+ Rules[:_string_hyphen_char_hyphen_escape] = rule_info("string-char-escape", "(/[\\/\\\"bfnrt]/ | \"u\" /\\d{4}/)")
1191
+ Rules[:_number] = rule_info("number", "(number-base:b number-exponent:e { b * (10 ** e) } | number-base:b { b })")
1192
+ Rules[:_number_hyphen_base] = rule_info("number-base", "(< number-base-whole number-base-frac > { text.to_f } | < number-base-whole > { text.to_i })")
1193
+ Rules[:_number_hyphen_base_hyphen_whole] = rule_info("number-base-whole", "(\"0\" | /-?[1-9]\\d*/)")
1194
+ Rules[:_number_hyphen_base_hyphen_frac] = rule_info("number-base-frac", "/\\.\\d+/")
1195
+ Rules[:_number_hyphen_exponent] = rule_info("number-exponent", "(\"E\" | \"e\") < /[+-]?\\d+/ > { text.to_i }")
1196
+ Rules[:__hyphen_] = rule_info("-", "/[ \\t]*/")
1197
+ Rules[:_strict_hyphen_root] = rule_info("strict-root", "(object | array)")
1198
+ Rules[:_root] = rule_info("root", "(&{self.strict} strict-root:v | !{self.strict} value:v) { @result = v }")
1199
+ end
@@ -0,0 +1,3 @@
1
+ module JsonKpeg
2
+ VERSION = "0.1.0"
3
+ end
data/lib/json-kpeg.rb ADDED
@@ -0,0 +1,3 @@
1
+ module JsonKpeg
2
+ require 'json-kpeg/parser.kpeg.rb'
3
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: json-kpeg
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Jonathan Castello
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-05-16 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: bundler
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 23
30
+ segments:
31
+ - 1
32
+ - 0
33
+ - 0
34
+ version: 1.0.0
35
+ type: :development
36
+ version_requirements: *id001
37
+ description: A simple JSON parser implemented using kpeg.
38
+ email: jonathan@jonathan.com
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - lib/json-kpeg.rb
47
+ - lib/json-kpeg/escaper.rb
48
+ - lib/json-kpeg/parser.kpeg
49
+ - lib/json-kpeg/parser.kpeg.rb
50
+ - lib/json-kpeg/version.rb
51
+ has_rdoc: true
52
+ homepage: https://github.com/Twisol/json-kpeg
53
+ licenses:
54
+ - MIT
55
+ post_install_message:
56
+ rdoc_options: []
57
+
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ hash: 3
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.5.2
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: A JSON parser implemented using kpeg.
85
+ test_files: []
86
+