Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pygments/lexers/int_fiction.py: 72%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

151 statements  

1""" 

2 pygments.lexers.int_fiction 

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

4 

5 Lexers for interactive fiction languages. 

6 

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

8 :license: BSD, see LICENSE for details. 

9""" 

10 

11import re 

12 

13from pygments.lexer import RegexLexer, include, bygroups, using, \ 

14 this, default, words 

15from pygments.token import Text, Comment, Operator, Keyword, Name, String, \ 

16 Number, Punctuation, Error, Generic 

17 

18__all__ = ['Inform6Lexer', 'Inform6TemplateLexer', 'Inform7Lexer', 

19 'Tads3Lexer'] 

20 

21 

22class Inform6Lexer(RegexLexer): 

23 """ 

24 For Inform 6 source code. 

25 """ 

26 

27 name = 'Inform 6' 

28 url = 'http://inform-fiction.org/' 

29 aliases = ['inform6', 'i6'] 

30 filenames = ['*.inf'] 

31 version_added = '2.0' 

32 

33 flags = re.MULTILINE | re.DOTALL 

34 

35 _name = r'[a-zA-Z_]\w*' 

36 

37 # Inform 7 maps these four character classes to their ASCII 

38 # equivalents. To support Inform 6 inclusions within Inform 7, 

39 # Inform6Lexer maps them too. 

40 _dash = '\\-\u2010-\u2014' 

41 _dquote = '"\u201c\u201d' 

42 _squote = "'\u2018\u2019" 

43 _newline = '\\n\u0085\u2028\u2029' 

44 

