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