coderay 1.0.0.738.pre → 1.0.0.778.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.
Files changed (42) hide show
  1. data/{lib/README → README.rdoc} +0 -0
  2. data/Rakefile +5 -5
  3. data/lib/coderay.rb +2 -2
  4. data/lib/coderay/encoder.rb +4 -4
  5. data/lib/coderay/encoders/_map.rb +3 -1
  6. data/lib/coderay/encoders/html.rb +9 -17
  7. data/lib/coderay/encoders/html/numbering.rb +5 -5
  8. data/lib/coderay/encoders/html/output.rb +3 -3
  9. data/lib/coderay/encoders/lines_of_code.rb +6 -9
  10. data/lib/coderay/encoders/statistic.rb +26 -25
  11. data/lib/coderay/encoders/terminal.rb +2 -2
  12. data/lib/coderay/encoders/text.rb +9 -9
  13. data/lib/coderay/encoders/xml.rb +8 -8
  14. data/lib/coderay/encoders/yaml.rb +5 -6
  15. data/lib/coderay/for_redcloth.rb +1 -1
  16. data/lib/coderay/helpers/file_type.rb +44 -42
  17. data/lib/coderay/helpers/plugin.rb +9 -17
  18. data/lib/coderay/helpers/word_list.rb +65 -126
  19. data/lib/coderay/scanner.rb +13 -5
  20. data/lib/coderay/scanners/_map.rb +3 -2
  21. data/lib/coderay/scanners/c.rb +5 -5
  22. data/lib/coderay/scanners/clojure.rb +27 -14
  23. data/lib/coderay/scanners/cpp.rb +5 -5
  24. data/lib/coderay/scanners/css.rb +1 -1
  25. data/lib/coderay/scanners/html.rb +60 -29
  26. data/lib/coderay/scanners/java.rb +2 -2
  27. data/lib/coderay/scanners/java_script.rb +1 -1
  28. data/lib/coderay/scanners/nitro_xhtml.rb +1 -1
  29. data/lib/coderay/scanners/php.rb +4 -4
  30. data/lib/coderay/scanners/python.rb +2 -2
  31. data/lib/coderay/scanners/rhtml.rb +1 -1
  32. data/lib/coderay/scanners/ruby.rb +4 -11
  33. data/lib/coderay/scanners/ruby/patterns.rb +1 -1
  34. data/lib/coderay/scanners/scheme.rb +2 -2
  35. data/lib/coderay/scanners/sql.rb +26 -19
  36. data/lib/coderay/scanners/text.rb +26 -0
  37. data/lib/coderay/styles/alpha.rb +7 -6
  38. data/lib/coderay/token_kinds.rb +5 -5
  39. data/test/functional/basic.rb +1 -1
  40. data/test/functional/examples.rb +5 -3
  41. metadata +85 -85
  42. data/lib/coderay/scanners/plaintext.rb +0 -26
@@ -12,11 +12,12 @@ module Scanners
12
12
  :nitro => :nitro_xhtml,
13
13
  :pascal => :delphi,
14
14
  :patch => :diff,
15
- :plain => :plaintext,
15
+ :plain => :text,
16
+ :plaintext => :text,
16
17
  :xhtml => :html,
17
18
  :yml => :yaml
18
19
 
19
- default :plain
20
+ default :text
20
21
 
21
22
  end
22
23
  end
@@ -7,7 +7,7 @@ module Scanners
7
7
  register_for :c
8
8
  file_extension 'c'
9
9
 