45 tokens = { 

46 'root': [ 

47 (rf'\A(!%[^{_newline}]*[{_newline}])+', Comment.Preproc, 

48 'directive'), 

49 default('directive') 

50 ], 

51 '_whitespace': [ 

52 (r'\s+', Text), 

53 (rf'![^{_newline}]*', Comment.Single) 

54 ], 

55 'default': [ 

56 include('_whitespace'), 

57 (r'\[', Punctuation, 'many-values'), # Array initialization 

58 (r':|(?=;)', Punctuation, '#pop'), 

59 (r'<', Punctuation), # Second angle bracket in an action statement 

60 default(('expression', '_expression')) 

61 ], 

62 

63 # Expressions 

64 '_expression': [ 

65 include('_whitespace'), 

66 (r'(?=sp\b)', Text, '#pop'), 

67 (rf'(?=[{_dquote}{_squote}$0-9#a-zA-Z_])', Text, 

68 ('#pop', 'value')), 

69 (rf'\+\+|[{_dash}]{{1,2}}(?!>)|~~?', Operator), 

70 (rf'(?=[()\[{_dash},?@{{:;])', Text, '#pop') 

71 ], 

72 'expression': [ 

73 include('_whitespace'), 

74 (r'\(', Punctuation, ('expression', '_expression')), 

75 (r'\)', Punctuation, '#pop'), 

76 (r'\[', Punctuation, ('#pop', 'statements', 'locals')), 

77 (rf'>(?=(\s+|(![^{_newline}]*))*[>;])', Punctuation), 

78 (rf'\+\+|[{_dash}]{{2}}(?!>)', Operator), 

79 (r',', Punctuation, '_expression'), 

80 (rf'&&?|\|\|?|[=~><]?=|[{_dash}]{{1,2}}>?|\.\.?[&#]?|::|[<>+*/%]', 

81 Operator, '_expression'), 

82 (r'(has|hasnt|in|notin|ofclass|or|provides)\b', Operator.Word, 

83 '_expression'), 

84 (r'sp\b', Name), 

85 (r'\?~?', Name.Label, 'label?'), 

86 (r'[@{]', Error), 

87 default('#pop') 

88 ], 

89 '_assembly-expression': [ 

90 (r'\(', Punctuation, ('#push', '_expression')), 

91 (r'[\[\]]', Punctuation), 

92 (rf'[{_dash}]>', Punctuation, '_expression'), 

93 (r'sp\b', Keyword.Pseudo), 

94 (r';', Punctuation, '#pop:3'), 

95 include('expression') 

96 ], 

97 '_for-expression': [ 

98 (r'\)', Punctuation, '#pop:2'), 

99 (r':', Punctuation, '#pop'), 

100 include('expression') 

101 ], 

102 '_keyword-expression': [ 

103 (r'(from|near|to)\b', Keyword, '_expression'), 

104 include('expression') 

105 ], 

106 '_list-expression': [ 

107 (r',', Punctuation, '#pop'), 

108 include('expression') 

109 ], 

110 '_object-expression': [ 

111 (r'has\b', Keyword.Declaration, '#pop'), 

112 include('_list-expression') 

113 ], 

114 

115 # Values 

116 'value': [ 

117 include('_whitespace'), 

118 # Strings 

119 (rf'[{_squote}][^@][{_squote}]', String.Char, '#pop'), 

120 (rf'([{_squote}])(@\{{[0-9a-fA-F]*\}})([{_squote}])', 

121 bygroups(String.Char, String.Escape, String.Char), '#pop'), 

122 (rf'([{_squote}])(@.{{2}})([{_squote}])', 

123 bygroups(String.Char, String.Escape, String.Char), '#pop'), 

124 (rf'[{_squote}]', String.Single, ('#pop', 'dictionary-word')), 

125 (rf'[{_dquote}]', String.Double, ('#pop', 'string')), 

126 # Numbers 

127 (rf'\$[<>]?[+{_dash}][0-9]*\.?[0-9]*([eE][+{_dash}]?[0-9]+)?', 

128 Number.Float, '#pop'), 

129 (r'\$[0-9a-fA-F]+', Number.Hex, '#pop'), 

130 (r'\$\$[01]+', Number.Bin, '#pop'), 

131 (r'[0-9]+', Number.Integer, '#pop'), 

132 # Values prefixed by hashes 

133 (rf'(##|#a\$)({_name})', bygroups(Operator, Name), '#pop'), 

134 (rf'(#g\$)({_name})', 

135 bygroups(Operator, Name.Variable.Global), '#pop'), 

136 (r'#[nw]\$', Operator, ('#pop', 'obsolete-dictionary-word')), 

137 (rf'(#r\$)({_name})', bygroups(Operator, Name.Function), '#pop'), 

138 (r'#', Name.Builtin, ('#pop', 'system-constant')), 

139 # System functions 

140 (words(( 

141 'child', 'children', 'elder', 'eldest', 'glk', 'indirect', 'metaclass', 

142 'parent', 'random', 'sibling', 'younger', 'youngest'), suffix=r'\b'), 

143 Name.Builtin, '#pop'), 

144 # Metaclasses 

145 (r'(?i)(Class|Object|Routine|String)\b', Name.Builtin, '#pop'), 

146 # Veneer routines 

147 (words(( 

148 'Box__Routine', 'CA__Pr', 'CDefArt', 'CInDefArt', 'Cl__Ms', 

149 'Copy__Primitive', 'CP__Tab', 'DA__Pr', 'DB__Pr', 'DefArt', 'Dynam__String', 

150 'EnglishNumber', 'Glk__Wrap', 'IA__Pr', 'IB__Pr', 'InDefArt', 'Main__', 

151 'Meta__class', 'OB__Move', 'OB__Remove', 'OC__Cl', 'OP__Pr', 'Print__Addr', 

152 'Print__PName', 'PrintShortName', 'RA__Pr', 'RA__Sc', 'RL__Pr', 'R_Process', 

153 'RT__ChG', 'RT__ChGt', 'RT__ChLDB', 'RT__ChLDW', 'RT__ChPR', 'RT__ChPrintA', 

154 'RT__ChPrintC', 'RT__ChPrintO', 'RT__ChPrintS', 'RT__ChPS', 'RT__ChR', 

155 'RT__ChSTB', 'RT__ChSTW', 'RT__ChT', 'RT__Err', 'RT__TrPS', 'RV__Pr', 

156 'Symb__Tab', 'Unsigned__Compare', 'WV__Pr', 'Z__Region'), 

157 prefix='(?i)', suffix=r'\b'), 

158 Name.Builtin, '#pop'), 

159 # Other built-in symbols 

160 (words(( 

161 'call', 'copy', 'create', 'DEBUG', 'destroy', 'DICT_CHAR_SIZE', 

162 'DICT_ENTRY_BYTES', 'DICT_IS_UNICODE', 'DICT_WORD_SIZE', 'DOUBLE_HI_INFINITY', 

163 'DOUBLE_HI_NAN', 'DOUBLE_HI_NINFINITY', 'DOUBLE_LO_INFINITY', 'DOUBLE_LO_NAN', 

164 'DOUBLE_LO_NINFINITY', 'false', 'FLOAT_INFINITY', 'FLOAT_NAN', 'FLOAT_NINFINITY', 

165 'GOBJFIELD_CHAIN', 'GOBJFIELD_CHILD', 'GOBJFIELD_NAME', 'GOBJFIELD_PARENT', 

166 'GOBJFIELD_PROPTAB', 'GOBJFIELD_SIBLING', 'GOBJ_EXT_START', 

167 'GOBJ_TOTAL_LENGTH', 'Grammar__Version', 'INDIV_PROP_START', 'INFIX', 

168 'infix__watching', 'MODULE_MODE', 'name', 'nothing', 'NUM_ATTR_BYTES', 'print', 

169 'print_to_array', 'recreate', 'remaining', 'self', 'sender', 'STRICT_MODE', 

170 'sw__var', 'sys__glob0', 'sys__glob1', 'sys__glob2', 'sys_statusline_flag', 

171 'TARGET_GLULX', 'TARGET_ZCODE', 'temp__global2', 'temp__global3', 

172 'temp__global4', 'temp_global', 'true', 'USE_MODULES', 'WORDSIZE'), 

173 prefix='(?i)', suffix=r'\b'), 

174 Name.Builtin, '#pop'), 

175 # Other values 

176 (_name, Name, '#pop') 

177 ], 

178 'value?': [ 

179 include('value'), 

180 default('#pop') 

181 ], 

182 # Strings 

183 'dictionary-word': [ 

184 (rf'[~^]+|//[^{_squote}]*', String.Escape), 

185 (rf'[^~^/\\@({{{_squote}]+', String.Single), 

186 (r'[/({]', String.Single), 

187 (r'@\{[0-9a-fA-F]*\}', String.Escape), 

188 (r'@.{2}', String.Escape), 

189 (rf'[{_squote}]', String.Single, '#pop') 

190 ], 

191 'string': [ 

192 (r'[~^]+', String.Escape), 

193 (rf'[^~^\\@({{{_dquote}]+', String.Double), 

194 (r'[({]', String.Double), 

195 (r'\\', String.Escape), 

196 (rf'@(\\\s*[{_newline}]\s*)*@((\\\s*[{_newline}]\s*)*[0-9])*', String.Escape), 

197 (rf'@(\\\s*[{_newline}]\s*)*[({{]((\\\s*[{_newline}]\s*)*[0-9a-zA-Z_])*' 

198 rf'(\\\s*[{_newline}]\s*)*[)}}]', 

199 String.Escape), 

200 (rf'@(\\\s*[{_newline}]\s*)*.(\\\s*[{_newline}]\s*)*.', 

201 String.Escape), 

202 (rf'[{_dquote}]', String.Double, '#pop') 

203 ], 

204 'plain-string': [ 

205 (rf'[^~^\\({{\[\]{_dquote}]+', String.Double), 

206 (r'[~^({\[\]]', String.Double), 

207 (r'\\', String.Escape), 

208 (rf'[{_dquote}]', String.Double, '#pop') 

209 ], 

210 # Names 

211 '_constant': [ 

212 include('_whitespace'), 

213 (_name, Name.Constant, '#pop'), 

214 include('value') 

215 ], 

216 'constant*': [ 

217 include('_whitespace'), 

218 (r',', Punctuation), 

219 (r'=', Punctuation, 'value?'), 

220 (_name, Name.Constant, 'value?'), 

221 default('#pop') 

222 ], 

223 '_global': [ 

224 include('_whitespace'), 

225 (_name, Name.Variable.Global, '#pop'), 

226 include('value') 

227 ], 

228 'label?': [ 

229 include('_whitespace'), 

230 (_name, Name.Label, '#pop'), 

231 default('#pop') 

232 ], 

233 'variable?': [ 

234 include('_whitespace'), 

235 (_name, Name.Variable, '#pop'), 

236 default('#pop') 

237 ], 

238 # Values after hashes 

239 'obsolete-dictionary-word': [ 

240 (r'\S\w*', String.Other, '#pop') 

241 ], 

242 'system-constant': [ 

243 include('_whitespace'), 

244 (_name, Name.Builtin, '#pop') 

245 ], 

246 

247 # Directives 

248 'directive': [ 

249 include('_whitespace'), 

250 (r'#', Punctuation), 

251 (r';', Punctuation, '#pop'), 

252 (r'\[', Punctuation, 

253 ('default', 'statements', 'locals', 'routine-name?')), 

254 (words(( 

255 'abbreviate', 'endif', 'dictionary', 'ifdef', 'iffalse', 'ifndef', 'ifnot', 

256 'iftrue', 'ifv3', 'ifv5', 'release', 'serial', 'switches', 'system_file', 

257 'version'), prefix='(?i)', suffix=r'\b'), 

258 Keyword, 'default'), 

259 (r'(?i)(array|global)\b', Keyword, 

260 ('default', 'directive-keyword?', '_global')), 

261 (r'(?i)attribute\b', Keyword, ('default', 'alias?', '_constant')), 

262 (r'(?i)class\b', Keyword, 

263 ('object-body', 'duplicates', 'class-name')), 

264 (r'(?i)(constant|default)\b', Keyword, 

265 ('default', 'constant*')), 

266 (r'(?i)(end\b)(.*)', bygroups(Keyword, Text)), 

267 (r'(?i)(extend|verb)\b', Keyword, 'grammar'), 

268 (r'(?i)fake_action\b', Keyword, ('default', '_constant')), 

269 (r'(?i)import\b', Keyword, 'manifest'), 

270 (r'(?i)(include|link|origsource)\b', Keyword, 

271 ('default', 'before-plain-string?')), 

272 (r'(?i)(lowstring|undef)\b', Keyword, ('default', '_constant')), 

273 (r'(?i)message\b', Keyword, ('default', 'diagnostic')), 

274 (r'(?i)(nearby|object)\b', Keyword, 

275 ('object-body', '_object-head')), 

276 (r'(?i)property\b', Keyword, 

277 ('default', 'alias?', '_constant', 'property-keyword*')), 

278 (r'(?i)replace\b', Keyword, 

279 ('default', 'routine-name?', 'routine-name?')), 

280 (r'(?i)statusline\b', Keyword, ('default', 'directive-keyword?')), 

281 (r'(?i)stub\b', Keyword, ('default', 'routine-name?')), 

282 (r'(?i)trace\b', Keyword, 

283 ('default', 'trace-keyword?', 'trace-keyword?')), 

284 (r'(?i)zcharacter\b', Keyword, 

285 ('default', 'directive-keyword?', 'directive-keyword?')), 

286 (_name, Name.Class, ('object-body', '_object-head')) 

287 ], 

288 # [, Replace, Stub 

289 'routine-name?': [ 

290 include('_whitespace'), 

291 (_name, Name.Function, '#pop'), 

292 default('#pop') 

293 ], 

294 'locals': [ 

295 include('_whitespace'), 

296 (r';', Punctuation, '#pop'), 

297 (r'\*', Punctuation), 

298 (r'"', String.Double, 'plain-string'), 

299 (_name, Name.Variable) 

300 ], 

301 # Array 

302 'many-values': [ 

303 include('_whitespace'), 

304 (r';', Punctuation), 

305 (r'\]', Punctuation, '#pop'), 

306 (r':', Error), 

307 default(('expression', '_expression')) 

308 ], 

309 # Attribute, Property 

310 'alias?': [ 

311 include('_whitespace'), 

312 (r'alias\b', Keyword, ('#pop', '_constant')), 

313 default('#pop') 

314 ], 

315 # Class, Object, Nearby 

316 'class-name': [ 

317 include('_whitespace'), 

318 (r'(?=[,;]|(class|has|private|with)\b)', Text, '#pop'), 

319 (_name, Name.Class, '#pop') 

320 ], 

321 'duplicates': [ 

322 include('_whitespace'), 

323 (r'\(', Punctuation, ('#pop', 'expression', '_expression')), 

324 default('#pop') 

325 ], 

326 '_object-head': [ 

327 (rf'[{_dash}]>', Punctuation), 

328 (r'(class|has|private|with)\b', Keyword.Declaration, '#pop'), 

329 include('_global') 

330 ], 

331 'object-body': [ 

332 include('_whitespace'), 

333 (r';', Punctuation, '#pop:2'), 

334 (r',', Punctuation), 

335 (r'class\b', Keyword.Declaration, 'class-segment'), 

336 (r'(has|private|with)\b', Keyword.Declaration), 

337 (r':', Error), 

338 default(('_object-expression', '_expression')) 

339 ], 

340 'class-segment': [ 

341 include('_whitespace'), 

342 (r'(?=[,;]|(class|has|private|with)\b)', Text, '#pop'), 

343 (_name, Name.Class), 

344 default('value') 

345 ], 

346 # Extend, Verb 

347 'grammar': [ 

348 include('_whitespace'), 

349 (r'=', Punctuation, ('#pop', 'default')), 

350 (r'\*', Punctuation, ('#pop', 'grammar-line')), 

351 default('_directive-keyword') 

352 ], 

353 'grammar-line': [ 

354 include('_whitespace'), 

355 (r';', Punctuation, '#pop'), 

356 (r'[/*]', Punctuation), 

357 (rf'[{_dash}]>', Punctuation, 'value'), 

358 (r'(noun|scope)\b', Keyword, '=routine'), 

359 default('_directive-keyword') 

360 ], 

361 '=routine': [ 

362 include('_whitespace'), 

363 (r'=', Punctuation, 'routine-name?'), 

364 default('#pop') 

365 ], 

366 # Import 

367 'manifest': [ 

368 include('_whitespace'), 

369 (r';', Punctuation, '#pop'), 

370 (r',', Punctuation), 

371 (r'(?i)global\b', Keyword, '_global'), 

372 default('_global') 

373 ], 

374 # Include, Link, Message 

375 'diagnostic': [ 

376 include('_whitespace'), 

377 (rf'[{_dquote}]', String.Double, ('#pop', 'message-string')), 

378 default(('#pop', 'before-plain-string?', 'directive-keyword?')) 

379 ], 

380 'before-plain-string?': [ 

381 include('_whitespace'), 

382 (rf'[{_dquote}]', String.Double, ('#pop', 'plain-string')), 

383 default('#pop') 

384 ], 

385 'message-string': [ 

386 (r'[~^]+', String.Escape), 

387 include('plain-string') 

388 ], 

389 

390 # Keywords used in directives 

391 '_directive-keyword!': [ 

392 include('_whitespace'), 

393 (words(( 

394 'additive', 'alias', 'buffer', 'class', 'creature', 'data', 'error', 'fatalerror', 

395 'first', 'has', 'held', 'individual', 'initial', 'initstr', 'last', 'long', 'meta', 

396 'multi', 'multiexcept', 'multiheld', 'multiinside', 'noun', 'number', 'only', 

397 'private', 'replace', 'reverse', 'scope', 'score', 'special', 'string', 'table', 

398 'terminating', 'time', 'topic', 'warning', 'with'), suffix=r'\b'), 

399 Keyword, '#pop'), 

400 (r'static\b', Keyword), 

401 (rf'[{_dash}]{{1,2}}>|[+=]', Punctuation, '#pop') 

402 ], 

403 '_directive-keyword': [ 

404 include('_directive-keyword!'), 

405 include('value') 

406 ], 

407 'directive-keyword?': [ 

408 include('_directive-keyword!'), 

409 default('#pop') 

410 ], 

411 'property-keyword*': [ 

412 include('_whitespace'), 

413 (words(('additive', 'individual', 'long'), 

414 suffix=rf'\b(?=(\s*|(![^{_newline}]*[{_newline}]))*[_a-zA-Z])'), 

415 Keyword), 

416 default('#pop') 

417 ], 

418 'trace-keyword?': [ 

419 include('_whitespace'), 

420 (words(( 

421 'assembly', 'dictionary', 'expressions', 'lines', 'linker', 

422 'objects', 'off', 'on', 'symbols', 'tokens', 'verbs'), suffix=r'\b'), 

423 Keyword, '#pop'), 

424 default('#pop') 

425 ], 

426 

427 # Statements 

428 'statements': [ 

429 include('_whitespace'), 

430 (r'\]', Punctuation, '#pop'), 

431 (r'[;{}]', Punctuation), 

432 (words(( 

433 'box', 'break', 'continue', 'default', 'give', 'inversion', 

434 'new_line', 'quit', 'read', 'remove', 'return', 'rfalse', 'rtrue', 

435 'spaces', 'string', 'until'), suffix=r'\b'), 

436 Keyword, 'default'), 

437 (r'(do|else)\b', Keyword), 

438 (r'(font|style)\b', Keyword, 

439 ('default', 'miscellaneous-keyword?')), 

440 (r'for\b', Keyword, ('for', '(?')), 

441 (r'(if|switch|while)', Keyword, 

442 ('expression', '_expression', '(?')), 

443 (r'(jump|save|restore)\b', Keyword, ('default', 'label?')), 

444 (r'objectloop\b', Keyword, 

445 ('_keyword-expression', 'variable?', '(?')), 

446 (rf'print(_ret)?\b|(?=[{_dquote}])', Keyword, 'print-list'), 

447 (r'\.', Name.Label, 'label?'), 

448 (r'@', Keyword, 'opcode'), 

449 (r'#(?![agrnw]\$|#)', Punctuation, 'directive'), 

450 (r'<', Punctuation, 'default'), 

451 (r'move\b', Keyword, 

452 ('default', '_keyword-expression', '_expression')), 

453 default(('default', '_keyword-expression', '_expression')) 

454 ], 

455 'miscellaneous-keyword?': [ 

456 include('_whitespace'), 

457 (r'(bold|fixed|from|near|off|on|reverse|roman|to|underline)\b', 

458 Keyword, '#pop'), 

459 (r'(a|A|an|address|char|name|number|object|property|string|the|' 

460 rf'The)\b(?=(\s+|(![^{_newline}]*))*\))', Keyword.Pseudo, 

461 '#pop'), 

462 (rf'{_name}(?=(\s+|(![^{_newline}]*))*\))', Name.Function, 

463 '#pop'), 

464 default('#pop') 

465 ], 

466 '(?': [ 

467 include('_whitespace'), 

468 (r'\(', Punctuation, '#pop'), 

469 default('#pop') 

470 ], 

471 'for': [ 

472 include('_whitespace'), 

473 (r';', Punctuation, ('_for-expression', '_expression')), 

474 default(('_for-expression', '_expression')) 

475 ], 

476 'print-list': [ 

477 include('_whitespace'), 

478 (r';', Punctuation, '#pop'), 

479 (r':', Error), 

480 default(('_list-expression', '_expression', '_list-expression', 'form')) 

481 ], 

482 'form': [ 

483 include('_whitespace'), 

484 (r'\(', Punctuation, ('#pop', 'miscellaneous-keyword?')), 

485 default('#pop') 

486 ], 

487 

488 # Assembly 

489 'opcode': [ 

490 include('_whitespace'), 

491 (rf'[{_dquote}]', String.Double, ('operands', 'plain-string')), 

492 (rf'[{_dash}]{{1,2}}>', Punctuation, 'operands'), 

493 (_name, Keyword, 'operands') 

494 ], 

495 'operands': [ 

496 (r':', Error), 

497 default(('_assembly-expression', '_expression')) 

498 ] 

499 } 

