| Class | CodeRay::Scanners::JSON |
| In: |
lib/coderay/scanners/json.rb
|
| Parent: | Scanner |
| KINDS_NOT_LOC | = | [ :float, :char, :content, :delimiter, :error, :integer, :operator, :value, ] |
| ESCAPE | = | / [bfnrt\\"\/] /x |
| UNICODE_ESCAPE | = | / u[a-fA-F0-9]{4} /x |
# File lib/coderay/scanners/json.rb, line 19
19: def scan_tokens tokens, options
20:
21: state = :initial
22: stack = []
23: key_expected = false
24:
25: until eos?
26:
27: kind = nil
28: match = nil
29:
30: case state
31:
32: when :initial
33: if match = scan(/ \s+ | \\\n /x)
34: tokens << [match, :space]
35: next
36: elsif match = scan(/ [:,\[{\]}] /x)
37: kind = :operator
38: case match
39: when '{' then stack << :object; key_expected = true
40: when '[' then stack << :array
41: when ':' then key_expected = false
42: when ',' then key_expected = true if stack.last == :object
43: when '}', ']' then stack.pop # no error recovery, but works for valid JSON
44: end
45: elsif match = scan(/ true | false | null /x)
46: kind = :value
47: elsif match = scan(/-?(?:0|[1-9]\d*)/)
48: kind = :integer
49: if scan(/\.\d+(?:[eE][-+]?\d+)?|[eE][-+]?\d+/)
50: match << matched
51: kind = :float
52: end
53: elsif match = scan(/"/)
54: state = key_expected ? :key : :string
55: tokens << [:open, state]
56: kind = :delimiter
57: else
58: getch
59: kind = :error
60: end
61:
62: when :string, :key
63: if scan(/[^\\"]+/)
64: kind = :content
65: elsif scan(/"/)
66: tokens << ['"', :delimiter]
67: tokens << [:close, state]
68: state = :initial
69: next
70: elsif scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
71: kind = :char
72: elsif scan(/\\./m)
73: kind = :content
74: elsif scan(/ \\ | $ /x)
75: tokens << [:close, state]
76: kind = :error
77: state = :initial
78: else
79: raise_inspect "else case \" reached; %p not handled." % peek(1), tokens
80: end
81:
82: else
83: raise_inspect 'Unknown state', tokens
84:
85: end
86:
87: match ||= matched
88: if $CODERAY_DEBUG and not kind
89: raise_inspect 'Error token %p in line %d' %
90: [[match, kind], line], tokens
91: end
92: raise_inspect 'Empty token', tokens unless match
93:
94: tokens << [match, kind]
95:
96: end
97:
98: if [:string, :key].include? state
99: tokens << [:close, state]
100: end
101:
102: tokens
103: end