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.
- data/LICENSE +421 -257
- data/README +24 -13
- data/bin/coderay +9 -4
- data/lib/coderay.rb +19 -17
- data/lib/coderay/duo.rb +67 -9
- data/lib/coderay/encoder.rb +18 -9
- data/lib/coderay/encoders/_map.rb +2 -1
- data/lib/coderay/encoders/debug.rb +14 -11
- data/lib/coderay/encoders/html.rb +44 -17
- data/lib/coderay/encoders/html/css.rb +13 -8
- data/lib/coderay/encoders/html/numerization.rb +8 -6
- data/lib/coderay/encoders/html/output.rb +3 -1
- data/lib/coderay/encoders/statistic.rb +2 -6
- data/lib/coderay/encoders/text.rb +2 -3
- data/lib/coderay/encoders/tokens.rb +3 -3
- data/lib/coderay/encoders/xml.rb +1 -2
- data/lib/coderay/for_redcloth.rb +72 -0
- data/lib/coderay/helpers/file_type.rb +38 -9
- data/lib/coderay/helpers/gzip_simple.rb +1 -0
- data/lib/coderay/helpers/plugin.rb +15 -8
- data/lib/coderay/helpers/word_list.rb +4 -0
- data/lib/coderay/scanner.rb +30 -13
- data/lib/coderay/scanners/_map.rb +1 -1
- data/lib/coderay/scanners/c.rb +3 -1
- data/lib/coderay/scanners/css.rb +181 -0
- data/lib/coderay/scanners/debug.rb +1 -0
- data/lib/coderay/scanners/delphi.rb +1 -0
- data/lib/coderay/scanners/diff.rb +104 -0
- data/lib/coderay/scanners/java.rb +179 -0
- data/lib/coderay/scanners/java/builtin_types.rb +419 -0
- data/lib/coderay/scanners/java_script.rb +187 -0
- data/lib/coderay/scanners/json.rb +106 -0
- data/lib/coderay/scanners/nitro_xhtml.rb +5 -4
- data/lib/coderay/scanners/plaintext.rb +2 -0
- data/lib/coderay/scanners/rhtml.rb +2 -2
- data/lib/coderay/scanners/ruby.rb +64 -50
- data/lib/coderay/scanners/ruby/patterns.rb +15 -19
- data/lib/coderay/scanners/scheme.rb +142 -0
- data/lib/coderay/scanners/sql.Keith.rb +143 -0
- data/lib/coderay/scanners/sql.rb +154 -0
- data/lib/coderay/scanners/xml.rb +1 -0
- data/lib/coderay/styles/cycnus.rb +30 -9
- data/lib/coderay/styles/murphy.rb +15 -2
- data/lib/coderay/{encoders/html/classes.rb → token_classes.rb} +14 -9
- data/lib/coderay/tokens.rb +33 -14
- data/lib/term/ansicolor.rb +220 -0
- 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, :
|
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, :
|
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, :
|
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, :
|
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)
|
@@ -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, :
|
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, :
|
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)
|
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(/
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
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
|
-
|
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
|
-
|
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
|
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(
|
214
|
-
|
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
|
-
|
334
|
-
|
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
|
-
| [
|
45
|
-
| [
|
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
|
-
| ===?
|
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}
|
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 = /
|
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
|
-
( ["'
|
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
|
-
#
|
129
|
+
# value_expected in method calls without parentheses.
|
133
130
|
VALUE_FOLLOWS = /
|
134
|
-
\
|
131
|
+
(?>[ \t\f\v]+)
|
135
132
|
(?:
|
136
133
|
[%\/][^\s=]
|
137
|
-
|
|
138
|
-
|
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
|