| Class | CodeRay::Scanners::JSON |
| In: |
lib/coderay/scanners/json.rb
|
| Parent: | Scanner |
Scanner for JSON (JavaScript Object Notation).
See json.org/ for a definition of the JSON lexic/grammar.
# File lib/coderay/scanners/json.rb, line 21
21: def scan_tokens encoder, options
22:
23: state = :initial
24: stack = []
25: key_expected = false
26:
27: until eos?
28:
29: case state
30:
31: when :initial
32: if match = scan(/ \s+ /x)
33: encoder.text_token match, :space
34: elsif match = scan(/"/)
35: state = key_expected ? :key : :string
36: encoder.begin_group state
37: encoder.text_token match, :delimiter
38: elsif match = scan(/ [:,\[{\]}] /x)
39: encoder.text_token match, :operator
40: case match
41: when ':' then key_expected = false
42: when ',' then key_expected = true if stack.last == :object
43: when '{' then stack << :object; key_expected = true
44: when '[' then stack << :array
45: when '}', ']' then stack.pop # no error recovery, but works for valid JSON
46: end
47: elsif match = scan(/ true | false | null /x)
48: encoder.text_token match, :value
49: elsif match = scan(/ -? (?: 0 | [1-9]\d* ) /x)
50: if scan(/ \.\d+ (?:[eE][-+]?\d+)? | [eE][-+]? \d+ /x)
51: match << matched
52: encoder.text_token match, :float
53: else
54: encoder.text_token match, :integer
55: end
56: else
57: encoder.text_token getch, :error
58: end
59:
60: when :string, :key
61: if match = scan(/[^\\"]+/)
62: encoder.text_token match, :content
63: elsif match = scan(/"/)
64: encoder.text_token match, :delimiter
65: encoder.end_group state
66: state = :initial
67: elsif match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
68: encoder.text_token match, :char
69: elsif match = scan(/\\./m)
70: encoder.text_token match, :content
71: elsif match = scan(/ \\ | $ /x)
72: encoder.end_group state
73: encoder.text_token match, :error
74: state = :initial
75: else
76: raise_inspect "else case \" reached; %p not handled." % peek(1), encoder
77: end
78:
79: else
80: raise_inspect 'Unknown state: %p' % [state], encoder
81:
82: end
83: end
84:
85: if [:string, :key].include? state
86: encoder.end_group state
87: end
88:
89: encoder
90: end