coderay 0.9.8 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/{lib/README → README_INDEX.rdoc} +10 -21
  2. data/Rakefile +6 -6
  3. data/bin/coderay +193 -64
  4. data/lib/coderay.rb +61 -105
  5. data/lib/coderay/duo.rb +17 -21
  6. data/lib/coderay/encoder.rb +100 -112
  7. data/lib/coderay/encoders/_map.rb +12 -7
  8. data/lib/coderay/encoders/comment_filter.rb +12 -30
  9. data/lib/coderay/encoders/count.rb +29 -11
  10. data/lib/coderay/encoders/debug.rb +32 -20
  11. data/lib/coderay/encoders/div.rb +13 -9
  12. data/lib/coderay/encoders/filter.rb +34 -51
  13. data/lib/coderay/encoders/html.rb +155 -161
  14. data/lib/coderay/encoders/html/css.rb +4 -9
  15. data/lib/coderay/encoders/html/numbering.rb +115 -0
  16. data/lib/coderay/encoders/html/output.rb +22 -70
  17. data/lib/coderay/encoders/json.rb +59 -45
  18. data/lib/coderay/encoders/lines_of_code.rb +12 -57
  19. data/lib/coderay/encoders/null.rb +6 -14
  20. data/lib/coderay/encoders/page.rb +13 -9
  21. data/lib/coderay/encoders/span.rb +13 -9
  22. data/lib/coderay/encoders/statistic.rb +58 -39
  23. data/lib/coderay/encoders/terminal.rb +179 -0
  24. data/lib/coderay/encoders/text.rb +31 -17
  25. data/lib/coderay/encoders/token_kind_filter.rb +111 -0
  26. data/lib/coderay/encoders/xml.rb +19 -18
  27. data/lib/coderay/encoders/yaml.rb +37 -9
  28. data/lib/coderay/for_redcloth.rb +4 -4
  29. data/lib/coderay/helpers/file_type.rb +127 -246
  30. data/lib/coderay/helpers/gzip.rb +41 -0
  31. data/lib/coderay/helpers/plugin.rb +241 -306
  32. data/lib/coderay/helpers/word_list.rb +65 -126
  33. data/lib/coderay/scanner.rb +173 -156
  34. data/lib/coderay/scanners/_map.rb +18 -17
  35. data/lib/coderay/scanners/c.rb +63 -77
  36. data/lib/coderay/scanners/clojure.rb +217 -0
  37. data/lib/coderay/scanners/cpp.rb +71 -84
  38. data/lib/coderay/scanners/css.rb +103 -120
  39. data/lib/coderay/scanners/debug.rb +47 -44
  40. data/lib/coderay/scanners/delphi.rb +70 -76
  41. data/lib/coderay/scanners/diff.rb +141 -50
  42. data/lib/coderay/scanners/erb.rb +81 -0
  43. data/lib/coderay/scanners/groovy.rb +104 -113
  44. data/lib/coderay/scanners/haml.rb +168 -0
  45. data/lib/coderay/scanners/html.rb +181 -110
  46. data/lib/coderay/scanners/java.rb +73 -75
  47. data/lib/coderay/scanners/java/builtin_types.rb +2 -0
  48. data/lib/coderay/scanners/java_script.rb +90 -101
  49. data/lib/coderay/scanners/json.rb +40 -53
  50. data/lib/coderay/scanners/php.rb +123 -147
  51. data/lib/coderay/scanners/python.rb +93 -91
  52. data/lib/coderay/scanners/raydebug.rb +66 -0
  53. data/lib/coderay/scanners/ruby.rb +343 -326
  54. data/lib/coderay/scanners/ruby/patterns.rb +40 -106
  55. data/lib/coderay/scanners/ruby/string_state.rb +71 -0
  56. data/lib/coderay/scanners/sql.rb +80 -66
  57. data/lib/coderay/scanners/text.rb +26 -0
  58. data/lib/coderay/scanners/xml.rb +1 -1
  59. data/lib/coderay/scanners/yaml.rb +74 -73
  60. data/lib/coderay/style.rb +10 -7
  61. data/lib/coderay/styles/_map.rb +3 -3
  62. data/lib/coderay/styles/alpha.rb +143 -0
  63. data/lib/coderay/token_kinds.rb +90 -0
  64. data/lib/coderay/tokens.rb +102 -277
  65. data/lib/coderay/tokens_proxy.rb +55 -0
  66. data/lib/coderay/version.rb +3 -0
  67. data/test/functional/basic.rb +200 -18
  68. data/test/functional/examples.rb +130 -0
  69. data/test/functional/for_redcloth.rb +15 -8
  70. data/test/functional/suite.rb +9 -6
  71. metadata +103 -123
  72. data/FOLDERS +0 -53
  73. data/bin/coderay_stylesheet +0 -4
  74. data/lib/coderay/encoders/html/numerization.rb +0 -133
  75. data/lib/coderay/encoders/term.rb +0 -158
  76. data/lib/coderay/encoders/token_class_filter.rb +0 -84
  77. data/lib/coderay/helpers/gzip_simple.rb +0 -123
  78. data/lib/coderay/scanners/nitro_xhtml.rb +0 -136
  79. data/lib/coderay/scanners/plaintext.rb +0 -20
  80. data/lib/coderay/scanners/rhtml.rb +0 -78
  81. data/lib/coderay/scanners/scheme.rb +0 -145
  82. data/lib/coderay/styles/cycnus.rb +0 -152
  83. data/lib/coderay/styles/murphy.rb +0 -134
  84. data/lib/coderay/token_classes.rb +0 -86
  85. data/test/functional/load_plugin_scanner.rb +0 -11
  86. data/test/functional/vhdl.rb +0 -126
  87. data/test/functional/word_list.rb +0 -79
