coderay 0.7.4.215 → 0.8.260
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.
- 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
|