coderay 1.0.0.598.pre → 1.0.0.738.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/coderay +1 -1
- data/lib/coderay.rb +38 -32
- data/lib/coderay/duo.rb +1 -54
- data/lib/coderay/encoder.rb +31 -33
- data/lib/coderay/encoders/_map.rb +4 -2
- data/lib/coderay/encoders/comment_filter.rb +0 -61
- data/lib/coderay/encoders/count.rb +2 -23
- data/lib/coderay/encoders/debug.rb +11 -60
- data/lib/coderay/encoders/filter.rb +0 -46
- data/lib/coderay/encoders/html.rb +83 -91
- data/lib/coderay/encoders/html/css.rb +1 -6
- data/lib/coderay/encoders/html/numbering.rb +18 -21
- data/lib/coderay/encoders/html/output.rb +10 -52
- data/lib/coderay/encoders/json.rb +19 -39
- data/lib/coderay/encoders/lines_of_code.rb +7 -52
- data/lib/coderay/encoders/null.rb +6 -13
- data/lib/coderay/encoders/statistic.rb +30 -93
- data/lib/coderay/encoders/terminal.rb +3 -4
- data/lib/coderay/encoders/text.rb +1 -23
- data/lib/coderay/encoders/token_kind_filter.rb +0 -58
- data/lib/coderay/helpers/file_type.rb +119 -240
- data/lib/coderay/helpers/gzip.rb +41 -0
- data/lib/coderay/helpers/plugin.rb +237 -307
- data/lib/coderay/scanner.rb +112 -88
- data/lib/coderay/scanners/_map.rb +3 -3
- data/lib/coderay/scanners/c.rb +7 -7
- data/lib/coderay/scanners/clojure.rb +204 -0
- data/lib/coderay/scanners/css.rb +10 -20
- data/lib/coderay/scanners/debug.rb +9 -55
- data/lib/coderay/scanners/diff.rb +21 -4
- data/lib/coderay/scanners/html.rb +65 -18
- data/lib/coderay/scanners/java.rb +3 -2
- data/lib/coderay/scanners/java_script.rb +3 -3
- data/lib/coderay/scanners/json.rb +7 -6
- data/lib/coderay/scanners/php.rb +2 -1
- data/lib/coderay/scanners/rhtml.rb +6 -2
- data/lib/coderay/scanners/ruby.rb +193 -193
- data/lib/coderay/scanners/ruby/patterns.rb +15 -82
- data/lib/coderay/scanners/ruby/string_state.rb +71 -0
- data/lib/coderay/scanners/sql.rb +1 -1
- data/lib/coderay/scanners/yaml.rb +4 -2
- data/lib/coderay/styles/_map.rb +2 -2
- data/lib/coderay/styles/alpha.rb +48 -38
- data/lib/coderay/styles/cycnus.rb +2 -1
- data/lib/coderay/token_kinds.rb +88 -86
- data/lib/coderay/tokens.rb +88 -112
- data/test/functional/basic.rb +184 -5
- data/test/functional/examples.rb +4 -4
- data/test/functional/for_redcloth.rb +3 -2
- data/test/functional/suite.rb +7 -6
- metadata +11 -24
- data/lib/coderay/helpers/gzip_simple.rb +0 -123
- data/test/functional/load_plugin_scanner.rb +0 -11
- data/test/functional/vhdl.rb +0 -126
- data/test/functional/word_list.rb +0 -79
@@ -1,6 +1,6 @@
|
|
1
1
|
module CodeRay
|
2
2
|
module Scanners
|
3
|
-
|
3
|
+
|
4
4
|
# This scanner is really complex, since Ruby _is_ a complex language!
|
5
5
|
#
|
6
6
|
# It tries to highlight 100% of all common code,
|
@@ -16,15 +16,12 @@ module Scanners
|
|
16
16
|
#
|
17
17
|
# Alias: +irb+
|
18
18
|
class Ruby < Scanner
|
19
|
-
|
19
|
+
|
20
20
|
register_for :ruby
|
21
21
|
file_extension 'rb'
|
22
|
-
|
23
|
-
helper :patterns
|
24
22
|
|
25
|
-
|
26
|
-
|
27
|
-
end
|
23
|
+
autoload :Patterns, 'coderay/scanners/ruby/patterns'
|
24
|
+
autoload :StringState, 'coderay/scanners/ruby/string_state'
|
28
25
|
|
29
26
|
protected
|
30
27
|
|
@@ -37,7 +34,7 @@ module Scanners
|
|
37
34
|
patterns = Patterns # avoid constant lookup
|
38
35
|
|
39
36
|
state = @state
|
40
|
-
if state.instance_of?
|
37
|
+
if state.instance_of? self.class::StringState
|
41
38
|
encoder.begin_group state.type
|
42
39
|
end
|
43
40
|
|
@@ -56,131 +53,48 @@ module Scanners
|
|
56
53
|
unicode = string.respond_to?(:encoding) && string.encoding.name == 'UTF-8'
|
57
54
|
|
58
55
|
until eos?
|
59
|
-
|
60
|
-
if state.instance_of?
|
61
|
-
|
62
|
-
match =
|
63
|
-
encoder.text_token match, :content unless match.empty?
|
64
|
-
break if eos?
|
65
|
-
|
66
|
-
if state.heredoc and self[1] # end of heredoc
|
67
|
-
match = getch.to_s
|
68
|
-
match << scan_until(/$/) unless eos?
|
69
|
-
encoder.text_token match, :delimiter
|
70
|
-
encoder.end_group state.type
|
71
|
-
state = state.next_state
|
72
|
-
next
|
73
|
-
end
|
74
|
-
|
75
|
-
case match = getch
|
76
|
-
|
77
|
-
when state.delim
|
78
|
-
if state.paren_depth
|
79
|
-
state.paren_depth -= 1
|
80
|
-
if state.paren_depth > 0
|
81
|
-
encoder.text_token match, :nesting_delimiter
|
82
|
-
next
|
83
|
-
end
|
84
|
-
end
|
85
|
-
encoder.text_token match, :delimiter
|
86
|
-
if state.type == :regexp and not eos?
|
87
|
-
modifiers = scan(/#{patterns::REGEXP_MODIFIERS}/ox)
|
88
|
-
encoder.text_token modifiers, :modifier unless modifiers.empty?
|
89
|
-
end
|
90
|
-
encoder.end_group state.type
|
91
|
-
value_expected = false
|
92
|
-
state = state.next_state
|
93
|
-
|
94
|
-
when '\\'
|
95
|
-
if state.interpreted
|
96
|
-
if esc = scan(/ #{patterns::ESCAPE} /ox)
|
97
|
-
encoder.text_token match + esc, :char
|
98
|
-
else
|
99
|
-
encoder.text_token match, :error
|
100
|
-
end
|
101
|
-
else
|
102
|
-
case m = getch
|
103
|
-
when state.delim, '\\'
|
104
|
-
encoder.text_token match + m, :char
|
105
|
-
when nil
|
106
|
-
encoder.text_token match, :content
|
107
|
-
else
|
108
|
-
encoder.text_token match + m, :content
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
when '#'
|
113
|
-
case peek(1)
|
114
|
-
when '{'
|
115
|
-
inline_block_stack ||= []
|
116
|
-
inline_block_stack << [state, inline_block_curly_depth, heredocs]
|
117
|
-
value_expected = true
|
118
|
-
state = :initial
|
119
|
-
inline_block_curly_depth = 1
|
120
|
-
encoder.begin_group :inline
|
121
|
-
encoder.text_token match + getch, :inline_delimiter
|
122
|
-
when '$', '@'
|
123
|
-
encoder.text_token match, :escape
|
124
|
-
last_state = state
|
125
|
-
state = :initial
|
126
|
-
else
|
127
|
-
raise_inspect 'else-case # reached; #%p not handled' %
|
128
|
-
[peek(1)], encoder
|
129
|
-
end
|
130
|
-
|
131
|
-
when state.opening_paren
|
132
|
-
state.paren_depth += 1
|
133
|
-
encoder.text_token match, :nesting_delimiter
|
134
|
-
|
135
|
-
when /#{patterns::REGEXP_SYMBOLS}/ox
|
136
|
-
encoder.text_token match, :function
|
137
|
-
|
138
|
-
else
|
139
|
-
raise_inspect 'else-case " reached; %p not handled, state = %p' %
|
140
|
-
[match, state], encoder
|
141
|
-
|
142
|
-
end
|
143
|
-
|
144
|
-
else
|
145
|
-
|
146
|
-
if match = scan(/[ \t\f]+/)
|
147
|
-
match << scan(/\s*/) unless eos? || heredocs
|
148
|
-
value_expected = true if match.index(?\n)
|
56
|
+
|
57
|
+
if state.instance_of? ::Symbol
|
58
|
+
|
59
|
+
if match = scan(/[ \t\f\v]+/)
|
149
60
|
encoder.text_token match, :space
|
150
61
|
|
151
|
-
elsif match = scan(
|
152
|
-
if
|
153
|
-
|
62
|
+
elsif match = scan(/\n/)
|
63
|
+
if heredocs
|
64
|
+
unscan # heredoc scanning needs \n at start
|
65
|
+
state = heredocs.shift
|
66
|
+
encoder.begin_group state.type
|
67
|
+
heredocs = nil if heredocs.empty?
|
68
|
+
else
|
154
69
|
state = :initial if state == :undef_comma_expected
|
70
|
+
encoder.text_token match, :space
|
71
|
+
value_expected = true
|
155
72
|
end
|
73
|
+
|
74
|
+
elsif match = scan(bol? ? / \#(!)?.* | #{patterns::RUBYDOC_OR_DATA} /ox : /\#.*/)
|
75
|
+
encoder.text_token match, self[1] ? :doctype : :comment
|
76
|
+
|
77
|
+
elsif match = scan(/\\\n/)
|
156
78
|
if heredocs
|
157
79
|
unscan # heredoc scanning needs \n at start
|
80
|
+
encoder.text_token scan(/\\/), :space
|
158
81
|
state = heredocs.shift
|
159
82
|
encoder.begin_group state.type
|
160
83
|
heredocs = nil if heredocs.empty?
|
161
|
-
next
|
162
84
|
else
|
163
|
-
match
|
85
|
+
encoder.text_token match, :space
|
164
86
|
end
|
165
|
-
encoder.text_token match, :space
|
166
|
-
|
167
|
-
elsif bol? && match = scan(/\#!.*/)
|
168
|
-
encoder.text_token match, :doctype
|
169
87
|
|
170
|
-
elsif match = scan(/\#.*/) or
|
171
|
-
(bol? and match = scan(/#{patterns::RUBYDOC_OR_DATA}/o))
|
172
|
-
encoder.text_token match, :comment
|
173
|
-
|
174
88
|
elsif state == :initial
|
175
|
-
|
89
|
+
|
176
90
|
# IDENTS #
|
177
|
-
if !method_call_expected
|
91
|
+
if !method_call_expected &&
|
178
92
|
match = scan(unicode ? /#{patterns::METHOD_NAME}/uo :
|
179
93
|
/#{patterns::METHOD_NAME}/o)
|
180
94
|
value_expected = false
|
181
95
|
kind = patterns::IDENT_KIND[match]
|
182
96
|
if kind == :ident
|
183
|
-
if match[
|
97
|
+
if match[/\A[A-Z]/] && !(match[/[!?]$/] || match?(/\(/))
|
184
98
|
kind = :constant
|
185
99
|
end
|
186
100
|
elsif kind == :reserved
|
@@ -189,22 +103,22 @@ module Scanners
|
|
189
103
|
end
|
190
104
|
value_expected = true if !value_expected && check(/#{patterns::VALUE_FOLLOWS}/o)
|
191
105
|
encoder.text_token match, kind
|
192
|
-
|
193
|
-
elsif method_call_expected
|
106
|
+
|
107
|
+
elsif method_call_expected &&
|
194
108
|
match = scan(unicode ? /#{patterns::METHOD_AFTER_DOT}/uo :
|
195
109
|
/#{patterns::METHOD_AFTER_DOT}/o)
|
196
|
-
if method_call_expected == '::' && match[
|
110
|
+
if method_call_expected == '::' && match[/\A[A-Z]/] && !match?(/\(/)
|
197
111
|
encoder.text_token match, :constant
|
198
112
|
else
|
199
113
|
encoder.text_token match, :ident
|
200
114
|
end
|
201
115
|
method_call_expected = false
|
202
116
|
value_expected = check(/#{patterns::VALUE_FOLLOWS}/o)
|
203
|
-
|
117
|
+
|
204
118
|
# OPERATORS #
|
205
|
-
elsif
|
206
|
-
value_expected = match !~ / [.\)\]\}] /x || match =~ /\A\.\./
|
119
|
+
elsif !method_call_expected && match = scan(/ (\.(?!\.)|::) | (?: \.\.\.? | ==?=? | [,\(\[\{] )() | [\)\]\}] /x)
|
207
120
|
method_call_expected = self[1]
|
121
|
+
value_expected = !method_call_expected && self[2]
|
208
122
|
if inline_block_stack
|
209
123
|
case match
|
210
124
|
when '{'
|
@@ -222,23 +136,44 @@ module Scanners
|
|
222
136
|
end
|
223
137
|
end
|
224
138
|
encoder.text_token match, :operator
|
225
|
-
|
226
|
-
elsif match = scan(
|
139
|
+
|
140
|
+
elsif match = scan(unicode ? /#{patterns::SYMBOL}/uo :
|
141
|
+
/#{patterns::SYMBOL}/o)
|
142
|
+
case delim = match[1]
|
143
|
+
when ?', ?"
|
144
|
+
encoder.begin_group :symbol
|
145
|
+
encoder.text_token ':', :symbol
|
146
|
+
match = delim.chr
|
147
|
+
encoder.text_token match, :delimiter
|
148
|
+
state = self.class::StringState.new :symbol, delim == ?", match
|
149
|
+
else
|
150
|
+
encoder.text_token match, :symbol
|
151
|
+
value_expected = false
|
152
|
+
end
|
153
|
+
|
154
|
+
elsif match = scan(/ ' (?:(?>[^'\\]*) ')? | " (?:(?>[^"\\\#]*) ")? /mx)
|
227
155
|
encoder.begin_group :string
|
228
|
-
|
229
|
-
|
230
|
-
|
156
|
+
if match.size == 1
|
157
|
+
encoder.text_token match, :delimiter
|
158
|
+
state = self.class::StringState.new :string, match == '"', match # important for streaming
|
159
|
+
else
|
160
|
+
encoder.text_token match[0,1], :delimiter
|
161
|
+
encoder.text_token match[1..-2], :content if match.size > 2
|
162
|
+
encoder.text_token match[-1,1], :delimiter
|
163
|
+
encoder.end_group :string
|
164
|
+
value_expected = false
|
165
|
+
end
|
166
|
+
|
231
167
|
elsif match = scan(unicode ? /#{patterns::INSTANCE_VARIABLE}/uo :
|
232
168
|
/#{patterns::INSTANCE_VARIABLE}/o)
|
233
169
|
value_expected = false
|
234
170
|
encoder.text_token match, :instance_variable
|
235
|
-
|
236
|
-
elsif value_expected
|
171
|
+
|
172
|
+
elsif value_expected && match = scan(/\//)
|
237
173
|
encoder.begin_group :regexp
|
238
174
|
encoder.text_token match, :delimiter
|
239
|
-
|
240
|
-
|
241
|
-
|
175
|
+
state = self.class::StringState.new :regexp, true, '/'
|
176
|
+
|
242
177
|
elsif match = scan(value_expected ? /[-+]?#{patterns::NUMERIC}/o : /#{patterns::NUMERIC}/o)
|
243
178
|
if method_call_expected
|
244
179
|
encoder.text_token match, :error
|
@@ -247,86 +182,63 @@ module Scanners
|
|
247
182
|
encoder.text_token match, self[1] ? :float : :integer
|
248
183
|
end
|
249
184
|
value_expected = false
|
250
|
-
|
251
|
-
elsif match = scan(
|
252
|
-
/#{patterns::SYMBOL}/o)
|
253
|
-
case delim = match[1]
|
254
|
-
when ?', ?"
|
255
|
-
encoder.begin_group :symbol
|
256
|
-
encoder.text_token ':', :symbol
|
257
|
-
match = delim.chr
|
258
|
-
encoder.text_token match, :delimiter
|
259
|
-
state = patterns::StringState.new :symbol, delim == ?", match
|
260
|
-
else
|
261
|
-
encoder.text_token match, :symbol
|
262
|
-
value_expected = false
|
263
|
-
end
|
264
|
-
|
265
|
-
elsif match = scan(/ [-+!~^]=? | [*|&]{1,2}=? | >>? /x)
|
185
|
+
|
186
|
+
elsif match = scan(/ [-+!~^\/]=? | [:;] | [*|&]{1,2}=? | >>? /x)
|
266
187
|
value_expected = true
|
267
188
|
encoder.text_token match, :operator
|
268
|
-
|
269
|
-
elsif value_expected
|
270
|
-
indented = self[1] == '-'
|
189
|
+
|
190
|
+
elsif value_expected && match = scan(/#{patterns::HEREDOC_OPEN}/o)
|
271
191
|
quote = self[3]
|
272
192
|
delim = self[quote ? 4 : 2]
|
273
193
|
kind = patterns::QUOTE_TO_TYPE[quote]
|
274
194
|
encoder.begin_group kind
|
275
195
|
encoder.text_token match, :delimiter
|
276
196
|
encoder.end_group kind
|
277
|
-
heredoc = patterns::StringState.new kind, quote != '\'',
|
278
|
-
delim, (indented ? :indented : :linestart )
|
279
197
|
heredocs ||= [] # create heredocs if empty
|
280
|
-
heredocs <<
|
198
|
+
heredocs << self.class::StringState.new(kind, quote != "'", delim,
|
199
|
+
self[1] == '-' ? :indented : :linestart)
|
281
200
|
value_expected = false
|
282
|
-
|
283
|
-
elsif value_expected
|
284
|
-
kind
|
285
|
-
raise_inspect 'Unknown fancy string: %%%p' % k, encoder
|
286
|
-
end
|
201
|
+
|
202
|
+
elsif value_expected && match = scan(/#{patterns::FANCY_STRING_START}/o)
|
203
|
+
kind = patterns::FANCY_STRING_KIND[self[1]]
|
287
204
|
encoder.begin_group kind
|
288
|
-
state =
|
205
|
+
state = self.class::StringState.new kind, patterns::FANCY_STRING_INTERPRETED[self[1]], self[2]
|
289
206
|
encoder.text_token match, :delimiter
|
290
|
-
|
291
|
-
elsif value_expected
|
207
|
+
|
208
|
+
elsif value_expected && match = scan(/#{patterns::CHARACTER}/o)
|
292
209
|
value_expected = false
|
293
210
|
encoder.text_token match, :integer
|
294
|
-
|
295
|
-
elsif match = scan(/
|
211
|
+
|
212
|
+
elsif match = scan(/ %=? | <(?:<|=>?)? | \? /x)
|
296
213
|
value_expected = true
|
297
214
|
encoder.text_token match, :operator
|
298
|
-
|
215
|
+
|
299
216
|
elsif match = scan(/`/)
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
encoder.begin_group :shell
|
305
|
-
encoder.text_token match, :delimiter
|
306
|
-
state = patterns::StringState.new :shell, true, match
|
307
|
-
end
|
308
|
-
|
217
|
+
encoder.begin_group :shell
|
218
|
+
encoder.text_token match, :delimiter
|
219
|
+
state = self.class::StringState.new :shell, true, match
|
220
|
+
|
309
221
|
elsif match = scan(unicode ? /#{patterns::GLOBAL_VARIABLE}/uo :
|
310
222
|
/#{patterns::GLOBAL_VARIABLE}/o)
|
311
223
|
encoder.text_token match, :global_variable
|
312
224
|
value_expected = false
|
313
|
-
|
225
|
+
|
314
226
|
elsif match = scan(unicode ? /#{patterns::CLASS_VARIABLE}/uo :
|
315
227
|
/#{patterns::CLASS_VARIABLE}/o)
|
316
228
|
encoder.text_token match, :class_variable
|
317
229
|
value_expected = false
|
318
|
-
|
230
|
+
|
319
231
|
elsif match = scan(/\\\z/)
|
320
232
|
encoder.text_token match, :space
|
321
|
-
|
233
|
+
|
322
234
|
else
|
323
235
|
if method_call_expected
|
324
236
|
method_call_expected = false
|
325
237
|
next
|
326
238
|
end
|
327
|
-
|
239
|
+
unless unicode
|
328
240
|
# check for unicode
|
329
|
-
|
241
|
+
$DEBUG_BEFORE, $DEBUG = $DEBUG, false
|
330
242
|
begin
|
331
243
|
if check(/./mu).size > 1
|
332
244
|
# seems like we should try again with unicode
|
@@ -335,7 +247,7 @@ module Scanners
|
|
335
247
|
rescue
|
336
248
|
# bad unicode char; use getch
|
337
249
|
ensure
|
338
|
-
$DEBUG =
|
250
|
+
$DEBUG = $DEBUG_BEFORE
|
339
251
|
end
|
340
252
|
next if unicode
|
341
253
|
end
|
@@ -348,7 +260,7 @@ module Scanners
|
|
348
260
|
state = last_state
|
349
261
|
last_state = nil
|
350
262
|
end
|
351
|
-
|
263
|
+
|
352
264
|
elsif state == :def_expected
|
353
265
|
if match = scan(unicode ? /(?>#{patterns::METHOD_NAME_EX})(?!\.|::)/uo :
|
354
266
|
/(?>#{patterns::METHOD_NAME_EX})(?!\.|::)/o)
|
@@ -358,7 +270,7 @@ module Scanners
|
|
358
270
|
last_state = :dot_expected
|
359
271
|
state = :initial
|
360
272
|
end
|
361
|
-
|
273
|
+
|
362
274
|
elsif state == :dot_expected
|
363
275
|
if match = scan(/\.|::/)
|
364
276
|
# invalid definition
|
@@ -367,7 +279,7 @@ module Scanners
|
|
367
279
|
else
|
368
280
|
state = :initial
|
369
281
|
end
|
370
|
-
|
282
|
+
|
371
283
|
elsif state == :module_expected
|
372
284
|
if match = scan(/<</)
|
373
285
|
encoder.text_token match, :operator
|
@@ -378,7 +290,7 @@ module Scanners
|
|
378
290
|
encoder.text_token match, :class
|
379
291
|
end
|
380
292
|
end
|
381
|
-
|
293
|
+
|
382
294
|
elsif state == :undef_expected
|
383
295
|
state = :undef_comma_expected
|
384
296
|
if match = scan(unicode ? /(?>#{patterns::METHOD_NAME_EX})(?!\.|::)/uo :
|
@@ -391,7 +303,7 @@ module Scanners
|
|
391
303
|
encoder.text_token ':', :symbol
|
392
304
|
match = delim.chr
|
393
305
|
encoder.text_token match, :delimiter
|
394
|
-
state =
|
306
|
+
state = self.class::StringState.new :symbol, delim == ?", match
|
395
307
|
state.next_state = :undef_comma_expected
|
396
308
|
else
|
397
309
|
encoder.text_token match, :symbol
|
@@ -399,7 +311,7 @@ module Scanners
|
|
399
311
|
else
|
400
312
|
state = :initial
|
401
313
|
end
|
402
|
-
|
314
|
+
|
403
315
|
elsif state == :undef_comma_expected
|
404
316
|
if match = scan(/,/)
|
405
317
|
encoder.text_token match, :operator
|
@@ -407,7 +319,7 @@ module Scanners
|
|
407
319
|
else
|
408
320
|
state = :initial
|
409
321
|
end
|
410
|
-
|
322
|
+
|
411
323
|
elsif state == :alias_expected
|
412
324
|
match = scan(unicode ? /(#{patterns::METHOD_NAME_OR_SYMBOL})([ \t]+)(#{patterns::METHOD_NAME_OR_SYMBOL})/uo :
|
413
325
|
/(#{patterns::METHOD_NAME_OR_SYMBOL})([ \t]+)(#{patterns::METHOD_NAME_OR_SYMBOL})/o)
|
@@ -418,33 +330,121 @@ module Scanners
|
|
418
330
|
encoder.text_token self[3], (self[3][0] == ?: ? :symbol : :method)
|
419
331
|
end
|
420
332
|
state = :initial
|
421
|
-
|
333
|
+
|
422
334
|
else
|
335
|
+
#:nocov:
|
423
336
|
raise_inspect 'Unknown state: %p' % [state], encoder
|
337
|
+
#:nocov:
|
338
|
+
end
|
339
|
+
|
340
|
+
else # StringState
|
341
|
+
|
342
|
+
match = scan_until(state.pattern) || scan_until(/\z/)
|
343
|
+
unless match.empty?
|
344
|
+
encoder.text_token match, :content
|
345
|
+
break if eos?
|
346
|
+
end
|
347
|
+
|
348
|
+
if state.heredoc && self[1] # end of heredoc
|
349
|
+
match = getch
|
350
|
+
match << scan_until(/$/) unless eos?
|
351
|
+
encoder.text_token match, :delimiter unless match.empty?
|
352
|
+
encoder.end_group state.type
|
353
|
+
state = state.next_state
|
354
|
+
next
|
355
|
+
end
|
356
|
+
|
357
|
+
case match = getch
|
358
|
+
|
359
|
+
when state.delim
|
360
|
+
if state.paren_depth
|
361
|
+
state.paren_depth -= 1
|
362
|
+
if state.paren_depth > 0
|
363
|
+
encoder.text_token match, :content
|
364
|
+
next
|
365
|
+
end
|
366
|
+
end
|
367
|
+
encoder.text_token match, :delimiter
|
368
|
+
if state.type == :regexp && !eos?
|
369
|
+
match = scan(/#{patterns::REGEXP_MODIFIERS}/o)
|
370
|
+
encoder.text_token match, :modifier unless match.empty?
|
371
|
+
end
|
372
|
+
encoder.end_group state.type
|
373
|
+
value_expected = false
|
374
|
+
state = state.next_state
|
375
|
+
|
376
|
+
when '\\'
|
377
|
+
if state.interpreted
|
378
|
+
if esc = scan(/#{patterns::ESCAPE}/o)
|
379
|
+
encoder.text_token match + esc, :char
|
380
|
+
else
|
381
|
+
encoder.text_token match, :error
|
382
|
+
end
|
383
|
+
else
|
384
|
+
case esc = getch
|
385
|
+
when state.delim, '\\'
|
386
|
+
encoder.text_token match + esc, :char
|
387
|
+
when nil
|
388
|
+
encoder.text_token match, :content
|
389
|
+
else
|
390
|
+
encoder.text_token match + esc, :content
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
when '#'
|
395
|
+
case peek(1)
|
396
|
+
when '{'
|
397
|
+
inline_block_stack ||= []
|
398
|
+
inline_block_stack << [state, inline_block_curly_depth, heredocs]
|
399
|
+
value_expected = true
|
400
|
+
state = :initial
|
401
|
+
inline_block_curly_depth = 1
|
402
|
+
encoder.begin_group :inline
|
403
|
+
encoder.text_token match + getch, :inline_delimiter
|
404
|
+
when '$', '@'
|
405
|
+
encoder.text_token match, :escape
|
406
|
+
last_state = state
|
407
|
+
state = :initial
|
408
|
+
else
|
409
|
+
#:nocov:
|
410
|
+
raise_inspect 'else-case # reached; #%p not handled' % [peek(1)], encoder
|
411
|
+
#:nocov:
|
412
|
+
end
|
413
|
+
|
414
|
+
when state.opening_paren
|
415
|
+
state.paren_depth += 1
|
416
|
+
encoder.text_token match, :content
|
417
|
+
|
418
|
+
else
|
419
|
+
#:nocov
|
420
|
+
raise_inspect 'else-case " reached; %p not handled, state = %p' % [match, state], encoder
|
421
|
+
#:nocov:
|
422
|
+
|
424
423
|
end
|
425
424
|
|
426
425
|
end
|
426
|
+
|
427
427
|
end
|
428
|
-
|
428
|
+
|
429
429
|
# cleaning up
|
430
430
|
if options[:keep_state]
|
431
431
|
@state = state
|
432
432
|
end
|
433
|
-
if state.is_a?
|
433
|
+
if state.is_a? self.class::StringState
|
434
434
|
encoder.end_group state.type
|
435
435
|
end
|
436
436
|
if inline_block_stack
|
437
437
|
until inline_block_stack.empty?
|
438
|
-
state,
|
439
|
-
encoder.end_group :inline
|
438
|
+
state, = *inline_block_stack.pop
|
439
|
+
encoder.end_group :inline
|
440
440
|
encoder.end_group state.type
|
441
441
|
end
|
442
442
|
end
|
443
|
-
|
443
|
+
|
444
444
|
encoder
|
445
445
|
end
|
446
|
-
|
446
|
+
|
447
447
|
end
|
448
|
-
|
448
|
+
|
449
449
|
end
|
450
450
|
end
|