rugments 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +52 -0
  3. data/README.md +195 -0
  4. data/bin/rugmentize +6 -0
  5. data/lib/rugments/cli.rb +357 -0
  6. data/lib/rugments/formatter.rb +29 -0
  7. data/lib/rugments/formatters/html.rb +142 -0
  8. data/lib/rugments/formatters/null.rb +17 -0
  9. data/lib/rugments/formatters/terminal256.rb +174 -0
  10. data/lib/rugments/lexer.rb +431 -0
  11. data/lib/rugments/lexers/apache/keywords.yml +453 -0
  12. data/lib/rugments/lexers/apache.rb +67 -0
  13. data/lib/rugments/lexers/apple_script.rb +366 -0
  14. data/lib/rugments/lexers/c.rb +210 -0
  15. data/lib/rugments/lexers/clojure.rb +109 -0
  16. data/lib/rugments/lexers/coffeescript.rb +172 -0
  17. data/lib/rugments/lexers/common_lisp.rb +343 -0
  18. data/lib/rugments/lexers/conf.rb +22 -0
  19. data/lib/rugments/lexers/cpp.rb +63 -0
  20. data/lib/rugments/lexers/csharp.rb +85 -0
  21. data/lib/rugments/lexers/css.rb +269 -0
  22. data/lib/rugments/lexers/dart.rb +102 -0
  23. data/lib/rugments/lexers/diff.rb +39 -0
  24. data/lib/rugments/lexers/elixir.rb +105 -0
  25. data/lib/rugments/lexers/erb.rb +54 -0
  26. data/lib/rugments/lexers/erlang.rb +116 -0
  27. data/lib/rugments/lexers/factor.rb +300 -0
  28. data/lib/rugments/lexers/gherkin/keywords.rb +13 -0
  29. data/lib/rugments/lexers/gherkin.rb +135 -0
  30. data/lib/rugments/lexers/go.rb +176 -0
  31. data/lib/rugments/lexers/groovy.rb +102 -0
  32. data/lib/rugments/lexers/haml.rb +226 -0
  33. data/lib/rugments/lexers/handlebars.rb +77 -0
  34. data/lib/rugments/lexers/haskell.rb +181 -0
  35. data/lib/rugments/lexers/html.rb +92 -0
  36. data/lib/rugments/lexers/http.rb +78 -0
  37. data/lib/rugments/lexers/ini.rb +55 -0
  38. data/lib/rugments/lexers/io.rb +66 -0
  39. data/lib/rugments/lexers/java.rb +74 -0
  40. data/lib/rugments/lexers/javascript.rb +258 -0
  41. data/lib/rugments/lexers/literate_coffeescript.rb +31 -0
  42. data/lib/rugments/lexers/literate_haskell.rb +34 -0
  43. data/lib/rugments/lexers/llvm.rb +82 -0
  44. data/lib/rugments/lexers/lua/builtins.rb +21 -0
  45. data/lib/rugments/lexers/lua.rb +120 -0
  46. data/lib/rugments/lexers/make.rb +114 -0
  47. data/lib/rugments/lexers/markdown.rb +151 -0
  48. data/lib/rugments/lexers/matlab/builtins.rb +10 -0
  49. data/lib/rugments/lexers/matlab.rb +70 -0
  50. data/lib/rugments/lexers/moonscript.rb +108 -0
  51. data/lib/rugments/lexers/nginx.rb +69 -0
  52. data/lib/rugments/lexers/nim.rb +149 -0
  53. data/lib/rugments/lexers/objective_c.rb +188 -0
  54. data/lib/rugments/lexers/ocaml.rb +109 -0
  55. data/lib/rugments/lexers/perl.rb +195 -0
  56. data/lib/rugments/lexers/php/builtins.rb +192 -0
  57. data/lib/rugments/lexers/php.rb +162 -0
  58. data/lib/rugments/lexers/plain_text.rb +23 -0
  59. data/lib/rugments/lexers/prolog.rb +62 -0
  60. data/lib/rugments/lexers/properties.rb +53 -0
  61. data/lib/rugments/lexers/puppet.rb +126 -0
  62. data/lib/rugments/lexers/python.rb +225 -0
  63. data/lib/rugments/lexers/qml.rb +70 -0
  64. data/lib/rugments/lexers/r.rb +55 -0
  65. data/lib/rugments/lexers/racket.rb +540 -0
  66. data/lib/rugments/lexers/ruby.rb +413 -0
  67. data/lib/rugments/lexers/rust.rb +188 -0
  68. data/lib/rugments/lexers/sass/common.rb +172 -0
  69. data/lib/rugments/lexers/sass.rb +72 -0
  70. data/lib/rugments/lexers/scala.rb +140 -0
  71. data/lib/rugments/lexers/scheme.rb +109 -0
  72. data/lib/rugments/lexers/scss.rb +32 -0
  73. data/lib/rugments/lexers/sed.rb +167 -0
  74. data/lib/rugments/lexers/shell.rb +150 -0
  75. data/lib/rugments/lexers/slim.rb +222 -0
  76. data/lib/rugments/lexers/smalltalk.rb +114 -0
  77. data/lib/rugments/lexers/sml.rb +345 -0
  78. data/lib/rugments/lexers/sql.rb +138 -0
  79. data/lib/rugments/lexers/swift.rb +153 -0
  80. data/lib/rugments/lexers/tcl.rb +189 -0
  81. data/lib/rugments/lexers/tex.rb +70 -0
  82. data/lib/rugments/lexers/toml.rb +68 -0
  83. data/lib/rugments/lexers/vb.rb +162 -0
  84. data/lib/rugments/lexers/viml/keywords.rb +11 -0
  85. data/lib/rugments/lexers/viml.rb +99 -0
  86. data/lib/rugments/lexers/xml.rb +57 -0
  87. data/lib/rugments/lexers/yaml.rb +362 -0
  88. data/lib/rugments/plugins/redcarpet.rb +28 -0
  89. data/lib/rugments/regex_lexer.rb +432 -0
  90. data/lib/rugments/template_lexer.rb +23 -0
  91. data/lib/rugments/text_analyzer.rb +46 -0
  92. data/lib/rugments/theme.rb +202 -0
  93. data/lib/rugments/themes/base16.rb +128 -0
  94. data/lib/rugments/themes/colorful.rb +65 -0
  95. data/lib/rugments/themes/github.rb +69 -0
  96. data/lib/rugments/themes/monokai.rb +88 -0
  97. data/lib/rugments/themes/monokai_sublime.rb +89 -0
  98. data/lib/rugments/themes/thankful_eyes.rb +69 -0
  99. data/lib/rugments/token.rb +180 -0
  100. data/lib/rugments/util.rb +99 -0
  101. data/lib/rugments/version.rb +3 -0
  102. data/lib/rugments.rb +33 -0
  103. metadata +149 -0
