Chris@0
|
1 module CodeRay
|
Chris@0
|
2 module Scanners
|
Chris@0
|
3
|
Chris@0
|
4 # YAML Scanner
|
Chris@0
|
5 #
|
Chris@0
|
6 # Based on the YAML scanner from Syntax by Jamis Buck.
|
Chris@0
|
7 class YAML < Scanner
|
Chris@0
|
8
|
Chris@0
|
9 register_for :yaml
|
Chris@0
|
10 file_extension 'yml'
|
Chris@0
|
11
|
Chris@0
|
12 KINDS_NOT_LOC = :all
|
Chris@0
|
13
|
Chris@0
|
14 def scan_tokens tokens, options
|
Chris@0
|
15
|
Chris@0
|
16 value_expected = nil
|
Chris@0
|
17 state = :initial
|
Chris@0
|
18 key_indent = indent = 0
|
Chris@0
|
19
|
Chris@0
|
20 until eos?
|
Chris@0
|
21
|
Chris@0
|
22 kind = nil
|
Chris@0
|
23 match = nil
|
Chris@0
|
24 key_indent = nil if bol?
|
Chris@0
|
25
|
Chris@0
|
26 if match = scan(/ +[\t ]*/)
|
Chris@0
|
27 kind = :space
|
Chris@0
|
28
|
Chris@0
|
29 elsif match = scan(/\n+/)
|
Chris@0
|
30 kind = :space
|
Chris@0
|
31 state = :initial if match.index(?\n)
|
Chris@0
|
32
|
Chris@0
|
33 elsif match = scan(/#.*/)
|
Chris@0
|
34 kind = :comment
|
Chris@0
|
35
|
Chris@0
|
36 elsif bol? and case
|
Chris@0
|
37 when match = scan(/---|\.\.\./)
|
Chris@0
|
38 tokens << [:open, :head]
|
Chris@0
|
39 tokens << [match, :head]
|
Chris@0
|
40 tokens << [:close, :head]
|
Chris@0
|
41 next
|
Chris@0
|
42 when match = scan(/%.*/)
|
Chris@0
|
43 tokens << [match, :doctype]
|
Chris@0
|
44 next
|
Chris@0
|
45 end
|
Chris@0
|
46
|
Chris@0
|
47 elsif state == :value and case
|
Chris@0
|
48 when !check(/(?:"[^"]*")(?=: |:$)/) && scan(/"/)
|
Chris@0
|
49 tokens << [:open, :string]
|
Chris@0
|
50 tokens << [matched, :delimiter]
|
Chris@0
|
51 tokens << [matched, :content] if scan(/ [^"\\]* (?: \\. [^"\\]* )* /mx)
|
Chris@0
|
52 tokens << [matched, :delimiter] if scan(/"/)
|
Chris@0
|
53 tokens << [:close, :string]
|
Chris@0
|
54 next
|
Chris@0
|
55 when match = scan(/[|>][-+]?/)
|
Chris@0
|
56 tokens << [:open, :string]
|
Chris@0
|
57 tokens << [match, :delimiter]
|
Chris@0
|
58 string_indent = key_indent || column(pos - match.size - 1)
|
Chris@0
|
59 tokens << [matched, :content] if scan(/(?:\n+ {#{string_indent + 1}}.*)+/)
|
Chris@0
|
60 tokens << [:close, :string]
|
Chris@0
|
61 next
|
Chris@0
|
62 when match = scan(/(?![!"*&]).+?(?=$|\s+#)/)
|
Chris@0
|
63 tokens << [match, :string]
|
Chris@0
|
64 string_indent = key_indent || column(pos - match.size - 1)
|
Chris@0
|
65 tokens << [matched, :string] if scan(/(?:\n+ {#{string_indent + 1}}.*)+/)
|
Chris@0
|
66 next
|
Chris@0
|
67 end
|
Chris@0
|
68
|
Chris@0
|
69 elsif case
|
Chris@0
|
70 when match = scan(/[-:](?= |$)/)
|
Chris@0
|
71 state = :value if state == :colon && (match == ':' || match == '-')
|
Chris@0
|
72 state = :value if state == :initial && match == '-'
|
Chris@0
|
73 kind = :operator
|
Chris@0
|
74 when match = scan(/[,{}\[\]]/)
|
Chris@0
|
75 kind = :operator
|
Chris@0
|
76 when state == :initial && match = scan(/[\w.() ]*\S(?=: |:$)/)
|
Chris@0
|
77 kind = :key
|
Chris@0
|
78 key_indent = column(pos - match.size - 1)
|
Chris@0
|
79 # tokens << [key_indent.inspect, :debug]
|
Chris@0
|
80 state = :colon
|
Chris@0
|
81 when match = scan(/(?:"[^"\n]*"|'[^'\n]*')(?=: |:$)/)
|
Chris@0
|
82 tokens << [:open, :key]
|
Chris@0
|
83 tokens << [match[0,1], :delimiter]
|
Chris@0
|
84 tokens << [match[1..-2], :content]
|
Chris@0
|
85 tokens << [match[-1,1], :delimiter]
|
Chris@0
|
86 tokens << [:close, :key]
|
Chris@0
|
87 key_indent = column(pos - match.size - 1)
|
Chris@0
|
88 # tokens << [key_indent.inspect, :debug]
|
Chris@0
|
89 state = :colon
|
Chris@0
|
90 next
|
Chris@0
|
91 when scan(/(![\w\/]+)(:([\w:]+))?/)
|
Chris@0
|
92 tokens << [self[1], :type]
|
Chris@0
|
93 if self[2]
|
Chris@0
|
94 tokens << [':', :operator]
|
Chris@0
|
95 tokens << [self[3], :class]
|
Chris@0
|
96 end
|
Chris@0
|
97 next
|
Chris@0
|
98 when scan(/&\S+/)
|
Chris@0
|
99 kind = :variable
|
Chris@0
|
100 when scan(/\*\w+/)
|
Chris@0
|
101 kind = :global_variable
|
Chris@0
|
102 when scan(/<</)
|
Chris@0
|
103 kind = :class_variable
|
Chris@0
|
104 when scan(/\d\d:\d\d:\d\d/)
|
Chris@0
|
105 kind = :oct
|
Chris@0
|
106 when scan(/\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d(\.\d+)? [-+]\d\d:\d\d/)
|
Chris@0
|
107 kind = :oct
|
Chris@0
|
108 when scan(/:\w+/)
|
Chris@0
|
109 kind = :symbol
|
Chris@0
|
110 when scan(/[^:\s]+(:(?! |$)[^:\s]*)* .*/)
|
Chris@0
|
111 kind = :error
|
Chris@0
|
112 when scan(/[^:\s]+(:(?! |$)[^:\s]*)*/)
|
Chris@0
|
113 kind = :error
|
Chris@0
|
114 end
|
Chris@0
|
115
|
Chris@0
|
116 else
|
Chris@0
|
117 getch
|
Chris@0
|
118 kind = :error
|
Chris@0
|
119
|
Chris@0
|
120 end
|
Chris@0
|
121
|
Chris@0
|
122 match ||= matched
|
Chris@0
|
123
|
Chris@0
|
124 if $CODERAY_DEBUG and not kind
|
Chris@0
|
125 raise_inspect 'Error token %p in line %d' %
|
Chris@0
|
126 [[match, kind], line], tokens, state
|
Chris@0
|
127 end
|
Chris@0
|
128 raise_inspect 'Empty token', tokens, state unless match
|
Chris@0
|
129
|
Chris@0
|
130 tokens << [match, kind]
|
Chris@0
|
131
|
Chris@0
|
132 end
|
Chris@0
|
133
|
Chris@0
|
134 tokens
|
Chris@0
|
135 end
|
Chris@0
|
136
|
Chris@0
|
137 end
|
Chris@0
|
138
|
Chris@0
|
139 end
|
Chris@0
|
140 end
|