Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pygments/lexers/ruby.py: 43%
108 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
1"""
2 pygments.lexers.ruby
3 ~~~~~~~~~~~~~~~~~~~~
5 Lexers for Ruby and related languages.
7 :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9"""
11import re
13from pygments.lexer import Lexer, RegexLexer, ExtendedRegexLexer, include, \
14 bygroups, default, LexerContext, do_insertions, words, line_re
15from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
16 Number, Punctuation, Error, Generic, Whitespace
17from pygments.util import shebang_matches
19__all__ = ['RubyLexer', 'RubyConsoleLexer', 'FancyLexer']
22RUBY_OPERATORS = (
23 '*', '**', '-', '+', '-@', '+@', '/', '%', '&', '|', '^', '`', '~',
24 '[]', '[]=', '<<', '>>', '<', '<>', '<=>', '>', '>=', '==', '==='
25)
28class RubyLexer(ExtendedRegexLexer):
29 """
30 For Ruby source code.
31 """
33 name = 'Ruby'
34 url = 'http://www.ruby-lang.org'
35 aliases = ['ruby', 'rb', 'duby']
36 filenames = ['*.rb', '*.rbw', 'Rakefile', '*.rake', '*.gemspec',
37 '*.rbx', '*.duby', 'Gemfile', 'Vagrantfile']
38 mimetypes = ['text/x-ruby', 'application/x-ruby']
40 flags = re.DOTALL | re.MULTILINE
42 def heredoc_callback(self, match, ctx):
43 # okay, this is the hardest part of parsing Ruby...
44 # match: 1 = <<[-~]?, 2 = quote? 3 = name 4 = quote? 5 = rest of line
46 start = match.start(1)
47 yield start, Operator, match.group(1) # <<[-~]?
48 yield match.start(2), String.Heredoc, match.group(2) # quote ", ', `
49 yield match.start(3), String.Delimiter, match.group(3) # heredoc name
50 yield match.start(4), String.Heredoc, match.group(4) # quote again
52 heredocstack = ctx.__dict__.setdefault('heredocstack', [])
53 outermost = not bool(heredocstack)
54 heredocstack.append((match.group(1) in ('<<-', '<<~'), match.group(3)))
56 ctx.pos = match.start(5)
57 ctx.end = match.end(5)
58 # this may find other heredocs, so limit the recursion depth
59 if len(heredocstack) < 100:
60 yield from self.get_tokens_unprocessed(context=ctx)
61 else:
62 yield ctx.pos, String.Heredoc, match.group(5)
63 ctx.pos = match.end()
65 if outermost:
66 # this is the outer heredoc again, now we can process them all
67 for tolerant, hdname in heredocstack:
68 lines = []
69 for match in line_re.finditer(ctx.text, ctx.pos):
70 if tolerant:
71 check = match.group().strip()
72 else:
73 check = match.group().rstrip()
74 if check == hdname:
75 for amatch in lines:
76 yield amatch.start(), String.Heredoc, amatch.group()
77 yield match.start(), String.Delimiter, match.group()
78 ctx.pos = match.end()
79 break
80 else:
81 lines.append(match)
82 else:
83 # end of heredoc not found -- error!
84 for amatch in lines:
85 yield amatch.start(), Error, amatch.group()
86 ctx.end = len(ctx.text)
87 del heredocstack[:]
89 def gen_rubystrings_rules():
90 def intp_regex_callback(self, match, ctx):
91 yield match.start(1), String.Regex, match.group(1) # begin
92 nctx = LexerContext(match.group(3), 0, ['interpolated-regex'])
93 for i, t, v in self.get_tokens_unprocessed(context=nctx):
94 yield match.start(3)+i, t, v
95 yield match.start(4), String.Regex, match.group(4) # end[mixounse]*
96 ctx.pos = match.end()
98 def intp_string_callback(self, match, ctx):
99 yield match.start(1), String.Other, match.group(1)
100 nctx = LexerContext(match.group(3), 0, ['interpolated-string'])
101 for i, t, v in self.get_tokens_unprocessed(context=nctx):
102 yield match.start(3)+i, t, v
103 yield match.start(4), String.Other, match.group(4) # end
104 ctx.pos = match.end()
106 states = {}
107 states['strings'] = [
108 # easy ones
109 (r'\:@{0,2}[a-zA-Z_]\w*[!?]?', String.Symbol),
110 (words(RUBY_OPERATORS, prefix=r'\:@{0,2}'), String.Symbol),
111 (r":'(\\\\|\\[^\\]|[^'\\])*'", String.Symbol),
112 (r':"', String.Symbol, 'simple-sym'),
113 (r'([a-zA-Z_]\w*)(:)(?!:)',
114 bygroups(String.Symbol, Punctuation)), # Since Ruby 1.9
115 (r'"', String.Double, 'simple-string-double'),
116 (r"'", String.Single, 'simple-string-single'),
117 (r'(?<!\.)`', String.Backtick, 'simple-backtick'),
118 ]
120 # quoted string and symbol
121 for name, ttype, end in ('string-double', String.Double, '"'), \
122 ('string-single', String.Single, "'"),\
123 ('sym', String.Symbol, '"'), \
124 ('backtick', String.Backtick, '`'):
125 states['simple-'+name] = [
126 include('string-intp-escaped'),
127 (r'[^\\%s#]+' % end, ttype),
128 (r'[\\#]', ttype),
129 (end, ttype, '#pop'),
130 ]
132 # braced quoted strings
133 for lbrace, rbrace, bracecc, name in \
134 ('\\{', '\\}', '{}', 'cb'), \
135 ('\\[', '\\]', '\\[\\]', 'sb'), \
136 ('\\(', '\\)', '()', 'pa'), \
137 ('<', '>', '<>', 'ab'):
138 states[name+'-intp-string'] = [
139 (r'\\[\\' + bracecc + ']', String.Other),
140 (lbrace, String.Other, '#push'),
141 (rbrace, String.Other, '#pop'),
142 include('string-intp-escaped'),
143 (r'[\\#' + bracecc + ']', String.Other),
144 (r'[^\\#' + bracecc + ']+', String.Other),
145 ]
146 states['strings'].append((r'%[QWx]?' + lbrace, String.Other,
147 name+'-intp-string'))
148 states[name+'-string'] = [
149 (r'\\[\\' + bracecc + ']', String.Other),
150 (lbrace, String.Other, '#push'),
151 (rbrace, String.Other, '#pop'),
152 (r'[\\#' + bracecc + ']', String.Other),
153 (r'[^\\#' + bracecc + ']+', String.Other),
154 ]
155 states['strings'].append((r'%[qsw]' + lbrace, String.Other,
156 name+'-string'))
157 states[name+'-regex'] = [
158 (r'\\[\\' + bracecc + ']', String.Regex),
159 (lbrace, String.Regex, '#push'),
160 (rbrace + '[mixounse]*', String.Regex, '#pop'),
161 include('string-intp'),
162 (r'[\\#' + bracecc + ']', String.Regex),
163 (r'[^\\#' + bracecc + ']+', String.Regex),
164 ]
165 states['strings'].append((r'%r' + lbrace, String.Regex,
166 name+'-regex'))
168 # these must come after %<brace>!
169 states['strings'] += [
170 # %r regex
171 (r'(%r([\W_]))((?:\\\2|(?!\2).)*)(\2[mixounse]*)',
172 intp_regex_callback),
173 # regular fancy strings with qsw
174 (r'%[qsw]([\W_])((?:\\\1|(?!\1).)*)\1', String.Other),
175 (r'(%[QWx]([\W_]))((?:\\\2|(?!\2).)*)(\2)',
176 intp_string_callback),
177 # special forms of fancy strings after operators or
178 # in method calls with braces
179 (r'(?<=[-+/*%=<>&!^|~,(])(\s*)(%([\t ])(?:(?:\\\3|(?!\3).)*)\3)',
180 bygroups(Whitespace, String.Other, None)),
181 # and because of fixed width lookbehinds the whole thing a
182 # second time for line startings...
183 (r'^(\s*)(%([\t ])(?:(?:\\\3|(?!\3).)*)\3)',
184 bygroups(Whitespace, String.Other, None)),
185 # all regular fancy strings without qsw
186 (r'(%([^a-zA-Z0-9\s]))((?:\\\2|(?!\2).)*)(\2)',
187 intp_string_callback),
188 ]
190 return states
192 tokens = {
193 'root': [
194 (r'\A#!.+?$', Comment.Hashbang),
195 (r'#.*?$', Comment.Single),
196 (r'=begin\s.*?\n=end.*?$', Comment.Multiline),
197 # keywords
198 (words((
199 'BEGIN', 'END', 'alias', 'begin', 'break', 'case', 'defined?',
200 'do', 'else', 'elsif', 'end', 'ensure', 'for', 'if', 'in', 'next', 'redo',
201 'rescue', 'raise', 'retry', 'return', 'super', 'then', 'undef',
202 'unless', 'until', 'when', 'while', 'yield'), suffix=r'\b'),
203 Keyword),
204 # start of function, class and module names
205 (r'(module)(\s+)([a-zA-Z_]\w*'
206 r'(?:::[a-zA-Z_]\w*)*)',
207 bygroups(Keyword, Whitespace, Name.Namespace)),
208 (r'(def)(\s+)', bygroups(Keyword, Whitespace), 'funcname'),
209 (r'def(?=[*%&^`~+-/\[<>=])', Keyword, 'funcname'),
210 (r'(class)(\s+)', bygroups(Keyword, Whitespace), 'classname'),
211 # special methods
212 (words((
213 'initialize', 'new', 'loop', 'include', 'extend', 'raise', 'attr_reader',
214 'attr_writer', 'attr_accessor', 'attr', 'catch', 'throw', 'private',
215 'module_function', 'public', 'protected', 'true', 'false', 'nil'),
216 suffix=r'\b'),
217 Keyword.Pseudo),
218 (r'(not|and|or)\b', Operator.Word),
219 (words((
220 'autoload', 'block_given', 'const_defined', 'eql', 'equal', 'frozen', 'include',
221 'instance_of', 'is_a', 'iterator', 'kind_of', 'method_defined', 'nil',
222 'private_method_defined', 'protected_method_defined',
223 'public_method_defined', 'respond_to', 'tainted'), suffix=r'\?'),
224 Name.Builtin),
225 (r'(chomp|chop|exit|gsub|sub)!', Name.Builtin),
226 (words((
227 'Array', 'Float', 'Integer', 'String', '__id__', '__send__', 'abort',
228 'ancestors', 'at_exit', 'autoload', 'binding', 'callcc', 'caller',
229 'catch', 'chomp', 'chop', 'class_eval', 'class_variables',
230 'clone', 'const_defined?', 'const_get', 'const_missing', 'const_set',
231 'constants', 'display', 'dup', 'eval', 'exec', 'exit', 'extend', 'fail', 'fork',
232 'format', 'freeze', 'getc', 'gets', 'global_variables', 'gsub',
233 'hash', 'id', 'included_modules', 'inspect', 'instance_eval',
234 'instance_method', 'instance_methods',
235 'instance_variable_get', 'instance_variable_set', 'instance_variables',
236 'lambda', 'load', 'local_variables', 'loop',
237 'method', 'method_missing', 'methods', 'module_eval', 'name',
238 'object_id', 'open', 'p', 'print', 'printf', 'private_class_method',
239 'private_instance_methods',
240 'private_methods', 'proc', 'protected_instance_methods',
241 'protected_methods', 'public_class_method',
242 'public_instance_methods', 'public_methods',
243 'putc', 'puts', 'raise', 'rand', 'readline', 'readlines', 'require',
244 'scan', 'select', 'self', 'send', 'set_trace_func', 'singleton_methods', 'sleep',
245 'split', 'sprintf', 'srand', 'sub', 'syscall', 'system', 'taint',
246 'test', 'throw', 'to_a', 'to_s', 'trace_var', 'trap', 'untaint',
247 'untrace_var', 'warn'), prefix=r'(?<!\.)', suffix=r'\b'),
248 Name.Builtin),
249 (r'__(FILE|LINE)__\b', Name.Builtin.Pseudo),
250 # normal heredocs
251 (r'(?<!\w)(<<[-~]?)(["`\']?)([a-zA-Z_]\w*)(\2)(.*?\n)',
252 heredoc_callback),
253 # empty string heredocs
254 (r'(<<[-~]?)("|\')()(\2)(.*?\n)', heredoc_callback),
255 (r'__END__', Comment.Preproc, 'end-part'),
256 # multiline regex (after keywords or assignments)
257 (r'(?:^|(?<=[=<>~!:])|'
258 r'(?<=(?:\s|;)when\s)|'
259 r'(?<=(?:\s|;)or\s)|'
260 r'(?<=(?:\s|;)and\s)|'
261 r'(?<=\.index\s)|'
262 r'(?<=\.scan\s)|'
263 r'(?<=\.sub\s)|'
264 r'(?<=\.sub!\s)|'
265 r'(?<=\.gsub\s)|'
266 r'(?<=\.gsub!\s)|'
267 r'(?<=\.match\s)|'
268 r'(?<=(?:\s|;)if\s)|'
269 r'(?<=(?:\s|;)elsif\s)|'
270 r'(?<=^when\s)|'
271 r'(?<=^index\s)|'
272 r'(?<=^scan\s)|'
273 r'(?<=^sub\s)|'
274 r'(?<=^gsub\s)|'
275 r'(?<=^sub!\s)|'
276 r'(?<=^gsub!\s)|'
277 r'(?<=^match\s)|'
278 r'(?<=^if\s)|'
279 r'(?<=^elsif\s)'
280 r')(\s*)(/)', bygroups(Text, String.Regex), 'multiline-regex'),
281 # multiline regex (in method calls or subscripts)
282 (r'(?<=\(|,|\[)/', String.Regex, 'multiline-regex'),
283 # multiline regex (this time the funny no whitespace rule)
284 (r'(\s+)(/)(?![\s=])', bygroups(Whitespace, String.Regex),
285 'multiline-regex'),
286 # lex numbers and ignore following regular expressions which
287 # are division operators in fact (grrrr. i hate that. any
288 # better ideas?)
289 # since pygments 0.7 we also eat a "?" operator after numbers
290 # so that the char operator does not work. Chars are not allowed
291 # there so that you can use the ternary operator.
292 # stupid example:
293 # x>=0?n[x]:""
294 (r'(0_?[0-7]+(?:_[0-7]+)*)(\s*)([/?])?',
295 bygroups(Number.Oct, Whitespace, Operator)),
296 (r'(0x[0-9A-Fa-f]+(?:_[0-9A-Fa-f]+)*)(\s*)([/?])?',
297 bygroups(Number.Hex, Whitespace, Operator)),
298 (r'(0b[01]+(?:_[01]+)*)(\s*)([/?])?',
299 bygroups(Number.Bin, Whitespace, Operator)),
300 (r'([\d]+(?:_\d+)*)(\s*)([/?])?',
301 bygroups(Number.Integer, Whitespace, Operator)),
302 # Names
303 (r'@@[a-zA-Z_]\w*', Name.Variable.Class),
304 (r'@[a-zA-Z_]\w*', Name.Variable.Instance),
305 (r'\$\w+', Name.Variable.Global),
306 (r'\$[!@&`\'+~=/\\,;.<>_*$?:"^-]', Name.Variable.Global),
307 (r'\$-[0adFiIlpvw]', Name.Variable.Global),
308 (r'::', Operator),
309 include('strings'),
310 # chars
311 (r'\?(\\[MC]-)*' # modifiers
312 r'(\\([\\abefnrstv#"\']|x[a-fA-F0-9]{1,2}|[0-7]{1,3})|\S)'
313 r'(?!\w)',
314 String.Char),
315 (r'[A-Z]\w+', Name.Constant),
316 # this is needed because ruby attributes can look
317 # like keywords (class) or like this: ` ?!?
318 (words(RUBY_OPERATORS, prefix=r'(\.|::)'),
319 bygroups(Operator, Name.Operator)),
320 (r'(\.|::)([a-zA-Z_]\w*[!?]?|[*%&^`~+\-/\[<>=])',
321 bygroups(Operator, Name)),
322 (r'[a-zA-Z_]\w*[!?]?', Name),
323 (r'(\[|\]|\*\*|<<?|>>?|>=|<=|<=>|=~|={3}|'
324 r'!~|&&?|\|\||\.{1,3})', Operator),
325 (r'[-+/*%=<>&!^|~]=?', Operator),
326 (r'[(){};,/?:\\]', Punctuation),
327 (r'\s+', Whitespace)
328 ],
329 'funcname': [
330 (r'\(', Punctuation, 'defexpr'),
331 (r'(?:([a-zA-Z_]\w*)(\.))?' # optional scope name, like "self."
332 r'('
333 r'[a-zA-Z\u0080-\uffff][a-zA-Z0-9_\u0080-\uffff]*[!?=]?' # method name
334 r'|!=|!~|=~|\*\*?|[-+!~]@?|[/%&|^]|<=>|<[<=]?|>[>=]?|===?' # or operator override
335 r'|\[\]=?' # or element reference/assignment override
336 r'|`' # or the undocumented backtick override
337 r')',
338 bygroups(Name.Class, Operator, Name.Function), '#pop'),
339 default('#pop')
340 ],
341 'classname': [
342 (r'\(', Punctuation, 'defexpr'),
343 (r'<<', Operator, '#pop'),
344 (r'[A-Z_]\w*', Name.Class, '#pop'),
345 default('#pop')
346 ],
347 'defexpr': [
348 (r'(\))(\.|::)?', bygroups(Punctuation, Operator), '#pop'),
349 (r'\(', Operator, '#push'),
350 include('root')
351 ],
352 'in-intp': [
353 (r'\{', String.Interpol, '#push'),
354 (r'\}', String.Interpol, '#pop'),
355 include('root'),
356 ],
357 'string-intp': [
358 (r'#\{', String.Interpol, 'in-intp'),
359 (r'#@@?[a-zA-Z_]\w*', String.Interpol),
360 (r'#\$[a-zA-Z_]\w*', String.Interpol)
361 ],
362 'string-intp-escaped': [
363 include('string-intp'),
364 (r'\\([\\abefnrstv#"\']|x[a-fA-F0-9]{1,2}|[0-7]{1,3})',
365 String.Escape)
366 ],
367 'interpolated-regex': [
368 include('string-intp'),
369 (r'[\\#]', String.Regex),
370 (r'[^\\#]+', String.Regex),
371 ],
372 'interpolated-string': [
373 include('string-intp'),
374 (r'[\\#]', String.Other),
375 (r'[^\\#]+', String.Other),
376 ],
377 'multiline-regex': [
378 include('string-intp'),
379 (r'\\\\', String.Regex),
380 (r'\\/', String.Regex),
381 (r'[\\#]', String.Regex),
382 (r'[^\\/#]+', String.Regex),
383 (r'/[mixounse]*', String.Regex, '#pop'),
384 ],
385 'end-part': [
386 (r'.+', Comment.Preproc, '#pop')
387 ]
388 }
389 tokens.update(gen_rubystrings_rules())
391 def analyse_text(text):
392 return shebang_matches(text, r'ruby(1\.\d)?')
395class RubyConsoleLexer(Lexer):
396 """
397 For Ruby interactive console (**irb**) output like:
399 .. sourcecode:: rbcon
401 irb(main):001:0> a = 1
402 => 1
403 irb(main):002:0> puts a
404 1
405 => nil
406 """
407 name = 'Ruby irb session'
408 aliases = ['rbcon', 'irb']
409 mimetypes = ['text/x-ruby-shellsession']
411 _prompt_re = re.compile(r'irb\([a-zA-Z_]\w*\):\d{3}:\d+[>*"\'] '
412 r'|>> |\?> ')
414 def get_tokens_unprocessed(self, text):
415 rblexer = RubyLexer(**self.options)
417 curcode = ''
418 insertions = []
419 for match in line_re.finditer(text):
420 line = match.group()
421 m = self._prompt_re.match(line)
422 if m is not None:
423 end = m.end()
424 insertions.append((len(curcode),
425 [(0, Generic.Prompt, line[:end])]))
426 curcode += line[end:]
427 else:
428 if curcode:
429 yield from do_insertions(
430 insertions, rblexer.get_tokens_unprocessed(curcode))
431 curcode = ''
432 insertions = []
433 yield match.start(), Generic.Output, line
434 if curcode:
435 yield from do_insertions(
436 insertions, rblexer.get_tokens_unprocessed(curcode))
439class FancyLexer(RegexLexer):
440 """
441 Pygments Lexer For Fancy.
443 Fancy is a self-hosted, pure object-oriented, dynamic,
444 class-based, concurrent general-purpose programming language
445 running on Rubinius, the Ruby VM.
447 .. versionadded:: 1.5
448 """
449 name = 'Fancy'
450 url = 'https://github.com/bakkdoor/fancy'
451 filenames = ['*.fy', '*.fancypack']
452 aliases = ['fancy', 'fy']
453 mimetypes = ['text/x-fancysrc']
455 tokens = {
456 # copied from PerlLexer:
457 'balanced-regex': [
458 (r'/(\\\\|\\[^\\]|[^/\\])*/[egimosx]*', String.Regex, '#pop'),
459 (r'!(\\\\|\\[^\\]|[^!\\])*![egimosx]*', String.Regex, '#pop'),
460 (r'\\(\\\\|[^\\])*\\[egimosx]*', String.Regex, '#pop'),
461 (r'\{(\\\\|\\[^\\]|[^}\\])*\}[egimosx]*', String.Regex, '#pop'),
462 (r'<(\\\\|\\[^\\]|[^>\\])*>[egimosx]*', String.Regex, '#pop'),
463 (r'\[(\\\\|\\[^\\]|[^\]\\])*\][egimosx]*', String.Regex, '#pop'),
464 (r'\((\\\\|\\[^\\]|[^)\\])*\)[egimosx]*', String.Regex, '#pop'),
465 (r'@(\\\\|\\[^\\]|[^@\\])*@[egimosx]*', String.Regex, '#pop'),
466 (r'%(\\\\|\\[^\\]|[^%\\])*%[egimosx]*', String.Regex, '#pop'),
467 (r'\$(\\\\|\\[^\\]|[^$\\])*\$[egimosx]*', String.Regex, '#pop'),
468 ],
469 'root': [
470 (r'\s+', Whitespace),
472 # balanced delimiters (copied from PerlLexer):
473 (r's\{(\\\\|\\[^\\]|[^}\\])*\}\s*', String.Regex, 'balanced-regex'),
474 (r's<(\\\\|\\[^\\]|[^>\\])*>\s*', String.Regex, 'balanced-regex'),
475 (r's\[(\\\\|\\[^\\]|[^\]\\])*\]\s*', String.Regex, 'balanced-regex'),
476 (r's\((\\\\|\\[^\\]|[^)\\])*\)\s*', String.Regex, 'balanced-regex'),
477 (r'm?/(\\\\|\\[^\\]|[^///\n])*/[gcimosx]*', String.Regex),
478 (r'm(?=[/!\\{<\[(@%$])', String.Regex, 'balanced-regex'),
480 # Comments
481 (r'#(.*?)\n', Comment.Single),
482 # Symbols
483 (r'\'([^\'\s\[\](){}]+|\[\])', String.Symbol),
484 # Multi-line DoubleQuotedString
485 (r'"""(\\\\|\\[^\\]|[^\\])*?"""', String),
486 # DoubleQuotedString
487 (r'"(\\\\|\\[^\\]|[^"\\])*"', String),
488 # keywords
489 (r'(def|class|try|catch|finally|retry|return|return_local|match|'
490 r'case|->|=>)\b', Keyword),
491 # constants
492 (r'(self|super|nil|false|true)\b', Name.Constant),
493 (r'[(){};,/?|:\\]', Punctuation),
494 # names
495 (words((
496 'Object', 'Array', 'Hash', 'Directory', 'File', 'Class', 'String',
497 'Number', 'Enumerable', 'FancyEnumerable', 'Block', 'TrueClass',
498 'NilClass', 'FalseClass', 'Tuple', 'Symbol', 'Stack', 'Set',
499 'FancySpec', 'Method', 'Package', 'Range'), suffix=r'\b'),
500 Name.Builtin),
501 # functions
502 (r'[a-zA-Z](\w|[-+?!=*/^><%])*:', Name.Function),
503 # operators, must be below functions
504 (r'[-+*/~,<>=&!?%^\[\].$]+', Operator),
505 (r'[A-Z]\w*', Name.Constant),
506 (r'@[a-zA-Z_]\w*', Name.Variable.Instance),
507 (r'@@[a-zA-Z_]\w*', Name.Variable.Class),
508 ('@@?', Operator),
509 (r'[a-zA-Z_]\w*', Name),
510 # numbers - / checks are necessary to avoid mismarking regexes,
511 # see comment in RubyLexer
512 (r'(0[oO]?[0-7]+(?:_[0-7]+)*)(\s*)([/?])?',
513 bygroups(Number.Oct, Whitespace, Operator)),
514 (r'(0[xX][0-9A-Fa-f]+(?:_[0-9A-Fa-f]+)*)(\s*)([/?])?',
515 bygroups(Number.Hex, Whitespace, Operator)),
516 (r'(0[bB][01]+(?:_[01]+)*)(\s*)([/?])?',
517 bygroups(Number.Bin, Whitespace, Operator)),
518 (r'([\d]+(?:_\d+)*)(\s*)([/?])?',
519 bygroups(Number.Integer, Whitespace, Operator)),
520 (r'\d+([eE][+-]?[0-9]+)|\d+\.\d+([eE][+-]?[0-9]+)?', Number.Float),
521 (r'\d+', Number.Integer)
522 ]
523 }