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

1""" 

2 pygments.lexers.ruby 

3 ~~~~~~~~~~~~~~~~~~~~ 

4 

5 Lexers for Ruby and related languages. 

6 

7 :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. 

8 :license: BSD, see LICENSE for details. 

9""" 

10 

11import re 

12 

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 

18 

19__all__ = ['RubyLexer', 'RubyConsoleLexer', 'FancyLexer'] 

20 

21 

22RUBY_OPERATORS = ( 

23 '*', '**', '-', '+', '-@', '+@', '/', '%', '&', '|', '^', '`', '~', 

24 '[]', '[]=', '<<', '>>', '<', '<>', '<=>', '>', '>=', '==', '===' 

25) 

26 

27 

28class RubyLexer(ExtendedRegexLexer): 

29 """ 

30 For Ruby source code. 

31 """ 

32 

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'] 

39 

40 flags = re.DOTALL | re.MULTILINE 

41 

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 

45 

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 

51 

52 heredocstack = ctx.__dict__.setdefault('heredocstack', []) 

53 outermost = not bool(heredocstack) 

54 heredocstack.append((match.group(1) in ('<<-', '<<~'), match.group(3))) 

55 

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() 

64 

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[:] 

88 

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() 

97 

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() 

105 

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 ] 

119 

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 ] 

131 

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')) 

167 

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 ] 

189 

190 return states 

191 

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()) 

390 

391 def analyse_text(text): 

392 return shebang_matches(text, r'ruby(1\.\d)?') 

393 

394 

395class RubyConsoleLexer(Lexer): 

396 """ 

397 For Ruby interactive console (**irb**) output like: 

398 

399 .. sourcecode:: rbcon 

400 

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'] 

410 

411 _prompt_re = re.compile(r'irb\([a-zA-Z_]\w*\):\d{3}:\d+[>*"\'] ' 

412 r'|>> |\?> ') 

413 

414 def get_tokens_unprocessed(self, text): 

415 rblexer = RubyLexer(**self.options) 

416 

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)) 

437 

438 

439class FancyLexer(RegexLexer): 

440 """ 

441 Pygments Lexer For Fancy. 

442 

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. 

446 

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'] 

454 

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), 

471 

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'), 

479 

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 }