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