@@ -0,0 +1,413 @@
1
+ module Rugments
2
+ module Lexers
3
+ class Ruby < RegexLexer
4
+ title 'Ruby'
5
+ desc 'The Ruby programming language (ruby-lang.org)'
6
+ tag 'ruby'
7
+ aliases 'rb'
8
+ filenames '*.rb', '*.ruby', '*.rbw', '*.rake', '*.gemspec', '*.podspec',
9
+ 'Rakefile', 'Guardfile', 'Gemfile', 'Capfile', 'Podfile',
10
+ 'Vagrantfile', '*.ru', '*.prawn'
11
+
12
+ mimetypes 'text/x-ruby', 'application/x-ruby'
13
+
14
+ def self.analyze_text(text)
15
+ return 1 if text.shebang? 'ruby'
16
+ end
17
+
18
+ state :symbols do
19
+ # symbols
20
+ rule %r(
21
+ : # initial :
22
+ @{0,2} # optional ivar, for :@foo and :@@foo
23
+ [a-z_]\w*[!?]? # the symbol
24
+ )xi, Str::Symbol
25
+
26
+ # special symbols
27
+ rule %r{:(?:\*\*|[-+]@|[/\%&\|^`~]|\[\]=?|<<|>>|<=?>|<=?|===?)},
28
+ Str::Symbol
29
+
30
+ rule /:'(\\\\|\\'|[^'])*'/, Str::Symbol
31
+ rule /:"/, Str::Symbol, :simple_sym
32
+ end
33
+
34
+ state :sigil_strings do
35
+ # %-sigiled strings
36
+ # %(abc), %[abc], %<abc>, %.abc., %r.abc., etc
37
+ delimiter_map = { '{' => '}', '[' => ']', '(' => ')', '<' => '>' }
38
+ rule /%([rqswQWxiI])?([^\w\s])/ do |m|
39
+ open = Regexp.escape(m[2])
40
+ close = Regexp.escape(delimiter_map[m[2]] || m[2])
41
+ interp = /[rQWxI]/ === m[1]
42
+ toktype = Str::Other
43
+
44
+ puts " open: #{open.inspect}" if @debug
45
+ puts " close: #{close.inspect}" if @debug
46
+
47
+ # regexes
48
+ if m[1] == 'r'
49
+ toktype = Str::Regex
50
+ push :regex_flags
51
+ end
52
+
53
+ token toktype
54
+
55
+ push do
56
+ rule /\\[##{open}#{close}\\]/, Str::Escape
57
+ # nesting rules only with asymmetric delimiters
58
+ if open != close
59
+ rule /#{open}/ do
60
+ token toktype
61
+ push
62
+ end
63
+ end
64
+ rule /#{close}/, toktype, :pop!
65
+
66
+ if interp
67
+ mixin :string_intp_escaped
68
+ rule /#/, toktype
69
+ else
70
+ rule /[\\#]/, toktype
71
+ end
72
+
73
+ rule /[^##{open}#{close}\\]+/m, toktype
74
+ end
75
+ end
76
+ end
77
+
78
+ state :strings do
79
+ mixin :symbols
80
+ rule /\b[a-z_]\w*?:\s+/, Str::Symbol, :expr_start
81
+ rule /'(\\\\|\\'|[^'])*'/, Str::Single
82
+ rule /"/, Str::Double, :simple_string
83
+ rule /(?<!\.)`/, Str::Backtick, :simple_backtick
84
+ end
85
+
86
+ state :regex_flags do
87
+ rule /[mixounse]*/, Str::Regex, :pop!
88
+ end
89
+
90
+ # double-quoted string and symbol
91
+ [[:string, Str::Double, '"'],
92
+ [:sym, Str::Symbol, '"'],
93
+ [:backtick, Str::Backtick, '`']].each do |name, tok, fin|
94
+ state :"simple_#{name}" do
95
+ mixin :string_intp_escaped
96
+ rule /[^\\#{fin}#]+/m, tok
97
+ rule /[\\#]/, tok
98
+ rule /#{fin}/, tok, :pop!
99
+ end
100
+ end
101
+
102
+ keywords = %w(
103
+ BEGIN END alias begin break case defined\? do else elsif end
104
+ ensure for if in next redo rescue raise retry return super then
105
+ undef unless until when while yield
106
+ )
107
+
108
+ keywords_pseudo = %w(
109
+ initialize new loop include extend raise attr_reader attr_writer
110
+ attr_accessor attr catch throw private module_function public
111
+ protected true false nil __FILE__ __LINE__
112
+ )
113
+
114
+ builtins_g = %w(
115
+ __id__ __send__ abort ancestors at_exit autoload binding callcc
116
+ caller catch chomp chop class_eval class_variables clone
117
+ const_defined\? const_get const_missing const_set constants
118
+ display dup eval exec exit extend fail fork format freeze
119
+ getc gets global_variables gsub hash id included_modules
120
+ inspect instance_eval instance_method instance_methods
121
+ instance_variable_get instance_variable_set instance_variables
122
+ lambda load local_variables loop method method_missing
123
+ methods module_eval name object_id open p print printf
124
+ private_class_method private_instance_methods private_methods proc
125
+ protected_instance_methods protected_methods public_class_method
126
+ public_instance_methods public_methods putc puts raise rand
127
+ readline readlines require require_relative scan select self send set_trace_func
128
+ singleton_methods sleep split sprintf srand sub syscall system
129
+ taint test throw to_a to_s trace_var trap untaint untrace_var warn
130
+ )
131
+
132
+ builtins_q = %w(
133
+ autoload block_given const_defined eql equal frozen
134
+ include instance_of is_a iterator kind_of method_defined
135
+ nil private_method_defined protected_method_defined
136
+ public_method_defined respond_to tainted
137
+ )
138
+
139
+ builtins_b = %w(chomp chop exit gsub sub)
140
+
141
+ start do
142
+ push :expr_start
143
+ @heredoc_queue = []
144
+ end
145
+
146
+ state :whitespace do
147
+ mixin :inline_whitespace
148
+ rule /\n\s*/m, Text, :expr_start
149
+ rule /#.*$/, Comment::Single
150
+
151
+ rule %r{=begin\b.*?end\b}m, Comment::Multiline
152
+ end
153
+
154
+ state :inline_whitespace do
155
+ rule /[ \t\r]+/, Text
156
+ end
157
+
158
+ state :root do
159
+ mixin :whitespace
160
+ rule /__END__/, Comment::Preproc, :end_part
161
+
162
+ rule /0_?[0-7]+(?:_[0-7]+)*/, Num::Oct
163
+ rule /0x[0-9A-Fa-f]+(?:_[0-9A-Fa-f]+)*/, Num::Hex
164
+ rule /0b[01]+(?:_[01]+)*/, Num::Bin
165
+ rule /[\d]+(?:_\d+)*/, Num::Integer
166
+
167
+ # names
168
+ rule /@@[a-z_]\w*/i, Name::Variable::Class
169
+ rule /@[a-z_]\w*/i, Name::Variable::Instance
170
+ rule /\$\w+/, Name::Variable::Global
171
+ rule %r{\$[!@&`'+~=/\\,;.<>_*\$?:"]}, Name::Variable::Global
172
+ rule /\$-[0adFiIlpvw]/, Name::Variable::Global
173
+ rule /::/, Operator
174
+
175
+ mixin :strings
176
+
177
+ rule /(?:#{keywords.join('|')})\b/, Keyword, :expr_start
178
+ rule /(?:#{keywords_pseudo.join('|')})\b/, Keyword::Pseudo, :expr_start
179
+
180
+ rule %r{
181
+ (module)
182
+ (\s+)
183
+ ([a-zA-Z_][a-zA-Z0-9_]*(::[a-zA-Z_][a-zA-Z0-9_]*)*)
184
+ }x do
185
+ groups Keyword, Text, Name::Namespace
186
+ end
187
+
188
+ rule /(def\b)(\s*)/ do
189
+ groups Keyword, Text
190
+ push :funcname
191
+ end
192
+
193
+ rule /(class\b)(\s*)/ do
194
+ groups Keyword, Text
195
+ push :classname
196
+ end
197
+
198
+ rule /(?:#{builtins_q.join('|')})[?]/, Name::Builtin, :expr_start
199
+ rule /(?:#{builtins_b.join('|')})!/, Name::Builtin, :expr_start
200
+ rule /(?<!\.)(?:#{builtins_g.join('|')})\b/,
201
+ Name::Builtin, :method_call
202
+
203
+ # char operator. ?x evaulates to "x", unless there's a digit
204
+ # beforehand like x>=0?n[x]:""
205
+ rule %r(
206
+ [?](\\[MC]-)* # modifiers
207
+ (\\([\\abefnrstv\#"']|x[a-fA-F0-9]{1,2}|[0-7]{1,3})|\S)
208
+ (?!\w)
209
+ )x, Str::Char
210
+
211
+ mixin :has_heredocs
212
+
213
+ rule /[A-Z][a-zA-Z0-9_]*/, Name::Constant, :method_call
214
+ rule /(\.|::)(\s*)([a-z_]\w*[!?]?|[*%&^`~+-\/\[<>=])/ do
215
+ groups Punctuation, Text, Name::Function
216
+ push :expr_start
217
+ end
218
+
219
+ rule /[a-zA-Z_]\w*[?!]/, Name, :expr_start
220
+ rule /[a-zA-Z_]\w*/, Name, :method_call
221
+ rule /\*\*|<<?|>>?|>=|<=|<=>|=~|={3}|!~|&&?|\|\||\.{1,3}/,
222
+ Operator, :expr_start
223
+ rule /[-+\/*%=<>&!^|~]=?/, Operator, :expr_start
224
+ rule %r<[\[({,?:\\;/]>, Punctuation, :expr_start
225
+ rule %r<[\])}]>, Punctuation
226
+ end
227
+
228
+ state :has_heredocs do
229
+ rule /(?<!\w)(<<-?)(["`']?)([a-zA-Z_]\w*)(\2)/ do |m|
230
+ token Operator, m[1]
231
+ token Name::Constant, "#{m[2]}#{m[3]}#{m[4]}"
232
+ @heredoc_queue << [m[1] == '<<-', m[3]]
233
+ push :heredoc_queue unless state? :heredoc_queue
234
+ end
235
+
236
+ rule /(<<-?)(["'])(\2)/ do |m|
237
+ token Operator, m[1]
238
+ token Name::Constant, "#{m[2]}#{m[3]}#{m[4]}"
239
+ @heredoc_queue << [m[1] == '<<-', '']
240
+ push :heredoc_queue unless state? :heredoc_queue
241
+ end
242
+ end
243
+
244
+ state :heredoc_queue do
245
+ rule /(?=\n)/ do
246
+ goto :resolve_heredocs
247
+ end
248
+
249
+ mixin :root
250
+ end
251
+
252
+ state :resolve_heredocs do
253
+ mixin :string_intp_escaped
254
+
255
+ rule /(\n)([^#\\\n]*)$/ do |m|
256
+ tolerant, heredoc_name = @heredoc_queue.first
257
+ check = tolerant ? m[2].strip : m[2].rstrip
258
+
259
+ # check if we found the end of the heredoc
260
+ line_tok = if check == heredoc_name
261
+ @heredoc_queue.shift
262
+ # if there's no more, we're done looking.
263
+ pop! if @heredoc_queue.empty?
264
+ Name::Constant
265
+ else
266
+ Str::Heredoc
267
+ end
268
+
269
+ groups(Str::Heredoc, line_tok)
270
+ end
271
+
272
+ rule /[#\\\n]/, Str::Heredoc
273
+ rule /[^#\\\n]+/, Str::Heredoc
274
+ end
275
+
276
+ state :funcname do
277
+ rule /\s+/, Text
278
+ rule /\(/, Punctuation, :defexpr
279
+ rule %r{
280
+ (?:([a-zA-Z_][\w_]*)(\.))?
281
+ (
282
+ [a-zA-Z_][\w_]*[!?]? |
283
+ \*\*? | [-+]@? | [/%&\|^`~] | \[\]=? |
284
+ <<? | >>? | <=>? | >= | ===?
285
+ )
286
+ }x do |m|
287
+ puts "matches: #{[m[0], m[1], m[2], m[3]].inspect}" if @debug
288
+ groups Name::Class, Operator, Name::Function
289
+ pop!
290
+ end
291
+
292
+ rule(//) { pop! }
293
+ end
294
+
295
+ state :classname do
296
+ rule /\s+/, Text
297
+ rule /\(/ do
298
+ token Punctuation
299
+ push :defexpr
300
+ push :expr_start
301
+ end
302
+
303
+ # class << expr
304
+ rule /<</ do
305
+ token Operator
306
+ goto :expr_start
307
+ end
308
+
309
+ rule /[A-Z_]\w*/, Name::Class
310
+
311
+ rule(//) { pop! }
312
+ end
313
+
314
+ state :defexpr do
315
+ rule /(\))(\.|::)?/ do
316
+ groups Punctuation, Operator
317
+ pop!
318
+ end
319
+ rule /\(/ do
320
+ token Punctuation
321
+ push :defexpr
322
+ push :expr_start
323
+ end
324
+
325
+ mixin :root
326
+ end
327
+
328
+ state :in_interp do
329
+ rule /}/, Str::Interpol, :pop!
330
+ mixin :root
331
+ end
332
+
333
+ state :string_intp do
334
+ rule /[#][{]/, Str::Interpol, :in_interp
335
+ rule /#(@@?|\$)[a-z_]\w*/i, Str::Interpol
336
+ end
337
+
338
+ state :string_intp_escaped do
339
+ mixin :string_intp
340
+ rule /\\([\\abefnrstv#"']|x[a-fA-F0-9]{1,2}|[0-7]{1,3})/,
341
+ Str::Escape
342
+ rule /\\./, Str::Escape
343
+ end
344
+
345
+ state :method_call do
346
+ rule %r{/} do
347
+ token Operator
348
+ goto :expr_start
349
+ end
350
+
351
+ rule(//) { goto :method_call_spaced }
352
+ end
353
+
354
+ state :method_call_spaced do
355
+ mixin :whitespace
356
+
357
+ rule %r{[%/]=} do
358
+ token Operator
359
+ goto :expr_start
360
+ end
361
+
362
+ rule %r{(/)(?=\S|\s*/)} do
363
+ token Str::Regex
364
+ goto :slash_regex
365
+ end
366
+
367
+ mixin :sigil_strings
368
+
369
+ rule(%r{(?=\s*/)}) { pop! }
370
+
371
+ rule(/\s+/) { token Text; goto :expr_start }
372
+ rule(//) { pop! }
373
+ end
374
+
375
+ state :expr_start do
376
+ mixin :inline_whitespace
377
+
378
+ rule %r{/} do
379
+ token Str::Regex
380
+ goto :slash_regex
381
+ end
382
+
383
+ # special case for using a single space. Ruby demands that
384
+ # these be in a single line, otherwise it would make no sense.
385
+ rule /(\s*)(%[rqswQWxiI]? \S* )/ do
386
+ groups Text, Str::Other
387
+ pop!
388
+ end
389
+
390
+ mixin :sigil_strings
391
+
392
+ rule(//) { pop! }
393
+ end
394
+
395
+ state :slash_regex do
396
+ mixin :string_intp
397
+ rule %r{\\\\}, Str::Regex
398
+ rule %r{\\/}, Str::Regex
399
+ rule %r{[\\#]}, Str::Regex
400
+ rule %r{[^\\/#]+}m, Str::Regex
401
+ rule %r{/} do
402
+ token Str::Regex
403
+ goto :regex_flags
404
+ end
405
+ end
406
+
407
+ state :end_part do
408
+ # eat up the rest of the stream as Comment::Preproc
409
+ rule /.+/m, Comment::Preproc, :pop!
410
+ end
411
+ end
412
+ end
413
+ end
@@ -0,0 +1,188 @@
1
+ module Rugments
2
+ module Lexers
3
+ class Rust < RegexLexer
4
+ title 'Rust'
5
+ desc 'The Rust programming language (rust-lang.org)'
6
+ tag 'rust'
7
+ aliases 'rs'
8
+ # TODO: *.rc conflicts with the rc shell...
9
+ filenames '*.rs', '*.rc'
10
+ mimetypes 'text/x-rust'
11
+
12
+ def self.analyze_text(text)
13
+ return 1 if text.shebang? 'rustc'
14
+ end
15
+
16
+ def self.keywords
17
+ @keywords ||= %w(
18
+ as assert break const copy do drop else enum extern fail false
19
+ fn for if impl let log loop match mod move mut priv pub pure
20
+ ref return self static struct true trait type unsafe use while
21
+ box
22
+ )
23
+ end
24
+
25
+ def self.builtins
26
+ @builtins ||= Set.new %w(
27
+ Add BitAnd BitOr BitXor bool c_char c_double c_float char
28
+ c_int clock_t c_long c_longlong Cons Const Copy c_schar c_short
29
+ c_uchar c_uint c_ulong c_ulonglong c_ushort c_void dev_t DIR
30
+ dirent Div Either Eq Err f32 f64 Failure FILE float fpos_t
31
+ i16 i32 i64 i8 Index ino_t int intptr_t Left mode_t Modulo Mul
32
+ Neg Nil None Num off_t Ok Option Ord Owned pid_t Ptr ptrdiff_t
33
+ Right Send Shl Shr size_t Some ssize_t str Sub Success time_t
34
+ u16 u32 u64 u8 uint uintptr_t
35
+ Box Vec String Gc Rc Arc
36
+ )
37
+ end
38
+
39
+ def macro_closed?
40
+ @macro_delims.values.all?(&:zero?)
41
+ end
42
+
43
+ start do
44
+ @macro_delims = { ']' => 0, ')' => 0, '}' => 0 }
45
+ end
46
+
47
+ delim_map = { '[' => ']', '(' => ')', '{' => '}' }
48
+
49
+ id = /[a-z_]\w*/i
50
+ hex = /[0-9a-f]/i
51
+ escapes = %r(
52
+ \\ ([nrt'\\] | x#{hex}{2} | u#{hex}{4} | U#{hex}{8})
53
+ )x
54
+ size = /8|16|32|64/
55
+
56
+ state :start_line do
57
+ mixin :whitespace
58
+ rule /\s+/, Text
59
+ rule /#\[/ do
60
+ token Comment::Preproc; push :attribute
61
+ end
62
+ rule(//) { pop! }
63
+ end
64
+
65
+ state :attribute do
66
+ mixin :whitespace
67
+ mixin :has_literals
68
+ rule /[(,)=]/, Comment::Preproc
69
+ rule /\]/, Comment::Preproc, :pop!
70
+ rule id, Comment::Preproc
71
+ end
72
+
73
+ state :whitespace do
74
+ rule /\s+/, Text
75
+ rule %r{//[^\n]*}, Comment
76
+ rule %r{/[*].*?[*]/}m, Comment::Multiline
77
+ end
78
+
79
+ state :root do
80
+ rule /\n/, Text, :start_line
81
+ mixin :whitespace
82
+ rule /\b(?:#{Rust.keywords.join('|')})\b/, Keyword
83
+ mixin :has_literals
84
+
85
+ rule %r{[=-]>}, Keyword
86
+ rule %r{<->}, Keyword
87
+ rule /[()\[\]{}|,:;]/, Punctuation
88
+ rule /[*!@~&+%^<>=-]/, Operator
89
+
90
+ rule /([.]\s*)?#{id}(?=\s*[(])/m, Name::Function
91
+ rule /[.]\s*#{id}/, Name::Property
92
+ rule /(#{id})(::)/m do
93
+ groups Name::Namespace, Punctuation
94
+ end
95
+
96
+ # macros
97
+ rule /\bmacro_rules!/, Name::Decorator, :macro_rules
98
+ rule /#{id}!/, Name::Decorator, :macro
99
+
100
+ rule /#{id}/ do |m|
101
+ name = m[0]
102
+ if self.class.builtins.include? name
103
+ token Name::Builtin
104
+ else
105
+ token Name
106
+ end
107
+ end
108
+ end
109
+
110
+ state :macro do
111
+ mixin :has_literals
112
+
113
+ rule /[\[{(]/ do |m|
114
+ @macro_delims[delim_map[m[0]]] += 1
115
+ puts " macro_delims: #{@macro_delims.inspect}" if @debug
116
+ token Punctuation
117
+ end
118
+
119
+ rule /[\]})]/ do |m|
120
+ @macro_delims[m[0]] -= 1
121
+ puts " macro_delims: #{@macro_delims.inspect}" if @debug
122
+ pop! if macro_closed?
123
+ token Punctuation
124
+ end
125
+
126
+ # same as the rule in root, but don't push another macro state
127
+ rule /#{id}!/, Name::Decorator
128
+ mixin :root
129
+
130
+ # No syntax errors in macros
131
+ rule /./, Text
132
+ end
133
+
134
+ state :macro_rules do
135
+ rule /[$]#{id}(:#{id})?/, Name::Variable
136
+ rule /[$]/, Name::Variable
137
+
138
+ mixin :macro
139
+ end
140
+
141
+ state :has_literals do
142
+ # constants
143
+ rule /\b(?:true|false|nil)\b/, Keyword::Constant
144
+ # characters
145
+ rule %r{
146
+ ' (?: #{escapes} | [^\\] ) '
147
+ }x, Str::Char
148
+
149
+ rule /"/, Str, :string
150
+
151
+ # numbers
152
+ dot = /[.][0-9_]+/
153
+ exp = /e[-+]?[0-9_]+/
154
+ flt = /f32|f64/
155
+
156
+ rule %r{
157
+ [0-9]+
158
+ (#{dot} #{exp}? #{flt}?
159
+ |#{dot}? #{exp} #{flt}?
160
+ |#{dot}? #{exp}? #{flt}
161
+ )
162
+ }x, Num::Float
163
+
164
+ rule %r{
165
+ ( 0b[10_]+
166
+ | 0x[0-9a-fA-F-]+
167
+ | [0-9]+
168
+ ) (u#{size}?|i#{size})?
169
+ }x, Num::Integer
170
+ end
171
+
172
+ state :string do
173
+ rule /"/, Str, :pop!
174
+ rule escapes, Str::Escape
175
+ rule /%%/, Str::Interpol
176
+ rule %r{
177
+ %
178
+ ( [0-9]+ [$] )? # Parameter
179
+ [0#+-]* # Flag
180
+ ( [0-9]+ [$]? )? # Width
181
+ ( [.] [0-9]+ )? # Precision
182
+ [bcdfiostuxX?] # Type
183
+ }x, Str::Interpol
184
+ rule /[^%"\\]+/m, Str
185
+ end
186
+ end
187
+ end
188
+ end