Mercurial > hg > soundsoftware-site
comparison vendor/plugins/coderay-0.9.2/lib/coderay/scanners/json.rb @ 0:513646585e45
* Import Redmine trunk SVN rev 3859
author | Chris Cannam |
---|---|
date | Fri, 23 Jul 2010 15:52:44 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:513646585e45 |
---|---|
1 module CodeRay | |
2 module Scanners | |
3 | |
4 class JSON < Scanner | |
5 | |
6 include Streamable | |
7 | |
8 register_for :json | |
9 file_extension 'json' | |
10 | |
11 KINDS_NOT_LOC = [ | |
12 :float, :char, :content, :delimiter, | |
13 :error, :integer, :operator, :value, | |
14 ] | |
15 | |
16 CONSTANTS = %w( true false null ) | |
17 IDENT_KIND = WordList.new(:key).add(CONSTANTS, :value) | |
18 | |
19 ESCAPE = / [bfnrt\\"\/] /x | |
20 UNICODE_ESCAPE = / u[a-fA-F0-9]{4} /x | |
21 | |
22 def scan_tokens tokens, options | |
23 | |
24 state = :initial | |
25 stack = [] | |
26 string_delimiter = nil | |
27 key_expected = false | |
28 | |
29 until eos? | |
30 | |
31 kind = nil | |
32 match = nil | |
33 | |
34 case state | |
35 | |
36 when :initial | |
37 if match = scan(/ \s+ | \\\n /x) | |
38 tokens << [match, :space] | |
39 next | |
40 elsif match = scan(/ [:,\[{\]}] /x) | |
41 kind = :operator | |
42 case match | |
43 when '{' then stack << :object; key_expected = true | |
44 when '[' then stack << :array | |
45 when ':' then key_expected = false | |
46 when ',' then key_expected = true if stack.last == :object | |
47 when '}', ']' then stack.pop # no error recovery, but works for valid JSON | |
48 end | |
49 elsif match = scan(/ true | false | null /x) | |
50 kind = IDENT_KIND[match] | |
51 elsif match = scan(/-?(?:0|[1-9]\d*)/) | |
52 kind = :integer | |
53 if scan(/\.\d+(?:[eE][-+]?\d+)?|[eE][-+]?\d+/) | |
54 match << matched | |
55 kind = :float | |
56 end | |
57 elsif match = scan(/"/) | |
58 state = key_expected ? :key : :string | |
59 tokens << [:open, state] | |
60 kind = :delimiter | |
61 else | |
62 getch | |
63 kind = :error | |
64 end | |
65 | |
66 when :string, :key | |
67 if scan(/[^\\"]+/) | |
68 kind = :content | |
69 elsif scan(/"/) | |
70 tokens << ['"', :delimiter] | |
71 tokens << [:close, state] | |
72 state = :initial | |
73 next | |
74 elsif scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox) | |
75 kind = :char | |
76 elsif scan(/\\./m) | |
77 kind = :content | |
78 elsif scan(/ \\ | $ /x) | |
79 tokens << [:close, :delimiter] | |
80 kind = :error | |
81 state = :initial | |
82 else | |
83 raise_inspect "else case \" reached; %p not handled." % peek(1), tokens | |
84 end | |
85 | |
86 else | |
87 raise_inspect 'Unknown state', tokens | |
88 | |
89 end | |
90 | |
91 match ||= matched | |
92 if $CODERAY_DEBUG and not kind | |
93 raise_inspect 'Error token %p in line %d' % | |
94 [[match, kind], line], tokens | |
95 end | |
96 raise_inspect 'Empty token', tokens unless match | |
97 | |
98 tokens << [match, kind] | |
99 | |
100 end | |
101 | |
102 if [:string, :key].include? state | |
103 tokens << [:close, state] | |
104 end | |
105 | |
106 tokens | |
107 end | |
108 | |
109 end | |
110 | |
111 end | |
112 end |