@@ -2,22 +2,42 @@ module CodeRay
2
2
  module Scanners
3
3
 
4
4
  # HTML Scanner
5
+ #
6
+ # Alias: +xhtml+
7
+ #
8
+ # See also: Scanners::XML
5
9
  class HTML < Scanner
6
10
 
7
- include Streamable
8
11
  register_for :html
9
12
 
10
13
  KINDS_NOT_LOC = [
11
14
  :comment, :doctype, :preprocessor,
12
15
  :tag, :attribute_name, :operator,
13
- :attribute_value, :delimiter, :content,
14
- :plain, :entity, :error
15
- ]
16
-
17
- ATTR_NAME = /[\w.:-]+/
18
- ATTR_VALUE_UNQUOTED = ATTR_NAME
19
- TAG_END = /\/?>/
20
- HEX = /[0-9a-fA-F]/
16
+ :attribute_value, :string,
17
+ :plain, :entity, :error,
18
+ ] # :nodoc:
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 = WordList::CaseIgnoring.new(nil).
36
+ add(EVENT_ATTRIBUTES, :script)
37
+
38
+ ATTR_NAME = /[\w.:-]+/ # :nodoc:
39
+ TAG_END = /\/?>/ # :nodoc:
40
+ HEX = /[0-9a-fA-F]/ # :nodoc:
21
41
  ENTITY = /
22
42
  &
23
43
  (?:
@@ -31,152 +51,203 @@ module Scanners
31
51
  )
32
52
  )
33
53
  ;