500 

501 def get_tokens_unprocessed(self, text): 

502 # 'in' is either a keyword or an operator. 

503 # If the token two tokens after 'in' is ')', 'in' is a keyword: 

504 # objectloop(a in b) 

505 # Otherwise, it is an operator: 

506 # objectloop(a in b && true) 

507 objectloop_queue = [] 

508 objectloop_token_count = -1 

509 previous_token = None 

510 for index, token, value in RegexLexer.get_tokens_unprocessed(self, 

511 text): 

512 if previous_token is Name.Variable and value == 'in': 

513 objectloop_queue = [[index, token, value]] 

514 objectloop_token_count = 2 

515 elif objectloop_token_count > 0: 

516 if token not in Comment and token not in Text: 

517 objectloop_token_count -= 1 

518 objectloop_queue.append((index, token, value)) 

519 else: 

520 if objectloop_token_count == 0: 

521 if objectloop_queue[-1][2] == ')': 

522 objectloop_queue[0][1] = Keyword 

523 while objectloop_queue: 

524 yield objectloop_queue.pop(0) 

525 objectloop_token_count = -1 

526 yield index, token, value 

527 if token not in Comment and token not in Text: 

528 previous_token = token 

529 while objectloop_queue: 

530 yield objectloop_queue.pop(0) 

531 

532 def analyse_text(text): 

