coderay 0.7.4.215 → 0.8.260

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/LICENSE +421 -257
  2. data/README +24 -13
  3. data/bin/coderay +9 -4
  4. data/lib/coderay.rb +19 -17
  5. data/lib/coderay/duo.rb +67 -9
  6. data/lib/coderay/encoder.rb +18 -9
  7. data/lib/coderay/encoders/_map.rb +2 -1
  8. data/lib/coderay/encoders/debug.rb +14 -11
  9. data/lib/coderay/encoders/html.rb +44 -17
  10. data/lib/coderay/encoders/html/css.rb +13 -8
  11. data/lib/coderay/encoders/html/numerization.rb +8 -6
  12. data/lib/coderay/encoders/html/output.rb +3 -1
  13. data/lib/coderay/encoders/statistic.rb +2 -6
  14. data/lib/coderay/encoders/text.rb +2 -3
  15. data/lib/coderay/encoders/tokens.rb +3 -3
  16. data/lib/coderay/encoders/xml.rb +1 -2
  17. data/lib/coderay/for_redcloth.rb +72 -0
  18. data/lib/coderay/helpers/file_type.rb +38 -9
  19. data/lib/coderay/helpers/gzip_simple.rb +1 -0
  20. data/lib/coderay/helpers/plugin.rb +15 -8
  21. data/lib/coderay/helpers/word_list.rb +4 -0
  22. data/lib/coderay/scanner.rb +30 -13
  23. data/lib/coderay/scanners/_map.rb +1 -1
  24. data/lib/coderay/scanners/c.rb +3 -1
  25. data/lib/coderay/scanners/css.rb +181 -0
  26. data/lib/coderay/scanners/debug.rb +1 -0
  27. data/lib/coderay/scanners/delphi.rb +1 -0
  28. data/lib/coderay/scanners/diff.rb +104 -0
  29. data/lib/coderay/scanners/java.rb +179 -0
  30. data/lib/coderay/scanners/java/builtin_types.rb +419 -0
  31. data/lib/coderay/scanners/java_script.rb +187 -0
  32. data/lib/coderay/scanners/json.rb +106 -0
  33. data/lib/coderay/scanners/nitro_xhtml.rb +5 -4
  34. data/lib/coderay/scanners/plaintext.rb +2 -0
  35. data/lib/coderay/scanners/rhtml.rb +2 -2
  36. data/lib/coderay/scanners/ruby.rb +64 -50
  37. data/lib/coderay/scanners/ruby/patterns.rb +15 -19
  38. data/lib/coderay/scanners/scheme.rb +142 -0
  39. data/lib/coderay/scanners/sql.Keith.rb +143 -0
  40. data/lib/coderay/scanners/sql.rb +154 -0
  41. data/lib/coderay/scanners/xml.rb +1 -0
  42. data/lib/coderay/styles/cycnus.rb +30 -9
  43. data/lib/coderay/styles/murphy.rb +15 -2
  44. data/lib/coderay/{encoders/html/classes.rb → token_classes.rb} +14 -9
  45. data/lib/coderay/tokens.rb +33 -14
  46. data/lib/term/ansicolor.rb +220 -0
  47. metadata +62 -44