34
- /ox
35
-
54
+ /ox # :nodoc:
55
+
36
56
  PLAIN_STRING_CONTENT = {
37
57
  "'" => /[^&'>\n]+/,
38
58
  '"' => /[^&">\n]+/,
39
- }
40
-
59
+ } # :nodoc:
60
+
41
61
  def reset
42
62
  super
43
63
  @state = :initial
64
+ @plain_string_content = nil
44
65
  end
45
-
46
- private
66
+
67
+ protected
68
+
47
69
  def setup
48
70
  @state = :initial
49
71
  @plain_string_content = nil
50
72
  end
51
-
52
- def scan_tokens tokens, options
53
-
54
- state = @state
73
+
74
+ def scan_java_script encoder, code
75
+ if code && !code.empty?
76
+ @java_script_scanner ||= Scanners::JavaScript.new '', :keep_tokens => true
77
+ # encoder.begin_group :inline
78
+ @java_script_scanner.tokenize code, :tokens => encoder
79
+ # encoder.end_group :inline
80
+ end
81
+ end
82
+
83
+ def scan_tokens encoder, options
84
+ state = options[:state] || @state
55
85
  plain_string_content = @plain_string_content
56
-
86
+ in_tag = in_attribute = nil
87
+
88
+ encoder.begin_group :string if state == :attribute_value_string
89
+
57
90
  until eos?
58
-
59
- kind = nil
60
- match = nil
61
-
62
- if scan(/\s+/m)
63
- kind = :space
64
-
91
+
92
+ if state != :in_special_tag && match = scan(/\s+/m)
93
+ encoder.text_token match, :space
94
+
65
95
  else
66
-
96
+
67
97
  case state
68
-
98
+
69
99
  when :initial
70
- if scan(/<!--.*?-->/m)
71
- kind = :comment
72
- elsif scan(/<!DOCTYPE.*?>/m)
73
- kind = :doctype
74
- elsif scan(/<\?xml.*?\?>/m)
75
- kind = :preprocessor
76
- elsif scan(/<\?.*?\?>|<%.*?%>/m)
77
- kind = :comment
78
- elsif scan(/<\/[-\w.:]*>/m)
79
- kind = :tag
80
- elsif match = scan(/<[-\w.:]+>?/m)
81
- kind = :tag
82
- state = :attribute unless match[-1] == ?>
83
- elsif scan(/[^<>&]+/)
84
- kind = :plain
85
- elsif scan(/#{ENTITY}/ox)
86
- kind = :entity
87
- elsif scan(/[<>&]/)
88
- kind = :error
100
+ if match = scan(/<!--(?:.*?-->|.*)/m)
101
+ encoder.text_token match, :comment
102
+ elsif match = scan(/<!DOCTYPE(?:.*?>|.*)/m)
103
+ encoder.text_token match, :doctype
104
+ elsif match = scan(/<\?xml(?:.*?\?>|.*)/m)
105
+ encoder.text_token match, :preprocessor
106
+ elsif match = scan(/<\?(?:.*?\?>|.*)/m)
107
+ encoder.text_token match, :comment
108
+ elsif match = scan(/<\/[-\w.:]*>?/m)
109
+ in_tag = nil
110
+ encoder.text_token match, :tag
111
+ elsif match = scan(/<(?:(script)|[-\w.:]+)(>)?/m)
112
+ encoder.text_token match, :tag
113
+ in_tag = self[1]
114
+ if self[2]
115
+ state = :in_special_tag if in_tag
116
+ else
117
+ state = :attribute
118
+ end
119
+ elsif match = scan(/[^<>&]+/)
120
+ encoder.text_token match, :plain
121
+ elsif match = scan(/#{ENTITY}/ox)
122
+ encoder.text_token match, :entity
123
+ elsif match = scan(/[<>&]/)
124
+ in_tag = nil
125
+ encoder.text_token match, :error
89
126
  else
90
- raise_inspect '[BUG] else-case reached with state %p' % [state], tokens
127
+ raise_inspect '[BUG] else-case reached with state %p' % [state], encoder
91
128
  end
92
-
129
+
93
130
  when :attribute
94
- if scan(/#{TAG_END}/o)
95
- kind = :tag
96
- state = :initial
97
- elsif scan(/#{ATTR_NAME}/o)
98
- kind = :attribute_name
131
+ if match = scan(/#{TAG_END}/o)
132
+ encoder.text_token match, :tag
133
+ in_attribute = nil
134
+ if in_tag
135
+ state = :in_special_tag
136
+ else
137
+ state = :initial
138
+ end
139
+ elsif match = scan(/#{ATTR_NAME}/o)
140
+ in_attribute = IN_ATTRIBUTE[match]
141
+ encoder.text_token match, :attribute_name
99
142
  state = :attribute_equal
100
143
  else
101
- kind = :error
102
- getch
144
+ in_tag = nil
145
+ encoder.text_token getch, :error
103
146
  end
104
-
147
+
105
148
  when :attribute_equal
106
- if scan(/=/)
107
- kind = :operator
149
+ if match = scan(/=/) #/
150
+ encoder.text_token match, :operator
108
151
  state = :attribute_value
109
- elsif scan(/#{ATTR_NAME}/o)
110
- kind = :attribute_name
111
- elsif scan(/#{TAG_END}/o)
112
- kind = :tag
113
- state = :initial
114
- elsif scan(/./)
115
- kind = :error
152
+ elsif scan(/#{ATTR_NAME}/o) || scan(/#{TAG_END}/o)
153
+ state = :attribute
154
+ next
155
+ else
156
+ encoder.text_token getch, :error
116
157
  state = :attribute
117
158
  end
118
-
159
+
119
160
  when :attribute_value
120
- if scan(/#{ATTR_VALUE_UNQUOTED}/o)
121
- kind = :attribute_value
161
+ if match = scan(/#{ATTR_NAME}/o)
162
+ encoder.text_token match, :attribute_value
122
163
  state = :attribute
123
164
  elsif match = scan(/["']/)
124
- tokens << [:open, :string]
125
- state = :attribute_value_string
126
- plain_string_content = PLAIN_STRING_CONTENT[match]
127
- kind = :delimiter
128
- elsif scan(/#{TAG_END}/o)
129
- kind = :tag
165
+ if in_attribute == :script
166
+ encoder.begin_group :inline
167
+ encoder.text_token match, :inline_delimiter
168
+ if scan(/javascript:[ \t]*/)
169
+ encoder.text_token matched, :comment
170
+ end
171
+ code = scan_until(match == '"' ? /(?="|\z)/ : /(?='|\z)/)
172
+ scan_java_script encoder, code
173
+ match = scan(/["']/)
174
+ encoder.text_token match, :inline_delimiter if match
175
+ encoder.end_group :inline
176
+ state = :attribute
177
+ in_attribute = nil
178
+ else
179
+ encoder.begin_group :string
180
+ state = :attribute_value_string
181
+ plain_string_content = PLAIN_STRING_CONTENT[match]
182
+ encoder.text_token match, :delimiter
183
+ end
184
+ elsif match = scan(/#{TAG_END}/o)
185
+ encoder.text_token match, :tag
130
186
  state = :initial
131
187
  else
132
- kind = :error
133
- getch
188
+ encoder.text_token getch, :error
134
189
  end
135
-
190
+
136
191
  when :attribute_value_string
137
- if scan(plain_string_content)
138
- kind = :content
139
- elsif scan(/['"]/)
140
- tokens << [matched, :delimiter]
141
- tokens << [:close, :string]
192
+ if match = scan(plain_string_content)
193
+ encoder.text_token match, :content
194
+ elsif match = scan(/['"]/)
195
+ encoder.text_token match, :delimiter
196
+ encoder.end_group :string
142
197
  state = :attribute
143
- next
144
- elsif scan(/#{ENTITY}/ox)
145
- kind = :entity
146
- elsif scan(/&/)
147
- kind = :content
148
- elsif scan(/[\n>]/)
149
- tokens << [:close, :string]
150
- kind = :error
198
+ elsif match = scan(/#{ENTITY}/ox)
199
+ encoder.text_token match, :entity
200
+ elsif match = scan(/&/)
201
+ encoder.text_token match, :content
202
+ elsif match = scan(/[\n>]/)
203
+ encoder.end_group :string
151
204
  state = :initial
205
+ encoder.text_token match, :error
152
206
  end
153
-
207
+
208
+ when :in_special_tag
209
+ case in_tag
210
+ when 'script'
211
+ encoder.text_token match, :space if match = scan(/[ \t]*\n/)
212
+ if scan(/(\s*<!--)(?:(.*?)(-->)|(.*))/m)
213
+ code = self[2] || self[4]
214
+ closing = self[3]
215
+ encoder.text_token self[1], :comment
216
+ else
217
+ code = scan_until(/(?=(?:\n\s*)?<\/script>)|\z/)
218
+ closing = false
219
+ end
220
+ unless code.empty?
221
+ encoder.begin_group :inline
222
+ scan_java_script encoder, code
223
+ encoder.end_group :inline
224
+ end
225
+ encoder.text_token closing, :comment if closing
226
+ state = :initial
227
+ else
228
+ raise 'unknown special tag: %p' % [in_tag]
229
+ end
230
+
154
231
  else
155
- raise_inspect 'Unknown state: %p' % [state], tokens
156
-
232
+ raise_inspect 'Unknown state: %p' % [state], encoder
233
+
157
234
  end
158
-
159
- end
160
-
161
- match ||= matched
162
- if $CODERAY_DEBUG and not kind
163
- raise_inspect 'Error token %p in line %d' %
164
- [[match, kind], line], tokens, state
235
+
165
236
  end
166
- raise_inspect 'Empty token', tokens unless match
167
-
168
- tokens << [match, kind]
237
+
169
238
  end
170
-
239
+
171
240
  if options[:keep_state]
172
241
  @state = state
173
242
  @plain_string_content = plain_string_content
174
243
  end
175
-
176
- tokens
244
+
245
+ encoder.end_group :string if state == :attribute_value_string
246
+
247
+ encoder
177
248
  end
178
-
249
+
179
250
  end
180
-
251
+
181
252
  end
182
253
  end
@@ -1,11 +1,12 @@
1
1
  module CodeRay
2
2
  module Scanners
3
-
3
+
4
+ # Scanner for Java.
4
5
  class Java < Scanner
5
-
6
- include Streamable
6
+
7
7
  register_for :java
8
- helper :builtin_types
8
+
9
+ autoload :BuiltinTypes, 'coderay/scanners/java/builtin_types'
9
10
 
10
11
  # http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html
11
12
  KEYWORDS = %w[
@@ -13,63 +14,64 @@ module Scanners
13
14
  finally for if instanceof import new package
14
15
  return switch throw try typeof while
15
16
  debugger export
16
- ]
17
- RESERVED = %w[ const goto ]
18
- CONSTANTS = %w[ false null true ]
19
- MAGIC_VARIABLES = %w[ this super ]
17
+ ] # :nodoc:
18
+ RESERVED = %w[ const goto ] # :nodoc:
19
+ CONSTANTS = %w[ false null true ] # :nodoc:
20
+ MAGIC_VARIABLES = %w[ this super ] # :nodoc:
20
21
  TYPES = %w[
21
22
  boolean byte char class double enum float int interface long
22
23
  short void
23
- ] << '[]' # because int[] should be highlighted as a type
24
+ ] << '[]' # :nodoc: because int[] should be highlighted as a type
24
25
  DIRECTIVES = %w[
25
26
  abstract extends final implements native private protected public
26
27
  static strictfp synchronized throws transient volatile
27
- ]
28
+ ] # :nodoc:
28
29
 
29
30
  IDENT_KIND = WordList.new(:ident).
30
31
  add(KEYWORDS, :keyword).
31
32
  add(RESERVED, :reserved).
32
- add(CONSTANTS, :pre_constant).
33
+ add(CONSTANTS, :predefined_constant).
33
34
  add(MAGIC_VARIABLES, :local_variable).
34
35
  add(TYPES, :type).
35
- add(BuiltinTypes::List, :pre_type).
36
+ add(BuiltinTypes::List, :predefined_type).
36
37
  add(BuiltinTypes::List.select { |builtin| builtin[/(Error|Exception)$/] }, :exception).
37
- add(DIRECTIVES, :directive)
38
+ add(DIRECTIVES, :directive) # :nodoc:
38
39
 
39
- ESCAPE = / [bfnrtv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x
40
- UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x
40
+ ESCAPE = / [bfnrtv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
41
+ UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
41
42
  STRING_CONTENT_PATTERN = {
42
43
  "'" => /[^\\']+/,
43
44
  '"' => /[^\\"]+/,
44
45
  '/' => /[^\\\/]+/,
45
- }
46
- IDENT = /[a-zA-Z_][A-Za-z_0-9]*/
46
+ } # :nodoc:
47
+ IDENT = /[a-zA-Z_][A-Za-z_0-9]*/ # :nodoc:
48
+
49
+ protected
47
50
 
48
- def scan_tokens tokens, options
51
+ def scan_tokens encoder, options
49
52
 
50
53
  state = :initial
51
54
  string_delimiter = nil
52
- import_clause = class_name_follows = last_token_dot = false
55
+ package_name_expected = false
56
+ class_name_follows = false
57
+ last_token_dot = false
53
58
 
54
59
  until eos?
55
60
 
56
- kind = nil
57
- match = nil
58
-
59
61
  case state
60
62
 
61
63
  when :initial
62
64
 
63
65
  if match = scan(/ \s+ | \\\n /x)
64
- tokens << [match, :space]
66
+ encoder.text_token match, :space
65
67
  next
66
68
 
67
69
  elsif match = scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx)
68
- tokens << [match, :comment]
70
+ encoder.text_token match, :comment
69
71
  next
70
72
 
71
- elsif import_clause && scan(/ #{IDENT} (?: \. #{IDENT} )* /ox)
72
- kind = :include
73
+ elsif package_name_expected && match = scan(/ #{IDENT} (?: \. #{IDENT} )* /ox)
74
+ encoder.text_token match, package_name_expected
73
75
 
74
76
  elsif match = scan(/ #{IDENT} | \[\] /ox)
75
77
  kind = IDENT_KIND[match]
@@ -79,95 +81,91 @@ module Scanners
79
81
  kind = :class
80
82
  class_name_follows = false
81
83
  else
82
- import_clause = true if match == 'import'
83
- class_name_follows = true if match == 'class' || match == 'interface'
84
+ case match
85
+ when 'import'
86
+ package_name_expected = :include
87
+ when 'package'
88
+ package_name_expected = :namespace
89
+ when 'class', 'interface'
90
+ class_name_follows = true
91
+ end
84
92
  end
93
+ encoder.text_token match, kind
85
94
 
86
- elsif scan(/ \.(?!\d) | [,?:()\[\]}] | -- | \+\+ | && | \|\| | \*\*=? | [-+*\/%^~&|<>=!]=? | <<<?=? | >>>?=? /x)
87
- kind = :operator
95
+ elsif match = scan(/ \.(?!\d) | [,?:()\[\]}] | -- | \+\+ | && | \|\| | \*\*=? | [-+*\/%^~&|<>=!]=? | <<<?=? | >>>?=? /x)
96
+ encoder.text_token match, :operator
88
97
 
89
- elsif scan(/;/)
90
- import_clause = false
91
- kind = :operator
98
+ elsif match = scan(/;/)
99
+ package_name_expected = false
100
+ encoder.text_token match, :operator
92
101
 
93
- elsif scan(/\{/)
102
+ elsif match = scan(/\{/)
94
103
  class_name_follows = false
95
- kind = :operator
104
+ encoder.text_token match, :operator
96
105
 
97
106
  elsif check(/[\d.]/)
98
- if scan(/0[xX][0-9A-Fa-f]+/)
99
- kind = :hex
100
- elsif scan(/(?>0[0-7]+)(?![89.eEfF])/)
101
- kind = :oct
102
- elsif scan(/\d+[fFdD]|\d*\.\d+(?:[eE][+-]?\d+)?[fFdD]?|\d+[eE][+-]?\d+[fFdD]?/)
103
- kind = :float
104
- elsif scan(/\d+[lL]?/)
105
- kind = :integer
107
+ if match = scan(/0[xX][0-9A-Fa-f]+/)
108
+ encoder.text_token match, :hex
109
+ elsif match = scan(/(?>0[0-7]+)(?![89.eEfF])/)
110
+ encoder.text_token match, :octal
111
+ elsif match = scan(/\d+[fFdD]|\d*\.\d+(?:[eE][+-]?\d+)?[fFdD]?|\d+[eE][+-]?\d+[fFdD]?/)
112
+ encoder.text_token match, :float
113
+ elsif match = scan(/\d+[lL]?/)
114
+ encoder.text_token match, :integer
106
115
  end
107
116
 
108
117
  elsif match = scan(/["']/)
109
- tokens << [:open, :string]
110
118
  state = :string
119
+ encoder.begin_group state
111
120
  string_delimiter = match
112
- kind = :delimiter
121
+ encoder.text_token match, :delimiter
113
122
 
114
- elsif scan(/ @ #{IDENT} /ox)
115
- kind = :annotation
123
+ elsif match = scan(/ @ #{IDENT} /ox)
124
+ encoder.text_token match, :annotation
116
125
 
117
126
  else
118
- getch
119
- kind = :error
127
+ encoder.text_token getch, :error
120
128
 
121
129
  end
122
130
 
123
131
  when :string
124
- if scan(STRING_CONTENT_PATTERN[string_delimiter])
125
- kind = :content
132
+ if match = scan(STRING_CONTENT_PATTERN[string_delimiter])
133
+ encoder.text_token match, :content
126
134
  elsif match = scan(/["'\/]/)
127
- tokens << [match, :delimiter]
128
- tokens << [:close, state]
129
- string_delimiter = nil
135
+ encoder.text_token match, :delimiter
136
+ encoder.end_group state
130
137
  state = :initial
131
- next
138
+ string_delimiter = nil
132
139
  elsif state == :string && (match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox))
133
140
  if string_delimiter == "'" && !(match == "\\\\" || match == "\\'")
134
- kind = :content
141
+ encoder.text_token match, :content
135
142
  else
136
- kind = :char
143
+ encoder.text_token match, :char
137
144
  end
138
- elsif scan(/\\./m)
139
- kind = :content
140
- elsif scan(/ \\ | $ /x)
141
- tokens << [:close, state]
142
- kind = :error
145
+ elsif match = scan(/\\./m)
146
+ encoder.text_token match, :content
147
+ elsif match = scan(/ \\ | $ /x)
148
+ encoder.end_group state
143
149
  state = :initial
150
+ encoder.text_token match, :error
144
151
  else
145
- raise_inspect "else case \" reached; %p not handled." % peek(1), tokens
152
+ raise_inspect "else case \" reached; %p not handled." % peek(1), encoder
146
153
  end
147
154
 
148
155
  else
149
- raise_inspect 'Unknown state', tokens
156
+ raise_inspect 'Unknown state', encoder
150
157
 
151
158
  end
152
-
153
- match ||= matched
154
- if $CODERAY_DEBUG and not kind
155
- raise_inspect 'Error token %p in line %d' %
156
- [[match, kind], line], tokens
157
- end
158
- raise_inspect 'Empty token', tokens unless match
159
159
 
160
160
  last_token_dot = match == '.'
161
161
 
162
- tokens << [match, kind]
163
-
164
162
  end
165
163
 
166
164
  if state == :string
167
- tokens << [:close, state]
165
+ encoder.end_group state
168
166
  end
169
167
 
170
- tokens
168
+ encoder
171
169
  end
172
170
 
173
171
  end