10
- RESERVED_WORDS = [
10
+ KEYWORDS = [
11
11
  'asm', 'break', 'case', 'continue', 'default', 'do',
12
12
  'else', 'enum', 'for', 'goto', 'if', 'return',
13
13
  'sizeof', 'struct', 'switch', 'typedef', 'union', 'while',
@@ -31,10 +31,10 @@ module Scanners
31
31
  ] # :nodoc:
32
32
 
33
33
  IDENT_KIND = WordList.new(:ident).
34
- add(RESERVED_WORDS, :reserved).
35
- add(PREDEFINED_TYPES, :pre_type).
34
+ add(KEYWORDS, :keyword).
35
+ add(PREDEFINED_TYPES, :predefined_type).
36
36
  add(DIRECTIVES, :directive).
37
- add(PREDEFINED_CONSTANTS, :pre_constant) # :nodoc:
37
+ add(PREDEFINED_CONSTANTS, :predefined_constant) # :nodoc:
38
38
 
39
39
  ESCAPE = / [rbfntv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
40
40
  UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
@@ -80,7 +80,7 @@ module Scanners
80
80
  match << matched
81
81
  else
82
82
  label_expected = false
83
- if kind == :reserved
83
+ if kind == :keyword
84
84
  case match
85
85
  when 'case', 'default'
86
86
  case_expected = true
@@ -14,7 +14,7 @@ module CodeRay
14
14
  ] # :nodoc:
15
15
 
16
16
  CORE_FORMS = %w[
17
- + - -> ->> .. / * < <= = == > >= accessor aclone add-classpath add-watch
17
+ + - -> ->> .. / * <= < = == >= > accessor aclone add-classpath add-watch
18
18
  agent agent-error agent-errors aget alength alias all-ns alter alter-meta!
19
19
  alter-var-root amap ancestors and apply areduce array-map aset aset-boolean
20
20
  aset-byte aset-char aset-double aset-float aset-int aset-long aset-short
@@ -74,20 +74,26 @@ module CodeRay
74
74
  with-in-str with-local-vars with-meta with-open with-out-str
75
75
  with-precision xml-seq zero? zipmap
76
76
  ] # :nodoc:
77
+
77
78
  PREDEFINED_CONSTANTS = %w[
78
- true false *1 *2 *3 *agent* *clojure-version* *command-line-args*
79
+ true false nil *1 *2 *3 *agent* *clojure-version* *command-line-args*
79
80
  *compile-files* *compile-path* *e *err* *file* *flush-on-newline*
80
81
  *in* *ns* *out* *print-dup* *print-length* *print-level* *print-meta*
81
82
  *print-readably* *read-eval* *warn-on-reflection*
82
83
  ] # :nodoc:
83
84
 
84
- IDENT_KIND = CaseIgnoringWordList.new(:ident).
85
+ IDENT_KIND = WordList.new(:ident).
85
86
  add(SPECIAL_FORMS, :reserved).
86
87
  add(CORE_FORMS, :reserved).
87
- add(PREDEFINED_CONSTANTS, :pre_constant)
88
+ add(PREDEFINED_CONSTANTS, :predefined_constant)
89
+
90
+ KEYWORD_NEXT_TOKEN_KIND = WordList.new(nil).
91
+ add(%w[ def defn defn- definline defmacro defmulti defmethod defstruct defonce declare ], :function).
92
+ add(%w[ ns ], :namespace).
93
+ add(%w[ defprotocol defrecord ], :class)
88
94
 
89
- BASIC_IDENTIFIER = /[a-zA-Z$%*\/_+!?&<>\-=][a-zA-Z0-9$&*+!\/_?<>\-\#]*/
90
- IDENTIFIER = /(?:[@']?(?:#{BASIC_IDENTIFIER}\.)*#{BASIC_IDENTIFIER}(?:\/#{BASIC_IDENTIFIER})?\.?)|\.\.?/
95
+ BASIC_IDENTIFIER = /[a-zA-Z$%*\/_+!?&<>\-=]=?[a-zA-Z0-9$&*+!\/_?<>\-\#]*/
96
+ IDENTIFIER = /(?!-\d)(?:(?:#{BASIC_IDENTIFIER}\.)*#{BASIC_IDENTIFIER}(?:\/#{BASIC_IDENTIFIER})?\.?)|\.\.?/
91
97
  SYMBOL = /::?#{IDENTIFIER}/o
92
98
  DIGIT = /\d/
93
99
  DIGIT10 = DIGIT
@@ -139,7 +145,7 @@ module CodeRay
139
145
  def scan_tokens encoder, options
140
146
 
141
147
  state = :initial
142
- ident_kind = IDENT_KIND
148
+ kind = nil
143
149
 
144
150
  until eos?
145
151
 
@@ -147,16 +153,23 @@ module CodeRay
147
153
  when :initial
148
154
  if match = scan(/ \s+ | \\\n | , /x)
149
155
  encoder.text_token match, :space
150
- elsif match = scan(/['`\(\[\)\]\{\}]|\#[({]|~@?|@/)
151
- encoder.text_token match, :operator # FIXME: was :operator_fat
156
+ elsif match = scan(/['`\(\[\)\]\{\}]|\#[({]|~@?|[@\^]/)
157
+ encoder.text_token match, :operator
152
158
  elsif match = scan(/;.*/)
153
- encoder.text_token match, :comment
154
- elsif match = scan(/\#\\(?:newline|space|.?)/)
159
+ encoder.text_token match, :comment # FIXME: recognize (comment ...) too
160
+ elsif match = scan(/\#?\\(?:newline|space|.?)/)
155
161
  encoder.text_token match, :char
156
162
  elsif match = scan(/\#[ft]/)
157
- encoder.text_token match, :pre_constant
163
+ encoder.text_token match, :predefined_constant
158
164
  elsif match = scan(/#{IDENTIFIER}/o)
159
- encoder.text_token match, ident_kind[matched]
165
+ kind = IDENT_KIND[match]
166
+ encoder.text_token match, kind
167
+ if rest? && kind == :reserved
168
+ if kind = KEYWORD_NEXT_TOKEN_KIND[match]
169
+ encoder.text_token match, :space if match = scan(/\s+/o)
170
+ encoder.text_token match, kind if match = scan(/#{IDENTIFIER}/o)
171
+ end
172
+ end
160
173
  elsif match = scan(/#{SYMBOL}/o)
161
174
  encoder.text_token match, :symbol
162
175
  elsif match = scan(/\./)
@@ -168,7 +181,7 @@ module CodeRay
168
181
  encoder.begin_group state
169
182
  encoder.text_token match, :delimiter
170
183
  elsif match = scan(/#{NUM}/o) and not matched.empty?
171
- encoder.text_token match, match[/[.e]/i] ? :float : :integer
184
+ encoder.text_token match, match[/[.e\/]/i] ? :float : :integer
172
185
  else
173
186
  encoder.text_token getch, :error
174
187
  end
@@ -11,7 +11,7 @@ module Scanners
11
11
  title 'C++'
12
12
 
13
13
  #-- http://www.cppreference.com/wiki/keywords/start
14
- RESERVED_WORDS = [
14
+ KEYWORDS = [
15
15
  'and', 'and_eq', 'asm', 'bitand', 'bitor', 'break',
16
16
  'case', 'catch', 'class', 'compl', 'const_cast',
17
17
  'continue', 'default', 'delete', 'do', 'dynamic_cast', 'else',
@@ -40,11 +40,11 @@ module Scanners
40
40
  ] # :nodoc:
41
41
 
42
42
  IDENT_KIND = WordList.new(:ident).
43
- add(RESERVED_WORDS, :reserved).
44
- add(PREDEFINED_TYPES, :pre_type).
43
+ add(KEYWORDS, :keyword).
44
+ add(PREDEFINED_TYPES, :predefined_type).
45
45
  add(PREDEFINED_VARIABLES, :local_variable).
46
46
  add(DIRECTIVES, :directive).
47
- add(PREDEFINED_CONSTANTS, :pre_constant) # :nodoc:
47
+ add(PREDEFINED_CONSTANTS, :predefined_constant) # :nodoc:
48
48
 
49
49
  ESCAPE = / [rbfntv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
50
50
  UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
@@ -94,7 +94,7 @@ module Scanners
94
94
  match << matched
95
95
  else
96
96
  label_expected = false
97
- if kind == :reserved
97
+ if kind == :keyword
98
98
  case match
99
99
  when 'class'
100
100
  state = :class_name_expected
@@ -9,7 +9,7 @@ module Scanners
9
9
  :comment,
10
10
  :class, :pseudo_class, :type,
11
11
  :constant, :directive,
12
- :key, :value, :operator, :color, :float,
12
+ :key, :value, :operator, :color, :float, :string,
13
13
  :error, :important,
14
14
  ] # :nodoc:
15
15
 
@@ -13,10 +13,28 @@ module Scanners
13
13
  KINDS_NOT_LOC = [
14
14
  :comment, :doctype, :preprocessor,
15
15
  :tag, :attribute_name, :operator,
16
- :attribute_value, :delimiter, :content,
16
+ :attribute_value, :string,
17
17
  :plain, :entity, :error,
18
18
  ] # :nodoc:
19
19
 
20
+ EVENT_ATTRIBUTES = %w(
21
+ onabort onafterprint onbeforeprint onbeforeunload onblur oncanplay
22
+ oncanplaythrough onchange onclick oncontextmenu oncuechange ondblclick
23
+ ondrag ondragdrop ondragend ondragenter ondragleave ondragover
24
+ ondragstart ondrop ondurationchange onemptied onended onerror onfocus
25
+ onformchange onforminput onhashchange oninput oninvalid onkeydown
26
+ onkeypress onkeyup onload onloadeddata onloadedmetadata onloadstart
27
+ onmessage onmousedown onmousemove onmouseout onmouseover onmouseup
28
+ onmousewheel onmove onoffline ononline onpagehide onpageshow onpause
29
+ onplay onplaying onpopstate onprogress onratechange onreadystatechange
30
+ onredo onreset onresize onscroll onseeked onseeking onselect onshow
31
+ onstalled onstorage onsubmit onsuspend ontimeupdate onundo onunload
32
+ onvolumechange onwaiting
33
+ )
34
+
35
+ IN_ATTRIBUTE = CaseIgnoringWordList.new(nil).
36
+ add(EVENT_ATTRIBUTES, :script)
37
+
20
38
  ATTR_NAME = /[\w.:-]+/ # :nodoc:
21
39
  TAG_END = /\/?>/ # :nodoc:
22
40
  HEX = /[0-9a-fA-F]/ # :nodoc:
@@ -70,7 +88,7 @@ module Scanners
70
88
 
71
89
  until eos?
72
90
 
73
- if match = scan(/\s+/m)
91
+ if state != :in_special_tag && match = scan(/\s+/m)
74
92
  encoder.text_token match, :space
75
93
 
76
94
  else
@@ -78,24 +96,6 @@ module Scanners
78
96
  case state
79
97
 
80
98
  when :initial
81
- case in_tag
82
- when 'script'
83
- if scan(/(\s*<!--)(?:(.*?)(-->)|(.*))/m)
84
- code = self[2] || self[4]
85
- closing = self[3]
86
- encoder.text_token self[1], :comment
87
- else
88
- code = scan_until(/(?=(?:\n\s*)?<\/script>)|\z/)
89
- closing = false
90
- end
91
- unless code.empty?
92
- encoder.begin_group :inline
93
- scan_java_script encoder, code
94
- encoder.end_group :inline
95
- end
96
- encoder.text_token closing, :comment if closing
97
- end
98
- next if eos?
99
99
  if match = scan(/<!--(?:.*?-->|.*)/m)
100
100
  encoder.text_token match, :comment
101
101
  elsif match = scan(/<!DOCTYPE(?:.*?>|.*)/m)
@@ -105,17 +105,22 @@ module Scanners
105
105
  elsif match = scan(/<\?(?:.*?\?>|.*)|<%(?:.*?%>|.*)/m)
106
106
  encoder.text_token match, :comment
107
107
  elsif match = scan(/<\/[-\w.:]*>?/m)
108
- encoder.text_token match, :tag
109
108
  in_tag = nil
109
+ encoder.text_token match, :tag
110
110
  elsif match = scan(/<(?:(script)|[-\w.:]+)(>)?/m)
111
111
  encoder.text_token match, :tag
112
112
  in_tag = self[1]
113
- state = :attribute unless self[2]
113
+ if self[2]
114
+ state = :in_special_tag if in_tag
115
+ else
116
+ state = :attribute
117
+ end
114
118
  elsif match = scan(/[^<>&]+/)
115
119
  encoder.text_token match, :plain
116
120
  elsif match = scan(/#{ENTITY}/ox)
117
121
  encoder.text_token match, :entity
118
122
  elsif match = scan(/[<>&]/)
123
+ in_tag = nil
119
124
  encoder.text_token match, :error
120
125
  else
121
126
  raise_inspect '[BUG] else-case reached with state %p' % [state], encoder
@@ -125,19 +130,22 @@ module Scanners
125
130
  if match = scan(/#{TAG_END}/o)
126
131
  encoder.text_token match, :tag
127
132
  in_attribute = nil
128
- state = :initial
129
- elsif match = scan(/#{ATTR_NAME}/o)
130
- if match.downcase == 'onclick'
131
- in_attribute = 'script'
133
+ if in_tag
134
+ state = :in_special_tag
135
+ else
136
+ state = :initial
132
137
  end
138
+ elsif match = scan(/#{ATTR_NAME}/o)
139
+ in_attribute = IN_ATTRIBUTE[match]
133
140
  encoder.text_token match, :attribute_name
134
141
  state = :attribute_equal
135
142
  else
143
+ in_tag = nil
136
144
  encoder.text_token getch, :error
137
145
  end
138
146
 
139
147
  when :attribute_equal
140
- if match = scan(/=/)
148
+ if match = scan(/=/) #/
141
149
  encoder.text_token match, :operator
142
150
  state = :attribute_value
143
151
  elsif scan(/#{ATTR_NAME}/o) || scan(/#{TAG_END}/o)
@@ -153,10 +161,10 @@ module Scanners
153
161
  encoder.text_token match, :attribute_value
154
162
  state = :attribute
155
163
  elsif match = scan(/["']/)
156
- if in_attribute == 'script'
164
+ if in_attribute == :script
157
165
  encoder.begin_group :inline
158
166
  encoder.text_token match, :inline_delimiter
159
- if scan(/javascript:\s*/)
167
+ if scan(/javascript:[ \t]*/)
160
168
  encoder.text_token matched, :comment
161
169
  end
162
170
  code = scan_until(match == '"' ? /(?="|\z)/ : /(?='|\z)/)
@@ -196,6 +204,29 @@ module Scanners
196
204
  encoder.text_token match, :error
197
205
  end
198
206
 
207
+ when :in_special_tag
208
+ case in_tag
209
+ when 'script'
210
+ encoder.text_token match, :space if match = scan(/[ \t]*\n/)
211
+ if scan(/(\s*<!--)(?:(.*?)(-->)|(.*))/m)
212
+ code = self[2] || self[4]
213
+ closing = self[3]
214
+ encoder.text_token self[1], :comment
215
+ else
216
+ code = scan_until(/(?=(?:\n\s*)?<\/script>)|\z/)
217
+ closing = false
218
+ end
219
+ unless code.empty?
220
+ encoder.begin_group :inline
221
+ scan_java_script encoder, code
222
+ encoder.end_group :inline
223
+ end
224
+ encoder.text_token closing, :comment if closing
225
+ state = :initial
226
+ else
227
+ raise 'unknown special tag: %p' % [in_tag]
228
+ end
229
+
199
230
  else
200
231
  raise_inspect 'Unknown state: %p' % [state], encoder
201
232
 
@@ -30,10 +30,10 @@ module Scanners
30
30
  IDENT_KIND = WordList.new(:ident).
31
31
  add(KEYWORDS, :keyword).
32
32
  add(RESERVED, :reserved).
33
- add(CONSTANTS, :pre_constant).
33
+ add(CONSTANTS, :predefined_constant).
34
34
  add(MAGIC_VARIABLES, :local_variable).
35
35
  add(TYPES, :type).
36
- add(BuiltinTypes::List, :pre_type).
36
+ add(BuiltinTypes::List, :predefined_type).
37
37
  add(BuiltinTypes::List.select { |builtin| builtin[/(Error|Exception)$/] }, :exception).
38
38
  add(DIRECTIVES, :directive) # :nodoc:
39
39
 
@@ -35,7 +35,7 @@ module Scanners
35
35
 
36
36
  IDENT_KIND = WordList.new(:ident).
37
37
  add(RESERVED_WORDS, :reserved).
38
- add(PREDEFINED_CONSTANTS, :pre_constant).
38
+ add(PREDEFINED_CONSTANTS, :predefined_constant).
39
39
  add(MAGIC_VARIABLES, :local_variable).
40
40
  add(KEYWORDS, :keyword) # :nodoc:
41
41
 
@@ -89,7 +89,7 @@ module Scanners
89
89
 
90
90
  until eos?
91
91
 
92
- if (match = scan_until(/(?=#{START_OF_RUBY})/o) || match = scan_until(/\z/)) and not match.empty?
92
+ if (match = scan_until(/(?=#{START_OF_RUBY})/o) || scan_rest) and not match.empty?
93
93
  @html_scanner.tokenize match
94
94
 
95
95
  elsif match = scan(/#{NITRO_VALUE_BLOCK}/o)
@@ -183,12 +183,12 @@ module Scanners
183
183
 
184
184
  IDENT_KIND = CaseIgnoringWordList.new(:ident).
185
185
  add(KEYWORDS, :reserved).
186
- add(TYPES, :pre_type).
186
+ add(TYPES, :predefined_type).
187
187
  add(LANGUAGE_CONSTRUCTS, :reserved).
188
188
  add(BUILTIN_FUNCTIONS, :predefined).
189
- add(CLASSES, :pre_constant).
189
+ add(CLASSES, :predefined_constant).
190
190
  add(EXCEPTIONS, :exception).
191
- add(CONSTANTS, :pre_constant)
191
+ add(CONSTANTS, :predefined_constant)
192
192
 
193
193
  VARIABLE_KIND = WordList.new(:local_variable).
194
194
  add(PREDEFINED, :predefined)
@@ -261,7 +261,7 @@ module Scanners
261
261
  label_expected = true
262
262
  states << :php
263
263
  else
264
- match = scan_until(/(?=#{RE::PHP_START})/o) || scan_until(/\z/)
264
+ match = scan_until(/(?=#{RE::PHP_START})/o) || scan_rest
265
265
  @html_scanner.tokenize match unless match.empty?
266
266
  end
267
267
 
@@ -58,7 +58,7 @@ module Scanners
58
58
  add(KEYWORDS, :keyword).
59
59
  add(OLD_KEYWORDS, :old_keyword).
60
60
  add(PREDEFINED_METHODS_AND_TYPES, :predefined).
61
- add(PREDEFINED_VARIABLES_AND_CONSTANTS, :pre_constant).
61
+ add(PREDEFINED_VARIABLES_AND_CONSTANTS, :predefined_constant).
62
62
  add(PREDEFINED_EXCEPTIONS, :exception) # :nodoc:
63
63
 
64
64
  NAME = / [^\W\d] \w* /x # :nodoc:
@@ -107,7 +107,7 @@ module Scanners
107
107
  string_raw = false
108
108
  string_type = nil
109
109
  docstring_coming = match?(/#{DOCSTRING_COMING}/o)
110
- import_clause = class_name_follows = last_token_dot = false
110
+ last_token_dot = false
111
111
  unicode = string.respond_to?(:encoding) && string.encoding.name == 'UTF-8'
112
112
  from_import_state = []
113
113
 
@@ -44,7 +44,7 @@ module Scanners
44
44
 
45
45
  until eos?
46
46
 
47
- if (match = scan_until(/(?=#{START_OF_ERB})/o) || scan_until(/\z/)) and not match.empty?
47
+ if (match = scan_until(/(?=#{START_OF_ERB})/o) || scan_rest) and not match.empty?
48
48
  @html_scanner.tokenize match, :tokens => encoder
49
49
 
50
50
  elsif match = scan(/#{ERB_RUBY_BLOCK}/o)
@@ -8,13 +8,6 @@ module Scanners
8
8
  #
9
9
  # It is optimized for HTML highlighting, and is not very useful for
10
10
  # parsing or pretty printing.
11
- #
12
- # For now, I think it's better than the scanners in VIM or Syntax, or
13
- # any highlighter I was able to find, except Caleb's RubyLexer.
14
- #
15
- # I hope it's also better than the rdoc/irb lexer.
16
- #
17
- # Alias: +irb+
18
11
  class Ruby < Scanner
19
12
 
20
13
  register_for :ruby
@@ -31,10 +24,8 @@ module Scanners
31
24
 
32
25
  def scan_tokens encoder, options
33
26
 
34
- patterns = Patterns # avoid constant lookup
35
-
36
27
  state = @state
37
- if state.instance_of? self.class::StringState
28
+ if state && state.instance_of?(self.class::StringState)
38
29
  encoder.begin_group state.type
39
30
  end
40
31
 
@@ -50,6 +41,8 @@ module Scanners
50
41
  # def_object_stack = nil
51
42
  # def_object_paren_depth = 0
52
43
 
44
+ patterns = Patterns # avoid constant lookup
45
+
53
46
  unicode = string.respond_to?(:encoding) && string.encoding.name == 'UTF-8'
54
47
 
55
48
  until eos?
@@ -339,7 +332,7 @@ module Scanners
339
332
 
340
333
  else # StringState
341
334
 
342
- match = scan_until(state.pattern) || scan_until(/\z/)
335
+ match = scan_until(state.pattern) || scan_rest
343
336
  unless match.empty?
344
337
  encoder.text_token match, :content
345
338
  break if eos?