@@ -14,15 +14,17 @@ class JSON < Scanner
14
14
15
15
ESCAPE = / [bfnrt\\ "\/ ] /x # :nodoc:
16
16
UNICODE_ESCAPE = / u[a-fA-F0-9]{4} /x # :nodoc:
17
+ KEY = / (?> (?: [^\\ "]+ | \\ . )* ) " \s * : /x
17
18
18
19
protected
19
20
21
+ def setup
22
+ @state = :initial
23
+ end
24
+
20
25
# See http://json.org/ for a definition of the JSON lexic/grammar.
21
26
def scan_tokens encoder , options
22
-
23
- state = :initial
24
- stack = [ ]
25
- key_expected = false
27
+ state = options [ :state ] || @state
26
28
27
29
until eos?
28
30
@@ -32,18 +34,11 @@ def scan_tokens encoder, options
32
34
if match = scan ( / \s + /x )
33
35
encoder . text_token match , :space
34
36
elsif match = scan ( /"/ )
35
- state = key_expected ? :key : :string
37
+ state = check ( / #{ KEY } /o ) ? :key : :string
36
38
encoder . begin_group state
37
39
encoder . text_token match , :delimiter
38
40
elsif match = scan ( / [:,\[ {\] }] /x )
39
41
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
42
elsif match = scan ( / true | false | null /x )
48
43
encoder . text_token match , :value
49
44
elsif match = scan ( / -? (?: 0 | [1-9]\d * ) /x )
@@ -82,6 +77,10 @@ def scan_tokens encoder, options
82
77
end
83
78
end
84
79
80
+ if options [ :keep_state ]
81
+ @state = state
82
+ end
83
+
85
84
if [ :string , :key ] . include? state
86
85
encoder . end_group state
87
86
end
0 commit comments