coderay 1.0.0.598.pre → 1.0.0.738.pre
Sign up to get free protection for your applications and to get access to all the features.
- 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
|