533 """We try to find a keyword which seem relatively common, unfortunately 

534 there is a decent overlap with Smalltalk keywords otherwise here..""" 

535 result = 0 

536 if re.search('\borigsource\b', text, re.IGNORECASE): 

537 result += 0.05 

538 

539 return result 

540 

541 

542class Inform7Lexer(RegexLexer): 

543 """ 

544 For Inform 7 source code. 

545 """ 

546 

547 name = 'Inform 7' 

548 url = 'http://inform7.com/' 

549 aliases = ['inform7', 'i7'] 

550 filenames = ['*.ni', '*.i7x'] 

551 version_added = '2.0' 

552 

553 flags = re.MULTILINE | re.DOTALL 

554 

555 _dash = Inform6Lexer._dash 

556 _dquote = Inform6Lexer._dquote 

557 _newline = Inform6Lexer._newline 

558 _start = rf'\A|(?<=[{_newline}])' 

559 

560 # There are three variants of Inform 7, differing in how to 

561 # interpret at signs and braces in I6T. In top-level inclusions, at 

562 # signs in the first column are inweb syntax. In phrase definitions 

563 # and use options, tokens in braces are treated as I7. Use options 

564 # also interpret "{N}". 

565 tokens = {} 

566 token_variants = ['+i6t-not-inline', '+i6t-inline', '+i6t-use-option'] 

567 

568 for level in token_variants: 

569 tokens[level] = { 

570 '+i6-root': list(Inform6Lexer.tokens['root']), 

571 '+i6t-root': [ # For Inform6TemplateLexer 

572 (rf'[^{Inform6Lexer._newline}]*', Comment.Preproc, 

573 ('directive', '+p')) 

574 ], 

575 'root': [ 

576 (r'(\|?\s)+', Text), 

577 (r'\[', Comment.Multiline, '+comment'), 

578 (rf'[{_dquote}]', Generic.Heading, 

579 ('+main', '+titling', '+titling-string')), 

580 default(('+main', '+heading?')) 

581 ], 

582 '+titling-string': [ 

583 (rf'[^{_dquote}]+', Generic.Heading), 

584 (rf'[{_dquote}]', Generic.Heading, '#pop') 

585 ], 

586 '+titling': [ 

587 (r'\[', Comment.Multiline, '+comment'), 

588 (rf'[^{_dquote}.;:|{_newline}]+', Generic.Heading), 

589 (rf'[{_dquote}]', Generic.Heading, '+titling-string'), 

590 (rf'[{_newline}]{{2}}|(?<=[\s{_dquote}])\|[\s{_dquote}]', 

591 Text, ('#pop', '+heading?')), 

592 (rf'[.;:]|(?<=[\s{_dquote}])\|', Text, '#pop'), 

593 (rf'[|{_newline}]', Generic.Heading) 

594 ], 

595 '+main': [ 

596 (rf'(?i)[^{_dquote}:a\[(|{_newline}]+', Text), 

597 (rf'[{_dquote}]', String.Double, '+text'), 

598 (r':', Text, '+phrase-definition'), 

599 (r'(?i)\bas\b', Text, '+use-option'), 

600 (r'\[', Comment.Multiline, '+comment'), 

601 (rf'(\([{_dash}])(.*?)([{_dash}]\))', 

602 bygroups(Punctuation, 

603 using(this, state=('+i6-root', 'directive'), 

604 i6t='+i6t-not-inline'), Punctuation)), 

605 (rf'({_start}|(?<=[\s;:.{_dquote}]))\|\s|[{_newline}]{{2,}}', Text, '+heading?'), 

606 (rf'(?i)[a(|{_newline}]', Text) 

607 ], 

608 '+phrase-definition': [ 

609 (r'\s+', Text), 

610 (r'\[', Comment.Multiline, '+comment'), 

611 (rf'(\([{_dash}])(.*?)([{_dash}]\))', 

612 bygroups(Punctuation, 

613 using(this, state=('+i6-root', 'directive', 

614 'default', 'statements'), 

615 i6t='+i6t-inline'), Punctuation), '#pop'), 

616 default('#pop') 

617 ], 

618 '+use-option': [ 

619 (r'\s+', Text), 

620 (r'\[', Comment.Multiline, '+comment'), 

621 (rf'(\([{_dash}])(.*?)([{_dash}]\))', 

622 bygroups(Punctuation, 

623 using(this, state=('+i6-root', 'directive'), 

624 i6t='+i6t-use-option'), Punctuation), '#pop'), 

625 default('#pop') 

626 ], 

627 '+comment': [ 

628 (r'[^\[\]]+', Comment.Multiline), 

629 (r'\[', Comment.Multiline, '#push'), 

630 (r'\]', Comment.Multiline, '#pop') 

631 ], 

632 '+text': [ 

633 (rf'[^\[{_dquote}]+', String.Double), 

634 (r'\[.*?\]', String.Interpol), 

635 (rf'[{_dquote}]', String.Double, '#pop') 

636 ], 

637 '+heading?': [ 

638 (r'(\|?\s)+', Text), 

639 (r'\[', Comment.Multiline, '+comment'), 

640 (rf'[{_dash}]{{4}}\s+', Text, '+documentation-heading'), 

641 (rf'[{_dash}]{{1,3}}', Text), 

642 (rf'(?i)(volume|book|part|chapter|section)\b[^{_newline}]*', 

643 Generic.Heading, '#pop'), 

644 default('#pop') 

645 ], 

646 '+documentation-heading': [ 

647 (r'\s+', Text), 

648 (r'\[', Comment.Multiline, '+comment'), 

649 (r'(?i)documentation\s+', Text, '+documentation-heading2'), 

650 default('#pop') 

651 ], 

652 '+documentation-heading2': [ 

653 (r'\s+', Text), 

654 (r'\[', Comment.Multiline, '+comment'), 

655 (rf'[{_dash}]{{4}}\s', Text, '+documentation'), 

656 default('#pop:2') 

657 ], 

658 '+documentation': [ 

659 (rf'(?i)({_start})\s*(chapter|example)\s*:[^{_newline}]*', Generic.Heading), 

660 (rf'(?i)({_start})\s*section\s*:[^{_newline}]*', 

661 Generic.Subheading), 

662 (rf'(({_start})\t.*?[{_newline}])+', 

663 using(this, state='+main')), 

664 (rf'[^{_newline}\[]+|[{_newline}\[]', Text), 

665 (r'\[', Comment.Multiline, '+comment'), 

666 ], 

667 '+i6t-not-inline': [ 

668 (rf'({_start})@c( .*?)?([{_newline}]|\Z)', 

669 Comment.Preproc), 

670 (rf'({_start})@([{_dash}]+|Purpose:)[^{_newline}]*', 

671 Comment.Preproc), 

672 (rf'({_start})@p( .*?)?([{_newline}]|\Z)', 

673 Generic.Heading, '+p') 

674 ], 

675 '+i6t-use-option': [ 

676 include('+i6t-not-inline'), 

677 (r'(\{)(N)(\})', bygroups(Punctuation, Text, Punctuation)) 

678 ], 

679 '+i6t-inline': [ 

680 (r'(\{)(\S[^}]*)?(\})', 

681 bygroups(Punctuation, using(this, state='+main'), 

682 Punctuation)) 

683 ], 

684 '+i6t': [ 

685 (rf'(\{{[{_dash}])(![^}}]*)(\}}?)', 

686 bygroups(Punctuation, Comment.Single, Punctuation)), 

687 (rf'(\{{[{_dash}])(lines)(:)([^}}]*)(\}}?)', 

688 bygroups(Punctuation, Keyword, Punctuation, Text, 

689 Punctuation), '+lines'), 

690 (rf'(\{{[{_dash}])([^:}}]*)(:?)([^}}]*)(\}}?)', 

691 bygroups(Punctuation, Keyword, Punctuation, Text, 

692 Punctuation)), 

693 (r'(\(\+)(.*?)(\+\)|\Z)', 

694 bygroups(Punctuation, using(this, state='+main'), 

695 Punctuation)) 

696 ], 

697 '+p': [ 

698 (r'[^@]+', Comment.Preproc), 

699 (rf'({_start})@c( .*?)?([{_newline}]|\Z)', 

700 Comment.Preproc, '#pop'), 

701 (rf'({_start})@([{_dash}]|Purpose:)', Comment.Preproc), 

702 (rf'({_start})@p( .*?)?([{_newline}]|\Z)', 

703 Generic.Heading), 

704 (r'@', Comment.Preproc) 

705 ], 

706 '+lines': [ 

707 (rf'({_start})@c( .*?)?([{_newline}]|\Z)', 

708 Comment.Preproc), 

709 (rf'({_start})@([{_dash}]|Purpose:)[^{_newline}]*', 

710 Comment.Preproc), 

711 (rf'({_start})@p( .*?)?([{_newline}]|\Z)', 

712 Generic.Heading, '+p'), 

713 (rf'({_start})@\w*[ {_newline}]', Keyword), 

714 (rf'![^{_newline}]*', Comment.Single), 

715 (rf'(\{{)([{_dash}]endlines)(\}})', 

716 bygroups(Punctuation, Keyword, Punctuation), '#pop'), 

717 (rf'[^@!{{]+?([{_newline}]|\Z)|.', Text) 

718 ] 

719 } 

