json-kpeg 0.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,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
+