@@ -0,0 +1,106 @@
1
+ module CodeRay
2
+ module Scanners
3
+
4
+ class JSON < Scanner
5
+
6
+ include Streamable
7
+
8
+ register_for :json
9
+
10
+ CONSTANTS = %w( true false null )
11
+ IDENT_KIND = WordList.new(:key).add(CONSTANTS, :reserved)
12
+
13
+ ESCAPE = / [bfnrt\\"\/] /x
14
+ UNICODE_ESCAPE = / u[a-fA-F0-9]{4} /x
15
+
16
+ def scan_tokens tokens, options
17
+
18
+ state = :initial
19
+ stack = []
20
+ string_delimiter = nil
21
+ key_expected = false
22
+
23
+ until eos?
24
+
25
+ kind = nil
26
+ match = nil
27
+
28
+ case state
29
+
30
+ when :initial
31
+ if match = scan(/ \s+ | \\\n /x)
32
+ tokens << [match, :space]
33
+ next
34
+ elsif match = scan(/ [:,\[{\]}] /x)
35
+ kind = :operator
36
+ case match
37
+ when '{': stack << :object; key_expected = true
38
+ when '[': stack << :array
39
+ when ':': key_expected = false
40
+ when ',': key_expected = true if stack.last == :object
41
+ when '}', ']': stack.pop # no error recovery, but works for valid JSON
42
+ end
43
+ elsif match = scan(/ true | false | null /x)
44
+ kind = IDENT_KIND[match]
45
+ elsif match = scan(/-?(?:0|[1-9]\d*)/)
46
+ kind = :integer
47
+ if scan(/\.\d+(?:[eE][-+]?\d+)?|[eE][-+]?\d+/)
48
+ match << matched
49
+ kind = :float
50
+ end
51
+ elsif match = scan(/"/)
52
+ state = key_expected ? :key : :string
53
+ tokens << [:open, state]
54
+ kind = :delimiter
55
+ else
56
+ getch
57
+ kind = :error
58
+ end
59
+
60
+ when :string, :key
61
+ if scan(/[^\\"]+/)
62
+ kind = :content
63
+ elsif scan(/"/)
64
+ tokens << ['"', :delimiter]
65
+ tokens << [:close, state]
66
+ state = :initial
67
+ next
68
+ elsif scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
69
+ kind = :char
70
+ elsif scan(/\\./m)
71
+ kind = :content
72
+ elsif scan(/ \\ | $ /x)
73
+ tokens << [:close, :delimiter]
74
+ kind = :error
75
+ state = :initial
76
+ else
77
+ raise_inspect "else case \" reached; %p not handled." % peek(1), tokens
78
+ end
79
+
80
+ else
81
+ raise_inspect 'Unknown state', tokens
82
+
83
+ end
84
+
85
+ match ||= matched
86
+ if $DEBUG and not kind
87
+ raise_inspect 'Error token %p in line %d' %
88
+ [[match, kind], line], tokens
89
+ end
90
+ raise_inspect 'Empty token', tokens unless match
91
+
92
+ tokens << [match, kind]
93
+
94
+ end
95
+
96
+ if [:string, :key].include? state
97
+ tokens << [:close, state]
98
+ end
99
+
100
+ tokens
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+ end
@@ -11,6 +11,7 @@ module Scanners
11
11
 
12
12
  include Streamable
13
13
  register_for :nitro_xhtml
14
+ file_extension :xhtml
14
15
 
15
16
  NITRO_RUBY_BLOCK = /
16
17
  <\?r
@@ -95,20 +96,20 @@ module Scanners
95
96
  delimiter = CLOSING_PAREN[start_tag[1,1]]
96
97
  end_tag = match[-1,1] == delimiter ? delimiter : ''
97
98
  tokens << [:open, :inline]
98
- tokens << [start_tag, :delimiter]
99
+ tokens << [start_tag, :inline_delimiter]
99
100
  code = match[start_tag.size .. -1 - end_tag.size]
100
101
  @ruby_scanner.tokenize code
101
- tokens << [end_tag, :delimiter] unless end_tag.empty?
102
+ tokens << [end_tag, :inline_delimiter] unless end_tag.empty?
102
103
  tokens << [:close, :inline]
103
104
 
104
105
  elsif match = scan(/#{NITRO_RUBY_BLOCK}/o)
105
106
  start_tag = '<?r'
106
107
  end_tag = match[-2,2] == '?>' ? '?>' : ''
107
108
  tokens << [:open, :inline]
108
- tokens << [start_tag, :delimiter]
109
+ tokens << [start_tag, :inline_delimiter]
109
110
  code = match[start_tag.size .. -(end_tag.size)-1]
110
111
  @ruby_scanner.tokenize code
111
- tokens << [end_tag, :delimiter] unless end_tag.empty?
112
+ tokens << [end_tag, :inline_delimiter] unless end_tag.empty?
112
113
  tokens << [:close, :inline]
113
114
 
114
115
  elsif entity = scan(/#{NITRO_ENTITY}/o)
@@ -4,6 +4,8 @@ module Scanners
4
4
  class Plaintext < Scanner
5
5
 
6
6
  register_for :plaintext, :plain
7
+
8
+ include Streamable
7
9
 
8
10
  def scan_tokens tokens, options
9
11
  text = (scan_until(/\z/) || '')
@@ -51,10 +51,10 @@ module Scanners
51
51
  start_tag = match[/\A<%[-=]?/]
52
52
  end_tag = match[/-?%?>?\z/]
53
53
  tokens << [:open, :inline]
54
- tokens << [start_tag, :delimiter]
54
+ tokens << [start_tag, :inline_delimiter]
55
55
  code = match[start_tag.size .. -1 - end_tag.size]
56
56
  @ruby_scanner.tokenize code
57
- tokens << [end_tag, :delimiter] unless end_tag.empty?
57
+ tokens << [end_tag, :inline_delimiter] unless end_tag.empty?
58
58
  tokens << [:close, :inline]
59
59
 
60
60
  else
@@ -18,6 +18,7 @@ module Scanners
18
18
  include Streamable
19
19
 
20
20
  register_for :ruby
21
+ file_extension 'rb'
21
22
 
22
23
  helper :patterns
23
24
 
@@ -90,15 +91,15 @@ module Scanners
90
91
  end
91
92
 
92
93
  when '#'
93
- case peek(1)[0]
94
- when ?{
94
+ case peek(1)
95
+ when '{'
95
96
  inline_block_stack << [state, depth, heredocs]
96
97
  value_expected = true
97
98
  state = :initial
98
99
  depth = 1
99
100
  tokens << [:open, :inline]
100
101
  tokens << [match + getch, :inline_delimiter]
101
- when ?$, ?@
102
+ when '$', '@'
102
103
  tokens << [match, :escape]
103
104
  last_state = state # scan one token as normal code, then return here
104
105
  state = :initial
@@ -121,36 +122,37 @@ module Scanners
121
122
  # }}}
122
123
  else
123
124
  # {{{
124
- if match = scan(/ [ \t\f]+ | \\? \n | \# .* /x) or
125
- ( bol? and match = scan(/#{patterns::RUBYDOC_OR_DATA}/o) )
126
- case m = match[0]
127
- when ?\s, ?\t, ?\f
128
- match << scan(/\s*/) unless eos? or heredocs
129
- kind = :space
130
- when ?\n, ?\\
131
- kind = :space
132
- if m == ?\n
133
- value_expected = true # FIXME not quite true
134
- state = :initial if state == :undef_comma_expected
135
- end
136
- if heredocs
137
- unscan # heredoc scanning needs \n at start
138
- state = heredocs.shift
139
- tokens << [:open, state.type]
140
- heredocs = nil if heredocs.empty?
141
- next
142
- else
143
- match << scan(/\s*/) unless eos?
144
- end
145
- when ?#, ?=, ?_
146
- kind = :comment
147
- value_expected = true
125
+ if match = scan(/[ \t\f]+/)
126
+ kind = :space
127
+ match << scan(/\s*/) unless eos? || heredocs
128
+ value_expected = true if match.index(?\n) # FIXME not quite true
129
+ tokens << [match, kind]
130
+ next
131
+
132
+ elsif match = scan(/\\?\n/)
133
+ kind = :space
134
+ if match == "\n"
135
+ value_expected = true # FIXME not quite true
136
+ state = :initial if state == :undef_comma_expected
137
+ end
138
+ if heredocs
139
+ unscan # heredoc scanning needs \n at start
140
+ state = heredocs.shift
141
+ tokens << [:open, state.type]
142
+ heredocs = nil if heredocs.empty?
143
+ next
148
144
  else
149
- raise_inspect 'else-case _ reached, because case %p was
150
- not handled' % [matched[0].chr], tokens
145
+ match << scan(/\s*/) unless eos?
151
146
  end
152
147
  tokens << [match, kind]
153
148
  next
149
+
150
+ elsif match = scan(/\#.*/) or
151
+ ( bol? and match = scan(/#{patterns::RUBYDOC_OR_DATA}/o) )
152
+ kind = :comment
153
+ value_expected = true
154
+ tokens << [match, kind]
155
+ next
154
156
 
155
157
  elsif state == :initial
156
158
 
@@ -167,19 +169,19 @@ module Scanners
167
169
  end
168
170
  end
169
171
  ## experimental!
170
- value_expected = :set if
171
- patterns::REGEXP_ALLOWED[match] or check(/#{patterns::VALUE_FOLLOWS}/o)
172
+ value_expected = :set if check(/#{patterns::VALUE_FOLLOWS}/o)
172
173
 
173
174
  elsif last_token_dot and match = scan(/#{patterns::METHOD_NAME_OPERATOR}/o)
174
175
  kind = :ident
175
176
  value_expected = :set if check(/#{patterns::VALUE_FOLLOWS}/o)
176
177
 
177
178
  # OPERATORS #
178
- elsif not last_token_dot and match = scan(/ ==?=? | \.\.?\.? | [\(\)\[\]\{\}] | :: | , /x)
179
+ # TODO: match (), [], {} as one single operator
180
+ elsif not last_token_dot and match = scan(/ \.\.\.? | (?:\.|::)() | [,\(\)\[\]\{\}] | ==?=? /x)
179
181
  if match !~ / [.\)\]\}] /x or match =~ /\.\.\.?/
180
182
  value_expected = :set
181
183
  end
182
- last_token_dot = :set if match == '.' or match == '::'
184
+ last_token_dot = :set if self[1]
183
185
  kind = :operator
184
186
  unless inline_block_stack.empty?
185
187
  case match
@@ -210,8 +212,9 @@ module Scanners
210
212
  interpreted = true
211
213
  state = patterns::StringState.new :regexp, interpreted, match
212
214
 
213
- elsif match = scan(/#{patterns::NUMERIC}/o)
214
- kind = if self[1] then :float else :integer end
215
+ # elsif match = scan(/[-+]?#{patterns::NUMERIC}/o)
216
+ elsif match = value_expected ? scan(/[-+]?#{patterns::NUMERIC}/o) : scan(/#{patterns::NUMERIC}/o)
217
+ kind = self[1] ? :float : :integer
215
218
 
216
219
  elsif match = scan(/#{patterns::SYMBOL}/o)
217
220
  case delim = match[1]
@@ -285,6 +288,18 @@ module Scanners
285
288
  next
286
289
  end
287
290
 
291
+ elsif state == :module_expected
292
+ if match = scan(/<</)
293
+ kind = :operator
294
+ else
295
+ state = :initial
296
+ if match = scan(/ (?:#{patterns::IDENT}::)* #{patterns::IDENT} /ox)
297
+ kind = :class
298
+ else
299
+ next
300
+ end
301
+ end
302
+
288
303
  elsif state == :undef_expected
289
304
  state = :undef_comma_expected
290
305
  if match = scan(/#{patterns::METHOD_NAME_EX}/o)
@@ -306,6 +321,15 @@ module Scanners
306
321
  next
307
322
  end
308
323
 
324
+ elsif state == :alias_expected
325
+ if match = scan(/(#{patterns::METHOD_NAME_OR_SYMBOL})([ \t]+)(#{patterns::METHOD_NAME_OR_SYMBOL})/o)
326
+ tokens << [self[1], (self[1][0] == ?: ? :symbol : :method)]
327
+ tokens << [self[2], :space]
328
+ tokens << [self[3], (self[3][0] == ?: ? :symbol : :method)]
329
+ end
330
+ state = :initial
331
+ next
332
+
309
333
  elsif state == :undef_comma_expected
310
334
  if match = scan(/,/)
311
335
  kind = :operator
@@ -315,23 +339,13 @@ module Scanners
315
339
  next
316
340
  end
317
341
 
318
- elsif state == :module_expected
319
- if match = scan(/<</)
320
- kind = :operator
321
- else
322
- state = :initial
323
- if match = scan(/ (?:#{patterns::IDENT}::)* #{patterns::IDENT} /ox)
324
- kind = :class
325
- else
326
- next
327
- end
328
- end
329
-
330
342
  end
331
343
  # }}}
332
-
333
- value_expected = value_expected == :set
334
- last_token_dot = last_token_dot == :set
344
+
345
+ unless kind == :error
346
+ value_expected = value_expected == :set
347
+ last_token_dot = last_token_dot == :set
348
+ end
335
349
 
336
350
  if $DEBUG and not kind
337
351
  raise_inspect 'Error token %p in line %d' %
@@ -14,19 +14,14 @@ module Scanners
14
14
 
15
15
  DEF_KEYWORDS = %w[ def ]
16
16
  UNDEF_KEYWORDS = %w[ undef ]
17
+ ALIAS_KEYWORDS = %w[ alias ]
17
18
  MODULE_KEYWORDS = %w[class module]
18
19
  DEF_NEW_STATE = WordList.new(:initial).
19
20
  add(DEF_KEYWORDS, :def_expected).
20
21
  add(UNDEF_KEYWORDS, :undef_expected).
22
+ add(ALIAS_KEYWORDS, :alias_expected).
21
23
  add(MODULE_KEYWORDS, :module_expected)
22
24
 
23
- IDENTS_ALLOWING_REGEXP = %w[
24
- and or not while until unless if then elsif when sub sub! gsub gsub!
25
- scan slice slice! split
26
- ]
27
- REGEXP_ALLOWED = WordList.new(false).
28
- add(IDENTS_ALLOWING_REGEXP, :set)
29
-
30
25
  PREDEFINED_CONSTANTS = %w[
31
26
  nil true false self
32
27
  DATA ARGV ARGF __FILE__ __LINE__
@@ -41,19 +36,20 @@ module Scanners
41
36
  METHOD_NAME = / #{IDENT} [?!]? /ox
42
37
  METHOD_NAME_OPERATOR = /
43
38
  \*\*? # multiplication and power
44
- | [-+]@? # plus, minus
45
- | [\/%&|^`~] # division, modulo or format strings, &and, |or, ^xor, `system`, tilde
39
+ | [-+~]@? # plus, minus, tilde with and without @
40
+ | [\/%&|^`] # division, modulo or format strings, &and, |or, ^xor, `system`
46
41
  | \[\]=? # array getter and setter
47
42
  | << | >> # append or shift left, shift right
48
43
  | <=?>? | >=? # comparison, rocket operator
49
- | ===? # simple equality and case equality
44
+ | ===? | =~ # simple equality, case equality, match
45
+ | ![~=@]? # negation with and without @, not-equal and not-match
50
46
  /ox
51
47
  METHOD_NAME_EX = / #{IDENT} (?:[?!]|=(?!>))? | #{METHOD_NAME_OPERATOR} /ox
52
48
  INSTANCE_VARIABLE = / @ #{IDENT} /ox
53
49
  CLASS_VARIABLE = / @@ #{IDENT} /ox
54
50
  OBJECT_VARIABLE = / @@? #{IDENT} /ox
55
51
  GLOBAL_VARIABLE = / \$ (?: #{IDENT} | [1-9]\d* | 0\w* | [~&+`'=\/,;_.<>!@$?*":\\] | -[a-zA-Z_0-9] ) /ox
56
- PREFIX_VARIABLE = / #{GLOBAL_VARIABLE} |#{OBJECT_VARIABLE} /ox
52
+ PREFIX_VARIABLE = / #{GLOBAL_VARIABLE} | #{OBJECT_VARIABLE} /ox
57
53
  VARIABLE = / @?@? #{IDENT} | #{GLOBAL_VARIABLE} /ox
58
54
 
59
55
  QUOTE_TO_TYPE = {
@@ -73,7 +69,7 @@ module Scanners
73
69
  EXPONENT = / [eE] [+-]? #{DECIMAL} /ox
74
70
  FLOAT_SUFFIX = / #{EXPONENT} | \. #{DECIMAL} #{EXPONENT}? /ox
75
71
  FLOAT_OR_INT = / #{DECIMAL} (?: #{FLOAT_SUFFIX} () )? /ox
76
- NUMERIC = / [-+]? (?: (?=0) (?: #{OCTAL} | #{HEXADECIMAL} | #{BINARY} ) | #{FLOAT_OR_INT} ) /ox
72
+ NUMERIC = / (?: (?=0) (?: #{OCTAL} | #{HEXADECIMAL} | #{BINARY} ) | #{FLOAT_OR_INT} ) /ox
77
73
 
78
74
  SYMBOL = /
79
75
  :
@@ -83,6 +79,7 @@ module Scanners
83
79
  | ['"]
84
80
  )
85
81
  /ox
82
+ METHOD_NAME_OR_SYMBOL = / #{METHOD_NAME_EX} | #{SYMBOL} /ox
86
83
 
87
84
  # TODO investigste \M, \c and \C escape sequences
88
85
  # (?: M-\\C-|C-\\M-|M-\\c|c\\M-|c|C-|M-)? (?: \\ (?: [0-7]{3} | x[0-9A-Fa-f]{2} | . ) )
@@ -111,7 +108,7 @@ module Scanners
111
108
  (?:
112
109
  ( [A-Za-z_0-9]+ ) # $2 = delim
113
110
  |
114
- ( ["'`] ) # $3 = quote, type
111
+ ( ["'`\/] ) # $3 = quote, type
115
112
  ( [^\n]*? ) \3 # $4 = delim
116
113
  )
117
114
  /mx
@@ -129,15 +126,14 @@ module Scanners
129
126
  /mx
130
127
 
131
128
  # Checks for a valid value to follow. This enables
132
- # fancy_allowed in method calls.
129
+ # value_expected in method calls without parentheses.
133
130
  VALUE_FOLLOWS = /
134
- \s+
131
+ (?>[ \t\f\v]+)
135
132
  (?:
136
133
  [%\/][^\s=]
137
- |
138
- <<-?\S
139
- |
140
- #{CHARACTER}
134
+ | <<-?\S
135
+ | [-+] \d
136
+ | #{CHARACTER}
141
137
  )
142
138
  /x
143
139
 
@@ -0,0 +1,142 @@
1
+ module CodeRay
2
+ module Scanners
3
+
4
+ # Scheme scanner for CodeRay (by closure).
5
+ # Thanks to murphy for putting CodeRay into public.
6
+ class Scheme < Scanner
7
+
8
+ register_for :scheme
9
+ file_extension 'scm'
10
+
11
+ CORE_FORMS = %w[
12
+ lambda let let* letrec syntax-case define-syntax let-syntax
13
+ letrec-syntax begin define quote if or and cond case do delay
14
+ quasiquote set! cons force call-with-current-continuation call/cc
15
+ ]
16
+
17
+ IDENT_KIND = CaseIgnoringWordList.new(:ident).
18
+ add(CORE_FORMS, :reserved)
19
+
20
+ #IDENTIFIER_INITIAL = /[a-z!@\$%&\*\/\:<=>\?~_\^]/i
21
+ #IDENTIFIER_SUBSEQUENT = /#{IDENTIFIER_INITIAL}|\d|\.|\+|-/
22
+ #IDENTIFIER = /#{IDENTIFIER_INITIAL}#{IDENTIFIER_SUBSEQUENT}*|\+|-|\.{3}/
23
+ IDENTIFIER = /[a-zA-Z!@$%&*\/:<=>?~_^][\w!@$%&*\/:<=>?~^.+\-]*|[+-]|\.\.\./
24
+ DIGIT = /\d/
25
+ DIGIT10 = DIGIT
26
+ DIGIT16 = /[0-9a-f]/i
27
+ DIGIT8 = /[0-7]/
28
+ DIGIT2 = /[01]/
29
+ RADIX16 = /\#x/i
30
+ RADIX8 = /\#o/i
31
+ RADIX2 = /\#b/i
32
+ RADIX10 = /\#d/i
33
+ EXACTNESS = /#i|#e/i
34
+ SIGN = /[\+-]?/
35
+ EXP_MARK = /[esfdl]/i
36
+ EXP = /#{EXP_MARK}#{SIGN}#{DIGIT}+/
37
+ SUFFIX = /#{EXP}?/
38
+ PREFIX10 = /#{RADIX10}?#{EXACTNESS}?|#{EXACTNESS}?#{RADIX10}?/
39
+ PREFIX16 = /#{RADIX16}#{EXACTNESS}?|#{EXACTNESS}?#{RADIX16}/
40
+ PREFIX8 = /#{RADIX8}#{EXACTNESS}?|#{EXACTNESS}?#{RADIX8}/
41
+ PREFIX2 = /#{RADIX2}#{EXACTNESS}?|#{EXACTNESS}?#{RADIX2}/
42
+ UINT10 = /#{DIGIT10}+#*/
43
+ UINT16 = /#{DIGIT16}+#*/
44
+ UINT8 = /#{DIGIT8}+#*/
45
+ UINT2 = /#{DIGIT2}+#*/
46
+ DECIMAL = /#{DIGIT10}+#+\.#*#{SUFFIX}|#{DIGIT10}+\.#{DIGIT10}*#*#{SUFFIX}|\.#{DIGIT10}+#*#{SUFFIX}|#{UINT10}#{EXP}/
47
+ UREAL10 = /#{UINT10}\/#{UINT10}|#{DECIMAL}|#{UINT10}/
48
+ UREAL16 = /#{UINT16}\/#{UINT16}|#{UINT16}/
49
+ UREAL8 = /#{UINT8}\/#{UINT8}|#{UINT8}/
50
+ UREAL2 = /#{UINT2}\/#{UINT2}|#{UINT2}/
51
+ REAL10 = /#{SIGN}#{UREAL10}/
52
+ REAL16 = /#{SIGN}#{UREAL16}/
53
+ REAL8 = /#{SIGN}#{UREAL8}/
54
+ REAL2 = /#{SIGN}#{UREAL2}/
55
+ IMAG10 = /i|#{UREAL10}i/
56
+ IMAG16 = /i|#{UREAL16}i/
57
+ IMAG8 = /i|#{UREAL8}i/
58
+ IMAG2 = /i|#{UREAL2}i/
59
+ COMPLEX10 = /#{REAL10}@#{REAL10}|#{REAL10}\+#{IMAG10}|#{REAL10}-#{IMAG10}|\+#{IMAG10}|-#{IMAG10}|#{REAL10}/
60
+ COMPLEX16 = /#{REAL16}@#{REAL16}|#{REAL16}\+#{IMAG16}|#{REAL16}-#{IMAG16}|\+#{IMAG16}|-#{IMAG16}|#{REAL16}/
61
+ COMPLEX8 = /#{REAL8}@#{REAL8}|#{REAL8}\+#{IMAG8}|#{REAL8}-#{IMAG8}|\+#{IMAG8}|-#{IMAG8}|#{REAL8}/
62
+ COMPLEX2 = /#{REAL2}@#{REAL2}|#{REAL2}\+#{IMAG2}|#{REAL2}-#{IMAG2}|\+#{IMAG2}|-#{IMAG2}|#{REAL2}/
63
+ NUM10 = /#{PREFIX10}?#{COMPLEX10}/
64
+ NUM16 = /#{PREFIX16}#{COMPLEX16}/
65
+ NUM8 = /#{PREFIX8}#{COMPLEX8}/
66
+ NUM2 = /#{PREFIX2}#{COMPLEX2}/
67
+ NUM = /#{NUM10}|#{NUM16}|#{NUM8}|#{NUM2}/
68
+
69
+ private
70
+ def scan_tokens tokens,options
71
+
72
+ state = :initial
73
+ ident_kind = IDENT_KIND
74
+
75
+ until eos?
76
+ kind = match = nil
77
+
78
+ case state
79
+ when :initial
80
+ if scan(/ \s+ | \\\n /x)
81
+ kind = :space
82
+ elsif scan(/['\(\[\)\]]|#\(/)
83
+ kind = :operator_fat
84
+ elsif scan(/;.*/)
85
+ kind = :comment
86
+ elsif scan(/#\\(?:newline|space|.?)/)
87
+ kind = :char
88
+ elsif scan(/#[ft]/)
89
+ kind = :pre_constant
90
+ elsif scan(/#{IDENTIFIER}/o)
91
+ kind = ident_kind[matched]
92
+ elsif scan(/\./)
93
+ kind = :operator
94
+ elsif scan(/"/)
95
+ tokens << [:open, :string]
96
+ state = :string
97
+ tokens << ['"', :delimiter]
98
+ next
99
+ elsif scan(/#{NUM}/o) and not matched.empty?
100
+ kind = :integer
101
+ elsif getch
102
+ kind = :error
103
+ end
104
+
105
+ when :string
106
+ if scan(/[^"\\]+/) or scan(/\\.?/)
107
+ kind = :content
108
+ elsif scan(/"/)
109
+ tokens << ['"', :delimiter]
110
+ tokens << [:close, :string]
111
+ state = :initial
112
+ next
113
+ else
114
+ raise_inspect "else case \" reached; %p not handled." % peek(1),
115
+ tokens, state
116
+ end
117
+
118
+ else
119
+ raise "else case reached"
120
+ end
121
+
122
+ match ||= matched
123
+ if $DEBUG and not kind
124
+ raise_inspect 'Error token %p in line %d' %
125
+ [[match, kind], line], tokens
126
+ end
127
+ raise_inspect 'Empty token', tokens, state unless match
128
+
129
+ tokens << [match, kind]
130
+
131
+ end # until eos
132
+
133
+ if state == :string
134
+ tokens << [:close, :string]
135
+ end
136
+
137
+ tokens
138
+
139
+ end #scan_tokens
140
+ end #class
141
+ end #module scanners
142
+ end #module coderay