720 # Inform 7 can include snippets of Inform 6 template language, 

721 # so all of Inform6Lexer's states are copied here, with 

722 # modifications to account for template syntax. Inform7Lexer's 

723 # own states begin with '+' to avoid name conflicts. Some of 

724 # Inform6Lexer's states begin with '_': these are not modified. 

725 # They deal with template syntax either by including modified 

726 # states, or by matching r'' then pushing to modified states. 

727 for token in Inform6Lexer.tokens: 

728 if token == 'root': 

729 continue 

730 tokens[level][token] = list(Inform6Lexer.tokens[token]) 

731 if not token.startswith('_'): 

732 tokens[level][token][:0] = [include('+i6t'), include(level)] 

733 

734 def __init__(self, **options): 

735 level = options.get('i6t', '+i6t-not-inline') 

736 if level not in self._all_tokens: 

737 self._tokens = self.__class__.process_tokendef(level) 

738 else: 

739 self._tokens = self._all_tokens[level] 

740 RegexLexer.__init__(self, **options) 

741 

742 

743class Inform6TemplateLexer(Inform7Lexer): 

744 """ 

745 For Inform 6 template code. 

746 """ 

747 

748 name = 'Inform 6 template' 

749 aliases = ['i6t'] 

750 filenames = ['*.i6t'] 

751 version_added = '2.0' 

752 

753 def get_tokens_unprocessed(self, text, stack=('+i6t-root',)): 

754 return Inform7Lexer.get_tokens_unprocessed(self, text, stack) 

755 

756 

757class Tads3Lexer(RegexLexer): 

758 """ 

759 For TADS 3 source code. 

760 """ 

761 

762 name = 'TADS 3' 

763 aliases = ['tads3'] 

764 filenames = ['*.t'] 

765 url = 'https://www.tads.org' 

766 version_added = '' 

767 

768 flags = re.DOTALL | re.MULTILINE 

769 

770 _comment_single = r'(?://(?:[^\\\n]|\\+[\w\W])*$)' 

771 _comment_multiline = r'(?:/\*(?:[^*]|\*(?!/))*\*/)' 

772 _escape = (r'(?:\\(?:[\n\\<>"\'^v bnrt]|u[\da-fA-F]{,4}|x[\da-fA-F]{,2}|' 

773 r'[0-3]?[0-7]{1,2}))') 

774 _name = r'(?:[_a-zA-Z]\w*)' 

775 _no_quote = r'(?=\s|\\?>)' 

776 _operator = (r'(?:&&|\|\||\+\+|--|\?\?|::|[.,@\[\]~]|' 

777 r'(?:[=+\-*/%!&|^]|<<?|>>?>?)=?)') 

778 _ws = rf'(?:\\|\s|{_comment_single}|{_comment_multiline})' 

779 _ws_pp = rf'(?:\\\n|[^\S\n]|{_comment_single}|{_comment_multiline})' 

780 

781 def _make_string_state(triple, double, verbatim=None, _escape=_escape): 

782 if verbatim: 

783 verbatim = ''.join([f'(?:{re.escape(c.lower())}|{re.escape(c.upper())})' 

784 for c in verbatim]) 

785 char = r'"' if double else r"'" 

786 token = String.Double if double else String.Single 

787 escaped_quotes = rf'+|{char}(?!{char}{{2}})' if triple else r'' 

788 prefix = '{}{}'.format('t' if triple else '', 'd' if double else 's') 

789 tag_state_name = f'{prefix}qt' 

790 state = [] 

791 if triple: 

792 state += [ 

793 (rf'{char}{{3,}}', token, '#pop'), 

794 (rf'\\{char}+', String.Escape), 

795 (char, token) 

796 ] 

797 else: 

798 state.append((char, token, '#pop')) 

799 state += [ 

800 include('s/verbatim'), 

801 (rf'[^\\<&{{}}{char}]+', token) 

802 ] 

803 if verbatim: 

804 # This regex can't use `(?i)` because escape sequences are 

805 # case-sensitive. `<\XMP>` works; `<\xmp>` doesn't. 

806 state.append((rf'\\?<(/|\\\\|(?!{_escape})\\){verbatim}(?=[\s=>])', 

807 Name.Tag, ('#pop', f'{prefix}qs', tag_state_name))) 

808 else: 

809 state += [ 

810 (rf'\\?<!([^><\\{char}]|<(?!<)|\\{char}{escaped_quotes}|{_escape}|\\.)*>?', Comment.Multiline), 

811 (r'(?i)\\?<listing(?=[\s=>]|\\>)', Name.Tag, 

812 ('#pop', f'{prefix}qs/listing', tag_state_name)), 

813 (r'(?i)\\?<xmp(?=[\s=>]|\\>)', Name.Tag, 

814 ('#pop', f'{prefix}qs/xmp', tag_state_name)), 

815 (rf'\\?<([^\s=><\\{char}]|<(?!<)|\\{char}{escaped_quotes}|{_escape}|\\.)*', Name.Tag, 

816 tag_state_name), 

817 include('s/entity') 

818 ] 

819 state += [ 

820 include('s/escape'), 

821 (rf'\{{([^}}<\\{char}]|<(?!<)|\\{char}{escaped_quotes}|{_escape}|\\.)*\}}', String.Interpol), 

822 (r'[\\&{}<]', token) 

823 ] 

824 return state 

825 

826 def _make_tag_state(triple, double, _escape=_escape): 

827 char = r'"' if double else r"'" 

828 quantifier = r'{3,}' if triple else r'' 

829 state_name = '{}{}qt'.format('t' if triple else '', 'd' if double else 's') 

830 token = String.Double if double else String.Single 

831 escaped_quotes = rf'+|{char}(?!{char}{{2}})' if triple else r'' 

832 return [ 

833 (rf'{char}{quantifier}', token, '#pop:2'), 

834 (r'(\s|\\\n)+', Text), 

835 (r'(=)(\\?")', bygroups(Punctuation, String.Double), 

836 f'dqs/{state_name}'), 

837 (r"(=)(\\?')", bygroups(Punctuation, String.Single), 

838 f'sqs/{state_name}'), 

839 (r'=', Punctuation, f'uqs/{state_name}'), 

840 (r'\\?>', Name.Tag, '#pop'), 

841 (rf'\{{([^}}<\\{char}]|<(?!<)|\\{char}{escaped_quotes}|{_escape}|\\.)*\}}', String.Interpol), 

842 (rf'([^\s=><\\{char}]|<(?!<)|\\{char}{escaped_quotes}|{_escape}|\\.)+', Name.Attribute), 

843 include('s/escape'), 

844 include('s/verbatim'), 

845 include('s/entity'), 

846 (r'[\\{}&]', Name.Attribute) 

847 ] 

848 

849 def _make_attribute_value_state(terminator, host_triple, host_double, 

850 _escape=_escape): 

851 token = (String.Double if terminator == r'"' else 

852 String.Single if terminator == r"'" else String.Other) 

853 host_char = r'"' if host_double else r"'" 

854 host_quantifier = r'{3,}' if host_triple else r'' 

855 host_token = String.Double if host_double else String.Single 

856 escaped_quotes = (rf'+|{host_char}(?!{host_char}{{2}})' 

857 if host_triple else r'') 

858 return [ 

859 (rf'{host_char}{host_quantifier}', host_token, '#pop:3'), 

860 (r'{}{}'.format(r'' if token is String.Other else r'\\?', terminator), 

861 token, '#pop'), 

862 include('s/verbatim'), 

863 include('s/entity'), 

864 (rf'\{{([^}}<\\{host_char}]|<(?!<)|\\{host_char}{escaped_quotes}|{_escape}|\\.)*\}}', String.Interpol), 

865 (r'([^\s"\'<%s{}\\&])+' % (r'>' if token is String.Other else r''), 

866 token), 

867 include('s/escape'), 

868 (r'["\'\s&{<}\\]', token) 

869 ] 

870 

871 tokens = { 

872 'root': [ 

873 ('\ufeff', Text), 

874 (r'\{', Punctuation, 'object-body'), 

875 (r';+', Punctuation), 

876 (r'(?=(argcount|break|case|catch|continue|default|definingobj|' 

877 r'delegated|do|else|for|foreach|finally|goto|if|inherited|' 

878 r'invokee|local|nil|new|operator|replaced|return|self|switch|' 

879 r'targetobj|targetprop|throw|true|try|while)\b)', Text, 'block'), 

880 (rf'({_name})({_ws}*)(\()', 

881 bygroups(Name.Function, using(this, state='whitespace'), 

882 Punctuation), 

883 ('block?/root', 'more/parameters', 'main/parameters')), 

884 include('whitespace'), 

885 (r'\++', Punctuation), 

886 (r'[^\s!"%-(*->@-_a-z{-~]+', Error), # Averts an infinite loop 

887 (r'(?!\Z)', Text, 'main/root') 

888 ], 

889 'main/root': [ 

890 include('main/basic'), 

891 default(('#pop', 'object-body/no-braces', 'classes', 'class')) 

892 ], 

893 'object-body/no-braces': [ 

894 (r';', Punctuation, '#pop'), 

895 (r'\{', Punctuation, ('#pop', 'object-body')), 

896 include('object-body') 

897 ], 

898 'object-body': [ 

899 (r';', Punctuation), 

900 (r'\{', Punctuation, '#push'), 

901 (r'\}', Punctuation, '#pop'), 

902 (r':', Punctuation, ('classes', 'class')), 

903 (rf'({_name}?)({_ws}*)(\()', 

904 bygroups(Name.Function, using(this, state='whitespace'), 

905 Punctuation), 

906 ('block?', 'more/parameters', 'main/parameters')), 

907 (rf'({_name})({_ws}*)(\{{)', 

908 bygroups(Name.Function, using(this, state='whitespace'), 

909 Punctuation), 'block'), 

910 (rf'({_name})({_ws}*)(:)', 

911 bygroups(Name.Variable, using(this, state='whitespace'), 

912 Punctuation), 

913 ('object-body/no-braces', 'classes', 'class')), 

914 include('whitespace'), 

915 (rf'->|{_operator}', Punctuation, 'main'), 

916 default('main/object-body') 

917 ], 

918 'main/object-body': [ 

919 include('main/basic'), 

920 (rf'({_name})({_ws}*)(=?)', 

921 bygroups(Name.Variable, using(this, state='whitespace'), 

922 Punctuation), ('#pop', 'more', 'main')), 

923 default('#pop:2') 

924 ], 

925 'block?/root': [ 

926 (r'\{', Punctuation, ('#pop', 'block')), 

927 include('whitespace'), 

928 (r'(?=[\[\'"<(:])', Text, # It might be a VerbRule macro. 

929 ('#pop', 'object-body/no-braces', 'grammar', 'grammar-rules')), 

930 # It might be a macro like DefineAction. 

931 default(('#pop', 'object-body/no-braces')) 

932 ], 

933 'block?': [ 

934 (r'\{', Punctuation, ('#pop', 'block')), 

935 include('whitespace'), 

936 default('#pop') 

937 ], 

938 'block/basic': [ 

939 (r'[;:]+', Punctuation), 

940 (r'\{', Punctuation, '#push'), 

941 (r'\}', Punctuation, '#pop'), 

942 (r'default\b', Keyword.Reserved), 

943 (rf'({_name})({_ws}*)(:)', 

944 bygroups(Name.Label, using(this, state='whitespace'), 

945 Punctuation)), 

946 include('whitespace') 

947 ], 

948 'block': [ 

949 include('block/basic'), 

950 (r'(?!\Z)', Text, ('more', 'main')) 

951 ], 

952 'block/embed': [ 

953 (r'>>', String.Interpol, '#pop'), 

954 include('block/basic'), 

955 (r'(?!\Z)', Text, ('more/embed', 'main')) 

956 ], 

957 'main/basic': [ 

958 include('whitespace'), 

959 (r'\(', Punctuation, ('#pop', 'more', 'main')), 

960 (r'\[', Punctuation, ('#pop', 'more/list', 'main')), 

961 (r'\{', Punctuation, ('#pop', 'more/inner', 'main/inner', 

962 'more/parameters', 'main/parameters')), 

963 (r'\*|\.{3}', Punctuation, '#pop'), 

964 (r'(?i)0x[\da-f]+', Number.Hex, '#pop'), 

965 (r'(\d+\.(?!\.)\d*|\.\d+)([eE][-+]?\d+)?|\d+[eE][-+]?\d+', 

966 Number.Float, '#pop'), 

967 (r'0[0-7]+', Number.Oct, '#pop'), 

968 (r'\d+', Number.Integer, '#pop'), 

969 (r'"""', String.Double, ('#pop', 'tdqs')), 

970 (r"'''", String.Single, ('#pop', 'tsqs')), 

971 (r'"', String.Double, ('#pop', 'dqs')), 

972 (r"'", String.Single, ('#pop', 'sqs')), 

973 (r'R"""', String.Regex, ('#pop', 'tdqr')), 

974 (r"R'''", String.Regex, ('#pop', 'tsqr')), 

975 (r'R"', String.Regex, ('#pop', 'dqr')), 

976 (r"R'", String.Regex, ('#pop', 'sqr')), 

977 # Two-token keywords 

978 (rf'(extern)({_ws}+)(object\b)', 

979 bygroups(Keyword.Reserved, using(this, state='whitespace'), 

980 Keyword.Reserved)), 

981 (rf'(function|method)({_ws}*)(\()', 

982 bygroups(Keyword.Reserved, using(this, state='whitespace'), 

983 Punctuation), 

984 ('#pop', 'block?', 'more/parameters', 'main/parameters')), 

985 (rf'(modify)({_ws}+)(grammar\b)', 

986 bygroups(Keyword.Reserved, using(this, state='whitespace'), 

987 Keyword.Reserved), 

988 ('#pop', 'object-body/no-braces', ':', 'grammar')), 

989 (rf'(new)({_ws}+(?=(?:function|method)\b))', 

990 bygroups(Keyword.Reserved, using(this, state='whitespace'))), 

991 (rf'(object)({_ws}+)(template\b)', 

992 bygroups(Keyword.Reserved, using(this, state='whitespace'), 

993 Keyword.Reserved), ('#pop', 'template')), 

994 (rf'(string)({_ws}+)(template\b)', 

995 bygroups(Keyword, using(this, state='whitespace'), 

996 Keyword.Reserved), ('#pop', 'function-name')), 

997 # Keywords 

998 (r'(argcount|definingobj|invokee|replaced|targetobj|targetprop)\b', 

999 Name.Builtin, '#pop'), 

1000 (r'(break|continue|goto)\b', Keyword.Reserved, ('#pop', 'label')), 

1001 (r'(case|extern|if|intrinsic|return|static|while)\b', 

1002 Keyword.Reserved), 

1003 (r'catch\b', Keyword.Reserved, ('#pop', 'catch')), 

1004 (r'class\b', Keyword.Reserved, 

1005 ('#pop', 'object-body/no-braces', 'class')), 

1006 (r'(default|do|else|finally|try)\b', Keyword.Reserved, '#pop'), 

1007 (r'(dictionary|property)\b', Keyword.Reserved, 

1008 ('#pop', 'constants')), 

1009 (r'enum\b', Keyword.Reserved, ('#pop', 'enum')), 

1010 (r'export\b', Keyword.Reserved, ('#pop', 'main')), 

1011 (r'(for|foreach)\b', Keyword.Reserved, 

1012 ('#pop', 'more/inner', 'main/inner')), 

1013 (r'(function|method)\b', Keyword.Reserved, 

1014 ('#pop', 'block?', 'function-name')), 

1015 (r'grammar\b', Keyword.Reserved, 

1016 ('#pop', 'object-body/no-braces', 'grammar')), 

1017 (r'inherited\b', Keyword.Reserved, ('#pop', 'inherited')), 

1018 (r'local\b', Keyword.Reserved, 

1019 ('#pop', 'more/local', 'main/local')), 

1020 (r'(modify|replace|switch|throw|transient)\b', Keyword.Reserved, 

1021 '#pop'), 

1022 (r'new\b', Keyword.Reserved, ('#pop', 'class')), 

1023 (r'(nil|true)\b', Keyword.Constant, '#pop'), 

1024 (r'object\b', Keyword.Reserved, ('#pop', 'object-body/no-braces')), 

1025 (r'operator\b', Keyword.Reserved, ('#pop', 'operator')), 

1026 (r'propertyset\b', Keyword.Reserved, 

1027 ('#pop', 'propertyset', 'main')), 

1028 (r'self\b', Name.Builtin.Pseudo, '#pop'), 

1029 (r'template\b', Keyword.Reserved, ('#pop', 'template')), 

1030 # Operators 

1031 (rf'(__objref|defined)({_ws}*)(\()', 

1032 bygroups(Operator.Word, using(this, state='whitespace'), 

1033 Operator), ('#pop', 'more/__objref', 'main')), 

1034 (r'delegated\b', Operator.Word), 

1035 # Compiler-defined macros and built-in properties 

1036 (r'(__DATE__|__DEBUG|__LINE__|__FILE__|' 

1037 r'__TADS_MACRO_FORMAT_VERSION|__TADS_SYS_\w*|__TADS_SYSTEM_NAME|' 

1038 r'__TADS_VERSION_MAJOR|__TADS_VERSION_MINOR|__TADS3|__TIME__|' 

1039 r'construct|finalize|grammarInfo|grammarTag|lexicalParent|' 

1040 r'miscVocab|sourceTextGroup|sourceTextGroupName|' 

1041 r'sourceTextGroupOrder|sourceTextOrder)\b', Name.Builtin, '#pop') 

1042 ], 

1043 'main': [ 

1044 include('main/basic'), 

1045 (_name, Name, '#pop'), 

1046 default('#pop') 

1047 ], 

1048 'more/basic': [ 

1049 (r'\(', Punctuation, ('more/list', 'main')), 

1050 (r'\[', Punctuation, ('more', 'main')), 

1051 (r'\.{3}', Punctuation), 

1052 (r'->|\.\.', Punctuation, 'main'), 

1053 (r'(?=;)|[:)\]]', Punctuation, '#pop'), 

1054 include('whitespace'), 

1055 (_operator, Operator, 'main'), 

1056 (r'\?', Operator, ('main', 'more/conditional', 'main')), 

1057 (rf'(is|not)({_ws}+)(in\b)', 

1058 bygroups(Operator.Word, using(this, state='whitespace'), 

1059 Operator.Word)), 

1060 (r'[^\s!"%-_a-z{-~]+', Error) # Averts an infinite loop 

1061 ], 

1062 'more': [ 

1063 include('more/basic'), 

1064 default('#pop') 

1065 ], 

1066 # Then expression (conditional operator) 

1067 'more/conditional': [ 

1068 (r':(?!:)', Operator, '#pop'), 

1069 include('more') 

1070 ], 

1071 # Embedded expressions 

1072 'more/embed': [ 

1073 (r'>>', String.Interpol, '#pop:2'), 

1074 include('more') 

1075 ], 

1076 # For/foreach loop initializer or short-form anonymous function 

1077 'main/inner': [ 

1078 (r'\(', Punctuation, ('#pop', 'more/inner', 'main/inner')), 

1079 (r'local\b', Keyword.Reserved, ('#pop', 'main/local')), 

1080 include('main') 

1081 ], 

1082 'more/inner': [ 

1083 (r'\}', Punctuation, '#pop'), 

1084 (r',', Punctuation, 'main/inner'), 

1085 (r'(in|step)\b', Keyword, 'main/inner'), 

1086 include('more') 

1087 ], 

1088 # Local 

1089 'main/local': [ 

1090 (_name, Name.Variable, '#pop'), 

1091 include('whitespace') 

1092 ], 

1093 'more/local': [ 

1094 (r',', Punctuation, 'main/local'), 

1095 include('more') 

1096 ], 

1097 # List 

1098 'more/list': [ 

1099 (r'[,:]', Punctuation, 'main'), 

1100 include('more') 

1101 ], 

1102 # Parameter list 

1103 'main/parameters': [ 

1104 (rf'({_name})({_ws}*)(?=:)', 

1105 bygroups(Name.Variable, using(this, state='whitespace')), '#pop'), 

1106 (rf'({_name})({_ws}+)({_name})', 

1107 bygroups(Name.Class, using(this, state='whitespace'), 

1108 Name.Variable), '#pop'), 

1109 (r'\[+', Punctuation), 

1110 include('main/basic'), 

1111 (_name, Name.Variable, '#pop'), 

1112 default('#pop') 

1113 ], 

1114 'more/parameters': [ 

1115 (rf'(:)({_ws}*(?=[?=,:)]))', 

1116 bygroups(Punctuation, using(this, state='whitespace'))), 

1117 (r'[?\]]+', Punctuation), 

1118 (r'[:)]', Punctuation, ('#pop', 'multimethod?')), 

1119 (r',', Punctuation, 'main/parameters'), 

1120 (r'=', Punctuation, ('more/parameter', 'main')), 

1121 include('more') 

1122 ], 

1123 'more/parameter': [ 

1124 (r'(?=[,)])', Text, '#pop'), 

1125 include('more') 

1126 ], 

1127 'multimethod?': [ 

1128 (r'multimethod\b', Keyword, '#pop'), 

1129 include('whitespace'), 

1130 default('#pop') 

1131 ], 

1132 

1133 # Statements and expressions 

1134 'more/__objref': [ 

1135 (r',', Punctuation, 'mode'), 

1136 (r'\)', Operator, '#pop'), 

1137 include('more') 

1138 ], 

1139 'mode': [ 

1140 (r'(error|warn)\b', Keyword, '#pop'), 

1141 include('whitespace') 

1142 ], 

1143 'catch': [ 

1144 (r'\(+', Punctuation), 

1145 (_name, Name.Exception, ('#pop', 'variables')), 

1146 include('whitespace') 

1147 ], 

1148 'enum': [ 

1149 include('whitespace'), 

1150 (r'token\b', Keyword, ('#pop', 'constants')), 

1151 default(('#pop', 'constants')) 

1152 ], 

1153 'grammar': [ 

1154 (r'\)+', Punctuation), 

1155 (r'\(', Punctuation, 'grammar-tag'), 

1156 (r':', Punctuation, 'grammar-rules'), 

1157 (_name, Name.Class), 

1158 include('whitespace') 

1159 ], 

1160 'grammar-tag': [ 

1161 include('whitespace'), 

1162 (r'"""([^\\"<]|""?(?!")|\\"+|\\.|<(?!<))+("{3,}|<<)|' 

1163 r'R"""([^\\"]|""?(?!")|\\"+|\\.)+"{3,}|' 

1164 r"'''([^\\'<]|''?(?!')|\\'+|\\.|<(?!<))+('{3,}|<<)|" 

1165 r"R'''([^\\']|''?(?!')|\\'+|\\.)+'{3,}|" 

1166 r'"([^\\"<]|\\.|<(?!<))+("|<<)|R"([^\\"]|\\.)+"|' 

1167 r"'([^\\'<]|\\.|<(?!<))+('|<<)|R'([^\\']|\\.)+'|" 

1168 r"([^)\s\\/]|/(?![/*]))+|\)", String.Other, '#pop') 

1169 ], 

1170 'grammar-rules': [ 

1171 include('string'), 

1172 include('whitespace'), 

1173 (rf'(\[)({_ws}*)(badness)', 

1174 bygroups(Punctuation, using(this, state='whitespace'), Keyword), 

1175 'main'), 

1176 (rf'->|{_operator}|[()]', Punctuation), 

1177 (_name, Name.Constant), 

1178 default('#pop:2') 

1179 ], 

1180 ':': [ 

1181 (r':', Punctuation, '#pop') 

1182 ], 

1183 'function-name': [ 

1184 (r'(<<([^>]|>>>|>(?!>))*>>)+', String.Interpol), 

1185 (rf'(?={_name}?{_ws}*[({{])', Text, '#pop'), 

1186 (_name, Name.Function, '#pop'), 

1187 include('whitespace') 

1188 ], 

1189 'inherited': [ 

1190 (r'<', Punctuation, ('#pop', 'classes', 'class')), 

1191 include('whitespace'), 

1192 (_name, Name.Class, '#pop'), 

1193 default('#pop') 

1194 ], 

1195 'operator': [ 

1196 (r'negate\b', Operator.Word, '#pop'), 

1197 include('whitespace'), 

1198 (_operator, Operator), 

1199 default('#pop') 

1200 ], 

1201 'propertyset': [ 

1202 (r'\(', Punctuation, ('more/parameters', 'main/parameters')), 

1203 (r'\{', Punctuation, ('#pop', 'object-body')), 

1204 include('whitespace') 

1205 ], 

1206 'template': [ 

1207 (r'(?=;)', Text, '#pop'), 

1208 include('string'), 

1209 (r'inherited\b', Keyword.Reserved), 

1210 include('whitespace'), 

1211 (rf'->|\?|{_operator}', Punctuation), 

1212 (_name, Name.Variable) 

1213 ], 

1214 

1215 # Identifiers 

1216 'class': [ 

1217 (r'\*|\.{3}', Punctuation, '#pop'), 

1218 (r'object\b', Keyword.Reserved, '#pop'), 

1219 (r'transient\b', Keyword.Reserved), 

1220 (_name, Name.Class, '#pop'), 

1221 include('whitespace'), 

1222 default('#pop') 

1223 ], 

1224 'classes': [ 

1225 (r'[:,]', Punctuation, 'class'), 

1226 include('whitespace'), 

1227 (r'>', Punctuation, '#pop'), 

1228 default('#pop') 

1229 ], 

1230 'constants': [ 

1231 (r',+', Punctuation), 

1232 (r';', Punctuation, '#pop'), 

1233 (r'property\b', Keyword.Reserved), 

1234 (_name, Name.Constant), 

1235 include('whitespace') 

1236 ], 

1237 'label': [ 

1238 (_name, Name.Label, '#pop'), 

1239 include('whitespace'), 

1240 default('#pop') 

1241 ], 

1242 'variables': [ 

1243 (r',+', Punctuation), 

1244 (r'\)', Punctuation, '#pop'), 

1245 include('whitespace'), 

1246 (_name, Name.Variable) 

1247 ], 

1248 

1249 # Whitespace and comments 

1250 'whitespace': [ 

1251 (rf'^{_ws_pp}*#({_comment_multiline}|[^\n]|(?<=\\)\n)*\n?', 

1252 Comment.Preproc), 

1253 (_comment_single, Comment.Single), 

1254 (_comment_multiline, Comment.Multiline), 

1255 (rf'\\+\n+{_ws_pp}*#?|\n+|([^\S\n]|\\)+', Text) 

1256 ], 

1257 

1258 # Strings 

1259 'string': [ 

1260 (r'"""', String.Double, 'tdqs'), 

1261 (r"'''", String.Single, 'tsqs'), 

1262 (r'"', String.Double, 'dqs'), 

1263 (r"'", String.Single, 'sqs') 

1264 ], 

1265 's/escape': [ 

1266 (rf'\{{\{{|\}}\}}|{_escape}', String.Escape) 

1267 ], 

1268 's/verbatim': [ 

1269 (r'<<\s*(as\s+decreasingly\s+likely\s+outcomes|cycling|else|end|' 

1270 r'first\s+time|one\s+of|only|or|otherwise|' 

1271 r'(sticky|(then\s+)?(purely\s+)?at)\s+random|stopping|' 

1272 r'(then\s+)?(half\s+)?shuffled|\|\|)\s*>>', String.Interpol), 

1273 (rf'<<(%(_({_escape}|\\?.)|[\-+ ,#]|\[\d*\]?)*\d*\.?\d*({_escape}|\\?.)|' 

1274 r'\s*((else|otherwise)\s+)?(if|unless)\b)?', 

1275 String.Interpol, ('block/embed', 'more/embed', 'main')) 

1276 ], 

1277 's/entity': [ 

1278 (r'(?i)&(#(x[\da-f]+|\d+)|[a-z][\da-z]*);?', Name.Entity) 

1279 ], 

1280 'tdqs': _make_string_state(True, True), 

1281 'tsqs': _make_string_state(True, False), 

1282 'dqs': _make_string_state(False, True), 

1283 'sqs': _make_string_state(False, False), 

1284 'tdqs/listing': _make_string_state(True, True, 'listing'), 

1285 'tsqs/listing': _make_string_state(True, False, 'listing'), 

1286 'dqs/listing': _make_string_state(False, True, 'listing'), 

1287 'sqs/listing': _make_string_state(False, False, 'listing'), 

1288 'tdqs/xmp': _make_string_state(True, True, 'xmp'), 

1289 'tsqs/xmp': _make_string_state(True, False, 'xmp'), 

1290 'dqs/xmp': _make_string_state(False, True, 'xmp'), 

1291 'sqs/xmp': _make_string_state(False, False, 'xmp'), 

1292 

1293 # Tags 

1294 'tdqt': _make_tag_state(True, True), 

1295 'tsqt': _make_tag_state(True, False), 

1296 'dqt': _make_tag_state(False, True), 

1297 'sqt': _make_tag_state(False, False), 

1298 'dqs/tdqt': _make_attribute_value_state(r'"', True, True), 

1299 'dqs/tsqt': _make_attribute_value_state(r'"', True, False), 

1300 'dqs/dqt': _make_attribute_value_state(r'"', False, True), 

1301 'dqs/sqt': _make_attribute_value_state(r'"', False, False), 

1302 'sqs/tdqt': _make_attribute_value_state(r"'", True, True), 

1303 'sqs/tsqt': _make_attribute_value_state(r"'", True, False), 

1304 'sqs/dqt': _make_attribute_value_state(r"'", False, True), 

1305 'sqs/sqt': _make_attribute_value_state(r"'", False, False), 

1306 'uqs/tdqt': _make_attribute_value_state(_no_quote, True, True), 

1307 'uqs/tsqt': _make_attribute_value_state(_no_quote, True, False), 

1308 'uqs/dqt': _make_attribute_value_state(_no_quote, False, True), 

1309 'uqs/sqt': _make_attribute_value_state(_no_quote, False, False), 

1310 

1311 # Regular expressions 

1312 'tdqr': [ 

1313 (r'[^\\"]+', String.Regex), 

1314 (r'\\"*', String.Regex), 

1315 (r'"{3,}', String.Regex, '#pop'), 

1316 (r'"', String.Regex) 

1317 ], 

1318 'tsqr': [ 

1319 (r"[^\\']+", String.Regex), 

1320 (r"\\'*", String.Regex), 

1321 (r"'{3,}", String.Regex, '#pop'), 

1322 (r"'", String.Regex) 

1323 ], 

1324 'dqr': [ 

1325 (r'[^\\"]+', String.Regex), 

1326 (r'\\"?', String.Regex), 

1327 (r'"', String.Regex, '#pop') 

1328 ], 

1329 'sqr': [ 

1330 (r"[^\\']+", String.Regex), 

1331 (r"\\'?", String.Regex), 

1332 (r"'", String.Regex, '#pop') 

1333 ] 

1334 } 

1335 

1336 def get_tokens_unprocessed(self, text, **kwargs): 

1337 pp = rf'^{self._ws_pp}*#{self._ws_pp}*' 

1338 if_false_level = 0 

1339 for index, token, value in ( 

1340 RegexLexer.get_tokens_unprocessed(self, text, **kwargs)): 

1341 if if_false_level == 0: # Not in a false #if 

1342 if (token is Comment.Preproc and 

1343 re.match(rf'{pp}if{self._ws_pp}+(0|nil){self._ws_pp}*$\n?', value)): 

1344 if_false_level = 1 

1345 else: # In a false #if 

1346 if token is Comment.Preproc: 

1347 if (if_false_level == 1 and 

1348 re.match(rf'{pp}el(if|se)\b', value)): 

1349 if_false_level = 0 

1350 elif re.match(rf'{pp}if', value): 

1351 if_false_level += 1 

1352 elif re.match(rf'{pp}endif\b', value): 

1353 if_false_level -= 1 

1354 else: 

1355 token = Comment 

1356 yield index, token, value 

1357 

1358 def analyse_text(text): 

1359 """This is a rather generic descriptive language without strong 

1360 identifiers. It looks like a 'GameMainDef' has to be present, 

1361 and/or a 'versionInfo' with an 'IFID' field.""" 

1362 result = 0 

1363 if '__TADS' in text or 'GameMainDef' in text: 

1364 result += 0.2 

1365 

1366 # This is a fairly unique keyword which is likely used in source as well 

1367 if 'versionInfo' in text and 'IFID' in text: 

1368 result += 0.1 

1369 

1370 return result