1""" 
    2    pygments.lexers.basic 
    3    ~~~~~~~~~~~~~~~~~~~~~ 
    4 
    5    Lexers for BASIC like languages (other than VB.net). 
    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, bygroups, default, words, include 
    14from pygments.token import Comment, Error, Keyword, Name, Number, \ 
    15    Punctuation, Operator, String, Text, Whitespace 
    16from pygments.lexers import _vbscript_builtins 
    17 
    18 
    19__all__ = ['BlitzBasicLexer', 'BlitzMaxLexer', 'MonkeyLexer', 'CbmBasicV2Lexer', 
    20           'QBasicLexer', 'VBScriptLexer', 'BBCBasicLexer'] 
    21 
    22 
    23class BlitzMaxLexer(RegexLexer): 
    24    """ 
    25    For BlitzMax source code. 
    26    """ 
    27 
    28    name = 'BlitzMax' 
    29    url = 'http://blitzbasic.com' 
    30    aliases = ['blitzmax', 'bmax'] 
    31    filenames = ['*.bmx'] 
    32    mimetypes = ['text/x-bmx'] 
    33    version_added = '1.4' 
    34 
    35    bmax_vopwords = r'\b(Shl|Shr|Sar|Mod)\b' 
    36    bmax_sktypes = r'@{1,2}|[!#$%]' 
    37    bmax_lktypes = r'\b(Int|Byte|Short|Float|Double|Long)\b' 
    38    bmax_name = r'[a-z_]\w*' 
    39    bmax_var = (rf'({bmax_name})(?:(?:([ \t]*)({bmax_sktypes})|([ \t]*:[ \t]*\b(?:Shl|Shr|Sar|Mod)\b)' 
    40                rf'|([ \t]*)(:)([ \t]*)(?:{bmax_lktypes}|({bmax_name})))(?:([ \t]*)(Ptr))?)') 
    41    bmax_func = bmax_var + r'?((?:[ \t]|\.\.\n)*)([(])' 
    42 
    43    flags = re.MULTILINE | re.IGNORECASE 
    44    tokens = { 
    45        'root': [ 
    46            # Text 
    47            (r'\s+', Whitespace), 
    48            (r'(\.\.)(\n)', bygroups(Text, Whitespace)),  # Line continuation 
    49            # Comments 
    50            (r"'.*?\n", Comment.Single), 
    51            (r'([ \t]*)\bRem\n(\n|.)*?\s*\bEnd([ \t]*)Rem', Comment.Multiline), 
    52            # Data types 
    53            ('"', String.Double, 'string'), 
    54            # Numbers 
    55            (r'[0-9]+\.[0-9]*(?!\.)', Number.Float), 
    56            (r'\.[0-9]*(?!\.)', Number.Float), 
    57            (r'[0-9]+', Number.Integer), 
    58            (r'\$[0-9a-f]+', Number.Hex), 
    59            (r'\%[10]+', Number.Bin), 
    60            # Other 
    61            (rf'(?:(?:(:)?([ \t]*)(:?{bmax_vopwords}|([+\-*/&|~]))|Or|And|Not|[=<>^]))', Operator), 
    62            (r'[(),.:\[\]]', Punctuation), 
    63            (r'(?:#[\w \t]*)', Name.Label), 
    64            (r'(?:\?[\w \t]*)', Comment.Preproc), 
    65            # Identifiers 
    66            (rf'\b(New)\b([ \t]?)([(]?)({bmax_name})', 
    67             bygroups(Keyword.Reserved, Whitespace, Punctuation, Name.Class)), 
    68            (rf'\b(Import|Framework|Module)([ \t]+)({bmax_name}\.{bmax_name})', 
    69             bygroups(Keyword.Reserved, Whitespace, Keyword.Namespace)), 
    70            (bmax_func, bygroups(Name.Function, Whitespace, Keyword.Type, 
    71                                 Operator, Whitespace, Punctuation, Whitespace, 
    72                                 Keyword.Type, Name.Class, Whitespace, 
    73                                 Keyword.Type, Whitespace, Punctuation)), 
    74            (bmax_var, bygroups(Name.Variable, Whitespace, Keyword.Type, Operator, 
    75                                Whitespace, Punctuation, Whitespace, Keyword.Type, 
    76                                Name.Class, Whitespace, Keyword.Type)), 
    77            (rf'\b(Type|Extends)([ \t]+)({bmax_name})', 
    78             bygroups(Keyword.Reserved, Whitespace, Name.Class)), 
    79            # Keywords 
    80            (r'\b(Ptr)\b', Keyword.Type), 
    81            (r'\b(Pi|True|False|Null|Self|Super)\b', Keyword.Constant), 
    82            (r'\b(Local|Global|Const|Field)\b', Keyword.Declaration), 
    83            (words(( 
    84                'TNullMethodException', 'TNullFunctionException', 
    85                'TNullObjectException', 'TArrayBoundsException', 
    86                'TRuntimeException'), prefix=r'\b', suffix=r'\b'), Name.Exception), 
    87            (words(( 
    88                'Strict', 'SuperStrict', 'Module', 'ModuleInfo', 
    89                'End', 'Return', 'Continue', 'Exit', 'Public', 'Private', 
    90                'Var', 'VarPtr', 'Chr', 'Len', 'Asc', 'SizeOf', 'Sgn', 'Abs', 'Min', 'Max', 
    91                'New', 'Release', 'Delete', 'Incbin', 'IncbinPtr', 'IncbinLen', 
    92                'Framework', 'Include', 'Import', 'Extern', 'EndExtern', 
    93                'Function', 'EndFunction', 'Type', 'EndType', 'Extends', 'Method', 'EndMethod', 
    94                'Abstract', 'Final', 'If', 'Then', 'Else', 'ElseIf', 'EndIf', 
    95                'For', 'To', 'Next', 'Step', 'EachIn', 'While', 'Wend', 'EndWhile', 
    96                'Repeat', 'Until', 'Forever', 'Select', 'Case', 'Default', 'EndSelect', 
    97                'Try', 'Catch', 'EndTry', 'Throw', 'Assert', 'Goto', 'DefData', 'ReadData', 
    98                'RestoreData'), prefix=r'\b', suffix=r'\b'), 
    99             Keyword.Reserved), 
    100            # Final resolve (for variable names and such) 
    101            (rf'({bmax_name})', Name.Variable), 
    102        ], 
    103        'string': [ 
    104            (r'""', String.Double), 
    105            (r'"C?', String.Double, '#pop'), 
    106            (r'[^"]+', String.Double), 
    107        ], 
    108    } 
    109 
    110 
    111class BlitzBasicLexer(RegexLexer): 
    112    """ 
    113    For BlitzBasic source code. 
    114    """ 
    115 
    116    name = 'BlitzBasic' 
    117    url = 'http://blitzbasic.com' 
    118    aliases = ['blitzbasic', 'b3d', 'bplus'] 
    119    filenames = ['*.bb', '*.decls'] 
    120    mimetypes = ['text/x-bb'] 
    121    version_added = '2.0' 
    122 
    123    bb_sktypes = r'@{1,2}|[#$%]' 
    124    bb_name = r'[a-z]\w*' 
    125    bb_var = (rf'({bb_name})(?:([ \t]*)({bb_sktypes})|([ \t]*)([.])([ \t]*)(?:({bb_name})))?') 
    126 
    127    flags = re.MULTILINE | re.IGNORECASE 
    128    tokens = { 
    129        'root': [ 
    130            # Text 
    131            (r'\s+', Whitespace), 
    132            # Comments 
    133            (r";.*?\n", Comment.Single), 
    134            # Data types 
    135            ('"', String.Double, 'string'), 
    136            # Numbers 
    137            (r'[0-9]+\.[0-9]*(?!\.)', Number.Float), 
    138            (r'\.[0-9]+(?!\.)', Number.Float), 
    139            (r'[0-9]+', Number.Integer), 
    140            (r'\$[0-9a-f]+', Number.Hex), 
    141            (r'\%[10]+', Number.Bin), 
    142            # Other 
    143            (words(('Shl', 'Shr', 'Sar', 'Mod', 'Or', 'And', 'Not', 
    144                    'Abs', 'Sgn', 'Handle', 'Int', 'Float', 'Str', 
    145                    'First', 'Last', 'Before', 'After'), 
    146                   prefix=r'\b', suffix=r'\b'), 
    147             Operator), 
    148            (r'([+\-*/~=<>^])', Operator), 
    149            (r'[(),:\[\]\\]', Punctuation), 
    150            (rf'\.([ \t]*)({bb_name})', Name.Label), 
    151            # Identifiers 
    152            (rf'\b(New)\b([ \t]+)({bb_name})', 
    153             bygroups(Keyword.Reserved, Whitespace, Name.Class)), 
    154            (rf'\b(Gosub|Goto)\b([ \t]+)({bb_name})', 
    155             bygroups(Keyword.Reserved, Whitespace, Name.Label)), 
    156            (rf'\b(Object)\b([ \t]*)([.])([ \t]*)({bb_name})\b', 
    157             bygroups(Operator, Whitespace, Punctuation, Whitespace, Name.Class)), 
    158            (rf'\b{bb_var}\b([ \t]*)(\()', 
    159             bygroups(Name.Function, Whitespace, Keyword.Type, Whitespace, Punctuation, 
    160                      Whitespace, Name.Class, Whitespace, Punctuation)), 
    161            (rf'\b(Function)\b([ \t]+){bb_var}', 
    162             bygroups(Keyword.Reserved, Whitespace, Name.Function, Whitespace, Keyword.Type, 
    163                      Whitespace, Punctuation, Whitespace, Name.Class)), 
    164            (rf'\b(Type)([ \t]+)({bb_name})', 
    165             bygroups(Keyword.Reserved, Whitespace, Name.Class)), 
    166            # Keywords 
    167            (r'\b(Pi|True|False|Null)\b', Keyword.Constant), 
    168            (r'\b(Local|Global|Const|Field|Dim)\b', Keyword.Declaration), 
    169            (words(( 
    170                'End', 'Return', 'Exit', 'Chr', 'Len', 'Asc', 'New', 'Delete', 'Insert', 
    171                'Include', 'Function', 'Type', 'If', 'Then', 'Else', 'ElseIf', 'EndIf', 
    172                'For', 'To', 'Next', 'Step', 'Each', 'While', 'Wend', 
    173                'Repeat', 'Until', 'Forever', 'Select', 'Case', 'Default', 
    174                'Goto', 'Gosub', 'Data', 'Read', 'Restore'), prefix=r'\b', suffix=r'\b'), 
    175             Keyword.Reserved), 
    176            # Final resolve (for variable names and such) 
    177            # (r'(%s)' % (bb_name), Name.Variable), 
    178            (bb_var, bygroups(Name.Variable, Whitespace, Keyword.Type, 
    179                              Whitespace, Punctuation, Whitespace, Name.Class)), 
    180        ], 
    181        'string': [ 
    182            (r'""', String.Double), 
    183            (r'"C?', String.Double, '#pop'), 
    184            (r'[^"\n]+', String.Double), 
    185        ], 
    186    } 
    187 
    188 
    189class MonkeyLexer(RegexLexer): 
    190    """ 
    191    For Monkey source code. 
    192    """ 
    193 
    194    name = 'Monkey' 
    195    aliases = ['monkey'] 
    196    filenames = ['*.monkey'] 
    197    mimetypes = ['text/x-monkey'] 
    198    url = 'https://blitzresearch.itch.io/monkeyx' 
    199    version_added = '1.6' 
    200 
    201    name_variable = r'[a-z_]\w*' 
    202    name_function = r'[A-Z]\w*' 
    203    name_constant = r'[A-Z_][A-Z0-9_]*' 
    204    name_class = r'[A-Z]\w*' 
    205    name_module = r'[a-z0-9_]*' 
    206 
    207    keyword_type = r'(?:Int|Float|String|Bool|Object|Array|Void)' 
    208    # ? == Bool // % == Int // # == Float // $ == String 
    209    keyword_type_special = r'[?%#$]' 
    210 
    211    flags = re.MULTILINE 
    212 
    213    tokens = { 
    214        'root': [ 
    215            # Text 
    216            (r'\s+', Whitespace), 
    217            # Comments 
    218            (r"'.*", Comment), 
    219            (r'(?i)^#rem\b', Comment.Multiline, 'comment'), 
    220            # preprocessor directives 
    221            (r'(?i)^(?:#If|#ElseIf|#Else|#EndIf|#End|#Print|#Error)\b', Comment.Preproc), 
    222            # preprocessor variable (any line starting with '#' that is not a directive) 
    223            (r'^#', Comment.Preproc, 'variables'), 
    224            # String 
    225            ('"', String.Double, 'string'), 
    226            # Numbers 
    227            (r'[0-9]+\.[0-9]*(?!\.)', Number.Float), 
    228            (r'\.[0-9]+(?!\.)', Number.Float), 
    229            (r'[0-9]+', Number.Integer), 
    230            (r'\$[0-9a-fA-Z]+', Number.Hex), 
    231            (r'\%[10]+', Number.Bin), 
    232            # Native data types 
    233            (rf'\b{keyword_type}\b', Keyword.Type), 
    234            # Exception handling 
    235            (r'(?i)\b(?:Try|Catch|Throw)\b', Keyword.Reserved), 
    236            (r'Throwable', Name.Exception), 
    237            # Builtins 
    238            (r'(?i)\b(?:Null|True|False)\b', Name.Builtin), 
    239            (r'(?i)\b(?:Self|Super)\b', Name.Builtin.Pseudo), 
    240            (r'\b(?:HOST|LANG|TARGET|CONFIG)\b', Name.Constant), 
    241            # Keywords 
    242            (r'(?i)^(Import)(\s+)(.*)(\n)', 
    243             bygroups(Keyword.Namespace, Whitespace, Name.Namespace, Whitespace)), 
    244            (r'(?i)^Strict\b.*\n', Keyword.Reserved), 
    245            (r'(?i)(Const|Local|Global|Field)(\s+)', 
    246             bygroups(Keyword.Declaration, Whitespace), 'variables'), 
    247            (r'(?i)(New|Class|Interface|Extends|Implements)(\s+)', 
    248             bygroups(Keyword.Reserved, Whitespace), 'classname'), 
    249            (r'(?i)(Function|Method)(\s+)', 
    250             bygroups(Keyword.Reserved, Whitespace), 'funcname'), 
    251            (r'(?i)(?:End|Return|Public|Private|Extern|Property|' 
    252             r'Final|Abstract)\b', Keyword.Reserved), 
    253            # Flow Control stuff 
    254            (r'(?i)(?:If|Then|Else|ElseIf|EndIf|' 
    255             r'Select|Case|Default|' 
    256             r'While|Wend|' 
    257             r'Repeat|Until|Forever|' 
    258             r'For|To|Until|Step|EachIn|Next|' 
    259             r'Exit|Continue)(?=\s)', Keyword.Reserved), 
    260            # not used yet 
    261            (r'(?i)\b(?:Module|Inline)\b', Keyword.Reserved), 
    262            # Array 
    263            (r'[\[\]]', Punctuation), 
    264            # Other 
    265            (r'<=|>=|<>|\*=|/=|\+=|-=|&=|~=|\|=|[-&*/^+=<>|~]', Operator), 
    266            (r'(?i)(?:Not|Mod|Shl|Shr|And|Or)', Operator.Word), 
    267            (r'[(){}!#,.:]', Punctuation), 
    268            # catch the rest 
    269            (rf'{name_constant}\b', Name.Constant), 
    270            (rf'{name_function}\b', Name.Function), 
    271            (rf'{name_variable}\b', Name.Variable), 
    272        ], 
    273        'funcname': [ 
    274            (rf'(?i){name_function}\b', Name.Function), 
    275            (r':', Punctuation, 'classname'), 
    276            (r'\s+', Whitespace), 
    277            (r'\(', Punctuation, 'variables'), 
    278            (r'\)', Punctuation, '#pop') 
    279        ], 
    280        'classname': [ 
    281            (rf'{name_module}\.', Name.Namespace), 
    282            (rf'{keyword_type}\b', Keyword.Type), 
    283            (rf'{name_class}\b', Name.Class), 
    284            # array (of given size) 
    285            (r'(\[)(\s*)(\d*)(\s*)(\])', 
    286             bygroups(Punctuation, Whitespace, Number.Integer, Whitespace, Punctuation)), 
    287            # generics 
    288            (r'\s+(?!<)', Whitespace, '#pop'), 
    289            (r'<', Punctuation, '#push'), 
    290            (r'>', Punctuation, '#pop'), 
    291            (r'\n', Whitespace, '#pop'), 
    292            default('#pop') 
    293        ], 
    294        'variables': [ 
    295            (rf'{name_constant}\b', Name.Constant), 
    296            (rf'{name_variable}\b', Name.Variable), 
    297            (rf'{keyword_type_special}', Keyword.Type), 
    298            (r'\s+', Whitespace), 
    299            (r':', Punctuation, 'classname'), 
    300            (r',', Punctuation, '#push'), 
    301            default('#pop') 
    302        ], 
    303        'string': [ 
    304            (r'[^"~]+', String.Double), 
    305            (r'~q|~n|~r|~t|~z|~~', String.Escape), 
    306            (r'"', String.Double, '#pop'), 
    307        ], 
    308        'comment': [ 
    309            (r'(?i)^#rem.*?', Comment.Multiline, "#push"), 
    310            (r'(?i)^#end.*?', Comment.Multiline, "#pop"), 
    311            (r'\n', Comment.Multiline), 
    312            (r'.+', Comment.Multiline), 
    313        ], 
    314    } 
    315 
    316 
    317class CbmBasicV2Lexer(RegexLexer): 
    318    """ 
    319    For CBM BASIC V2 sources. 
    320    """ 
    321    name = 'CBM BASIC V2' 
    322    aliases = ['cbmbas'] 
    323    filenames = ['*.bas'] 
    324    url = 'https://en.wikipedia.org/wiki/Commodore_BASIC' 
    325    version_added = '1.6' 
    326 
    327    flags = re.IGNORECASE 
    328 
    329    tokens = { 
    330        'root': [ 
    331            (r'rem.*\n', Comment.Single), 
    332            (r'\s+', Whitespace), 
    333            (r'new|run|end|for|to|next|step|go(to|sub)?|on|return|stop|cont' 
    334             r'|if|then|input#?|read|wait|load|save|verify|poke|sys|print#?' 
    335             r'|list|clr|cmd|open|close|get#?', Keyword.Reserved), 
    336            (r'data|restore|dim|let|def|fn', Keyword.Declaration), 
    337            (r'tab|spc|sgn|int|abs|usr|fre|pos|sqr|rnd|log|exp|cos|sin|tan|atn' 
    338             r'|peek|len|val|asc|(str|chr|left|right|mid)\$', Name.Builtin), 
    339            (r'[-+*/^<>=]', Operator), 
    340            (r'not|and|or', Operator.Word), 
    341            (r'"[^"\n]*.', String), 
    342            (r'\d+|[-+]?\d*\.\d*(e[-+]?\d+)?', Number.Float), 
    343            (r'[(),:;]', Punctuation), 
    344            (r'\w+[$%]?', Name), 
    345        ] 
    346    } 
    347 
    348    def analyse_text(text): 
    349        # if it starts with a line number, it shouldn't be a "modern" Basic 
    350        # like VB.net 
    351        if re.match(r'^\d+', text): 
    352            return 0.2 
    353 
    354 
    355class QBasicLexer(RegexLexer): 
    356    """ 
    357    For QBasic source code. 
    358    """ 
    359 
    360    name = 'QBasic' 
    361    aliases = ['qbasic', 'basic'] 
    362    filenames = ['*.BAS', '*.bas'] 
    363    mimetypes = ['text/basic'] 
    364    url = 'https://en.wikipedia.org/wiki/QBasic' 
    365    version_added = '2.0' 
    366 
    367    declarations = ('DATA', 'LET') 
    368 
    369    functions = ( 
    370        'ABS', 'ASC', 'ATN', 'CDBL', 'CHR$', 'CINT', 'CLNG', 
    371        'COMMAND$', 'COS', 'CSNG', 'CSRLIN', 'CVD', 'CVDMBF', 'CVI', 
    372        'CVL', 'CVS', 'CVSMBF', 'DATE$', 'ENVIRON$', 'EOF', 'ERDEV', 
    373        'ERDEV$', 'ERL', 'ERR', 'EXP', 'FILEATTR', 'FIX', 'FRE', 
    374        'FREEFILE', 'HEX$', 'INKEY$', 'INP', 'INPUT$', 'INSTR', 'INT', 
    375        'IOCTL$', 'LBOUND', 'LCASE$', 'LEFT$', 'LEN', 'LOC', 'LOF', 
    376        'LOG', 'LPOS', 'LTRIM$', 'MID$', 'MKD$', 'MKDMBF$', 'MKI$', 
    377        'MKL$', 'MKS$', 'MKSMBF$', 'OCT$', 'PEEK', 'PEN', 'PLAY', 
    378        'PMAP', 'POINT', 'POS', 'RIGHT$', 'RND', 'RTRIM$', 'SADD', 
    379        'SCREEN', 'SEEK', 'SETMEM', 'SGN', 'SIN', 'SPACE$', 'SPC', 
    380        'SQR', 'STICK', 'STR$', 'STRIG', 'STRING$', 'TAB', 'TAN', 
    381        'TIME$', 'TIMER', 'UBOUND', 'UCASE$', 'VAL', 'VARPTR', 
    382        'VARPTR$', 'VARSEG' 
    383    ) 
    384 
    385    metacommands = ('$DYNAMIC', '$INCLUDE', '$STATIC') 
    386 
    387    operators = ('AND', 'EQV', 'IMP', 'NOT', 'OR', 'XOR') 
    388 
    389    statements = ( 
    390        'BEEP', 'BLOAD', 'BSAVE', 'CALL', 'CALL ABSOLUTE', 
    391        'CALL INTERRUPT', 'CALLS', 'CHAIN', 'CHDIR', 'CIRCLE', 'CLEAR', 
    392        'CLOSE', 'CLS', 'COLOR', 'COM', 'COMMON', 'CONST', 'DATA', 
    393        'DATE$', 'DECLARE', 'DEF FN', 'DEF SEG', 'DEFDBL', 'DEFINT', 
    394        'DEFLNG', 'DEFSNG', 'DEFSTR', 'DEF', 'DIM', 'DO', 'LOOP', 
    395        'DRAW', 'END', 'ENVIRON', 'ERASE', 'ERROR', 'EXIT', 'FIELD', 
    396        'FILES', 'FOR', 'NEXT', 'FUNCTION', 'GET', 'GOSUB', 'GOTO', 
    397        'IF', 'THEN', 'INPUT', 'INPUT #', 'IOCTL', 'KEY', 'KEY', 
    398        'KILL', 'LET', 'LINE', 'LINE INPUT', 'LINE INPUT #', 'LOCATE', 
    399        'LOCK', 'UNLOCK', 'LPRINT', 'LSET', 'MID$', 'MKDIR', 'NAME', 
    400        'ON COM', 'ON ERROR', 'ON KEY', 'ON PEN', 'ON PLAY', 
    401        'ON STRIG', 'ON TIMER', 'ON UEVENT', 'ON', 'OPEN', 'OPEN COM', 
    402        'OPTION BASE', 'OUT', 'PAINT', 'PALETTE', 'PCOPY', 'PEN', 
    403        'PLAY', 'POKE', 'PRESET', 'PRINT', 'PRINT #', 'PRINT USING', 
    404        'PSET', 'PUT', 'PUT', 'RANDOMIZE', 'READ', 'REDIM', 'REM', 
    405        'RESET', 'RESTORE', 'RESUME', 'RETURN', 'RMDIR', 'RSET', 'RUN', 
    406        'SCREEN', 'SEEK', 'SELECT CASE', 'SHARED', 'SHELL', 'SLEEP', 
    407        'SOUND', 'STATIC', 'STOP', 'STRIG', 'SUB', 'SWAP', 'SYSTEM', 
    408        'TIME$', 'TIMER', 'TROFF', 'TRON', 'TYPE', 'UEVENT', 'UNLOCK', 
    409        'VIEW', 'WAIT', 'WHILE', 'WEND', 'WIDTH', 'WINDOW', 'WRITE' 
    410    ) 
    411 
    412    keywords = ( 
    413        'ACCESS', 'ALIAS', 'ANY', 'APPEND', 'AS', 'BASE', 'BINARY', 
    414        'BYVAL', 'CASE', 'CDECL', 'DOUBLE', 'ELSE', 'ELSEIF', 'ENDIF', 
    415        'INTEGER', 'IS', 'LIST', 'LOCAL', 'LONG', 'LOOP', 'MOD', 
    416        'NEXT', 'OFF', 'ON', 'OUTPUT', 'RANDOM', 'SIGNAL', 'SINGLE', 
    417        'STEP', 'STRING', 'THEN', 'TO', 'UNTIL', 'USING', 'WEND' 
    418    ) 
    419 
    420    tokens = { 
    421        'root': [ 
    422            (r'\n+', Text), 
    423            (r'\s+', Text.Whitespace), 
    424            (r'^(\s*)(\d*)(\s*)(REM .*)$', 
    425             bygroups(Text.Whitespace, Name.Label, Text.Whitespace, 
    426                      Comment.Single)), 
    427            (r'^(\s*)(\d+)(\s*)', 
    428             bygroups(Text.Whitespace, Name.Label, Text.Whitespace)), 
    429            (r'(?=[\s]*)(\w+)(?=[\s]*=)', Name.Variable.Global), 
    430            (r'(?=[^"]*)\'.*$', Comment.Single), 
    431            (r'"[^\n"]*"', String.Double), 
    432            (r'(END)(\s+)(FUNCTION|IF|SELECT|SUB)', 
    433             bygroups(Keyword.Reserved, Text.Whitespace, Keyword.Reserved)), 
    434            (r'(DECLARE)(\s+)([A-Z]+)(\s+)(\S+)', 
    435             bygroups(Keyword.Declaration, Text.Whitespace, Name.Variable, 
    436                      Text.Whitespace, Name)), 
    437            (r'(DIM)(\s+)(SHARED)(\s+)([^\s(]+)', 
    438             bygroups(Keyword.Declaration, Text.Whitespace, Name.Variable, 
    439                      Text.Whitespace, Name.Variable.Global)), 
    440            (r'(DIM)(\s+)([^\s(]+)', 
    441             bygroups(Keyword.Declaration, Text.Whitespace, Name.Variable.Global)), 
    442            (r'^(\s*)([a-zA-Z_]+)(\s*)(\=)', 
    443             bygroups(Text.Whitespace, Name.Variable.Global, Text.Whitespace, 
    444                      Operator)), 
    445            (r'(GOTO|GOSUB)(\s+)(\w+\:?)', 
    446             bygroups(Keyword.Reserved, Text.Whitespace, Name.Label)), 
    447            (r'(SUB)(\s+)(\w+\:?)', 
    448             bygroups(Keyword.Reserved, Text.Whitespace, Name.Label)), 
    449            include('declarations'), 
    450            include('functions'), 
    451            include('metacommands'), 
    452            include('operators'), 
    453            include('statements'), 
    454            include('keywords'), 
    455            (r'[a-zA-Z_]\w*[$@#&!]', Name.Variable.Global), 
    456            (r'[a-zA-Z_]\w*\:', Name.Label), 
    457            (r'\-?\d*\.\d+[@|#]?', Number.Float), 
    458            (r'\-?\d+[@|#]', Number.Float), 
    459            (r'\-?\d+#?', Number.Integer.Long), 
    460            (r'\-?\d+#?', Number.Integer), 
    461            (r'!=|==|:=|\.=|<<|>>|[-~+/\\*%=<>&^|?:!.]', Operator), 
    462            (r'[\[\]{}(),;]', Punctuation), 
    463            (r'[\w]+', Name.Variable.Global), 
    464        ], 
    465        # can't use regular \b because of X$() 
    466        # XXX: use words() here 
    467        'declarations': [ 
    468            (r'\b({})(?=\(|\b)'.format('|'.join(map(re.escape, declarations))), 
    469             Keyword.Declaration), 
    470        ], 
    471        'functions': [ 
    472            (r'\b({})(?=\(|\b)'.format('|'.join(map(re.escape, functions))), 
    473             Keyword.Reserved), 
    474        ], 
    475        'metacommands': [ 
    476            (r'\b({})(?=\(|\b)'.format('|'.join(map(re.escape, metacommands))), 
    477             Keyword.Constant), 
    478        ], 
    479        'operators': [ 
    480            (r'\b({})(?=\(|\b)'.format('|'.join(map(re.escape, operators))), Operator.Word), 
    481        ], 
    482        'statements': [ 
    483            (r'\b({})\b'.format('|'.join(map(re.escape, statements))), 
    484             Keyword.Reserved), 
    485        ], 
    486        'keywords': [ 
    487            (r'\b({})\b'.format('|'.join(keywords)), Keyword), 
    488        ], 
    489    } 
    490 
    491    def analyse_text(text): 
    492        if '$DYNAMIC' in text or '$STATIC' in text: 
    493            return 0.9 
    494 
    495 
    496class VBScriptLexer(RegexLexer): 
    497    """ 
    498    VBScript is scripting language that is modeled on Visual Basic. 
    499    """ 
    500    name = 'VBScript' 
    501    aliases = ['vbscript'] 
    502    filenames = ['*.vbs', '*.VBS'] 
    503    url = 'https://learn.microsoft.com/en-us/previous-versions/t0aew7h6(v=vs.85)' 
    504    version_added = '2.4' 
    505 
    506    flags = re.IGNORECASE 
    507 
    508    tokens = { 
    509        'root': [ 
    510            (r"'[^\n]*", Comment.Single), 
    511            (r'\s+', Whitespace), 
    512            ('"', String.Double, 'string'), 
    513            ('&h[0-9a-f]+', Number.Hex), 
    514            # Float variant 1, for example: 1., 1.e2, 1.2e3 
    515            (r'[0-9]+\.[0-9]*(e[+-]?[0-9]+)?', Number.Float), 
    516            (r'\.[0-9]+(e[+-]?[0-9]+)?', Number.Float),  # Float variant 2, for example: .1, .1e2 
    517            (r'[0-9]+e[+-]?[0-9]+', Number.Float),  # Float variant 3, for example: 123e45 
    518            (r'[0-9]+', Number.Integer), 
    519            ('#.+#', String),  # date or time value 
    520            (r'(dim)(\s+)([a-z_][a-z0-9_]*)', 
    521             bygroups(Keyword.Declaration, Whitespace, Name.Variable), 'dim_more'), 
    522            (r'(function|sub)(\s+)([a-z_][a-z0-9_]*)', 
    523             bygroups(Keyword.Declaration, Whitespace, Name.Function)), 
    524            (r'(class)(\s+)([a-z_][a-z0-9_]*)', 
    525             bygroups(Keyword.Declaration, Whitespace, Name.Class)), 
    526            (r'(const)(\s+)([a-z_][a-z0-9_]*)', 
    527             bygroups(Keyword.Declaration, Whitespace, Name.Constant)), 
    528            (r'(end)(\s+)(class|function|if|property|sub|with)', 
    529             bygroups(Keyword, Whitespace, Keyword)), 
    530            (r'(on)(\s+)(error)(\s+)(goto)(\s+)(0)', 
    531             bygroups(Keyword, Whitespace, Keyword, Whitespace, Keyword, Whitespace, Number.Integer)), 
    532            (r'(on)(\s+)(error)(\s+)(resume)(\s+)(next)', 
    533             bygroups(Keyword, Whitespace, Keyword, Whitespace, Keyword, Whitespace, Keyword)), 
    534            (r'(option)(\s+)(explicit)', bygroups(Keyword, Whitespace, Keyword)), 
    535            (r'(property)(\s+)(get|let|set)(\s+)([a-z_][a-z0-9_]*)', 
    536             bygroups(Keyword.Declaration, Whitespace, Keyword.Declaration, Whitespace, Name.Property)), 
    537            (r'rem\s.*[^\n]*', Comment.Single), 
    538            (words(_vbscript_builtins.KEYWORDS, suffix=r'\b'), Keyword), 
    539            (words(_vbscript_builtins.OPERATORS), Operator), 
    540            (words(_vbscript_builtins.OPERATOR_WORDS, suffix=r'\b'), Operator.Word), 
    541            (words(_vbscript_builtins.BUILTIN_CONSTANTS, suffix=r'\b'), Name.Constant), 
    542            (words(_vbscript_builtins.BUILTIN_FUNCTIONS, suffix=r'\b'), Name.Builtin), 
    543            (words(_vbscript_builtins.BUILTIN_VARIABLES, suffix=r'\b'), Name.Builtin), 
    544            (r'[a-z_][a-z0-9_]*', Name), 
    545            (r'\b_\n', Operator), 
    546            (words(r'(),.:'), Punctuation), 
    547            (r'.+(\n)?', Error) 
    548        ], 
    549        'dim_more': [ 
    550            (r'(\s*)(,)(\s*)([a-z_][a-z0-9]*)', 
    551             bygroups(Whitespace, Punctuation, Whitespace, Name.Variable)), 
    552            default('#pop'), 
    553        ], 
    554        'string': [ 
    555            (r'[^"\n]+', String.Double), 
    556            (r'\"\"', String.Double), 
    557            (r'"', String.Double, '#pop'), 
    558            (r'\n', Error, '#pop'),  # Unterminated string 
    559        ], 
    560    } 
    561 
    562 
    563class BBCBasicLexer(RegexLexer): 
    564    """ 
    565    BBC Basic was supplied on the BBC Micro, and later Acorn RISC OS. 
    566    It is also used by BBC Basic For Windows. 
    567    """ 
    568    base_keywords = ['OTHERWISE', 'AND', 'DIV', 'EOR', 'MOD', 'OR', 'ERROR', 
    569                     'LINE', 'OFF', 'STEP', 'SPC', 'TAB', 'ELSE', 'THEN', 
    570                     'OPENIN', 'PTR', 'PAGE', 'TIME', 'LOMEM', 'HIMEM', 'ABS', 
    571                     'ACS', 'ADVAL', 'ASC', 'ASN', 'ATN', 'BGET', 'COS', 'COUNT', 
    572                     'DEG', 'ERL', 'ERR', 'EVAL', 'EXP', 'EXT', 'FALSE', 'FN', 
    573                     'GET', 'INKEY', 'INSTR', 'INT', 'LEN', 'LN', 'LOG', 'NOT', 
    574                     'OPENUP', 'OPENOUT', 'PI', 'POINT', 'POS', 'RAD', 'RND', 
    575                     'SGN', 'SIN', 'SQR', 'TAN', 'TO', 'TRUE', 'USR', 'VAL', 
    576                     'VPOS', 'CHR$', 'GET$', 'INKEY$', 'LEFT$', 'MID$', 
    577                     'RIGHT$', 'STR$', 'STRING$', 'EOF', 'PTR', 'PAGE', 'TIME', 
    578                     'LOMEM', 'HIMEM', 'SOUND', 'BPUT', 'CALL', 'CHAIN', 'CLEAR', 
    579                     'CLOSE', 'CLG', 'CLS', 'DATA', 'DEF', 'DIM', 'DRAW', 'END', 
    580                     'ENDPROC', 'ENVELOPE', 'FOR', 'GOSUB', 'GOTO', 'GCOL', 'IF', 
    581                     'INPUT', 'LET', 'LOCAL', 'MODE', 'MOVE', 'NEXT', 'ON', 
    582                     'VDU', 'PLOT', 'PRINT', 'PROC', 'READ', 'REM', 'REPEAT', 
    583                     'REPORT', 'RESTORE', 'RETURN', 'RUN', 'STOP', 'COLOUR', 
    584                     'TRACE', 'UNTIL', 'WIDTH', 'OSCLI'] 
    585 
    586    basic5_keywords = ['WHEN', 'OF', 'ENDCASE', 'ENDIF', 'ENDWHILE', 'CASE', 
    587                       'CIRCLE', 'FILL', 'ORIGIN', 'POINT', 'RECTANGLE', 'SWAP', 
    588                       'WHILE', 'WAIT', 'MOUSE', 'QUIT', 'SYS', 'INSTALL', 
    589                       'LIBRARY', 'TINT', 'ELLIPSE', 'BEATS', 'TEMPO', 'VOICES', 
    590                       'VOICE', 'STEREO', 'OVERLAY', 'APPEND', 'AUTO', 'CRUNCH', 
    591                       'DELETE', 'EDIT', 'HELP', 'LIST', 'LOAD', 'LVAR', 'NEW', 
    592                       'OLD', 'RENUMBER', 'SAVE', 'TEXTLOAD', 'TEXTSAVE', 
    593                       'TWIN', 'TWINO', 'INSTALL', 'SUM', 'BEAT'] 
    594 
    595 
    596    name = 'BBC Basic' 
    597    aliases = ['bbcbasic'] 
    598    filenames = ['*.bbc'] 
    599    url = 'https://www.bbcbasic.co.uk/bbcbasic.html' 
    600    version_added = '2.4' 
    601 
    602    tokens = { 
    603        'root': [ 
    604            (r"[0-9]+", Name.Label), 
    605            (r"(\*)([^\n]*)", 
    606             bygroups(Keyword.Pseudo, Comment.Special)), 
    607            default('code'), 
    608        ], 
    609 
    610        'code': [ 
    611            (r"(REM)([^\n]*)", 
    612             bygroups(Keyword.Declaration, Comment.Single)), 
    613            (r'\n', Whitespace, 'root'), 
    614            (r'\s+', Whitespace), 
    615            (r':', Comment.Preproc), 
    616 
    617            # Some special cases to make functions come out nicer 
    618            (r'(DEF)(\s*)(FN|PROC)([A-Za-z_@][\w@]*)', 
    619             bygroups(Keyword.Declaration, Whitespace, 
    620                      Keyword.Declaration, Name.Function)), 
    621            (r'(FN|PROC)([A-Za-z_@][\w@]*)', 
    622             bygroups(Keyword, Name.Function)), 
    623 
    624            (r'(GOTO|GOSUB|THEN|RESTORE)(\s*)(\d+)', 
    625             bygroups(Keyword, Whitespace, Name.Label)), 
    626 
    627            (r'(TRUE|FALSE)', Keyword.Constant), 
    628            (r'(PAGE|LOMEM|HIMEM|TIME|WIDTH|ERL|ERR|REPORT\$|POS|VPOS|VOICES)', 
    629             Keyword.Pseudo), 
    630 
    631            (words(base_keywords), Keyword), 
    632            (words(basic5_keywords), Keyword), 
    633 
    634            ('"', String.Double, 'string'), 
    635 
    636            ('%[01]{1,32}', Number.Bin), 
    637            ('&[0-9a-f]{1,8}', Number.Hex), 
    638 
    639            (r'[+-]?[0-9]+\.[0-9]*(E[+-]?[0-9]+)?', Number.Float), 
    640            (r'[+-]?\.[0-9]+(E[+-]?[0-9]+)?', Number.Float), 
    641            (r'[+-]?[0-9]+E[+-]?[0-9]+', Number.Float), 
    642            (r'[+-]?\d+', Number.Integer), 
    643 
    644            (r'([A-Za-z_@][\w@]*[%$]?)', Name.Variable), 
    645            (r'([+\-]=|[$!|?+\-*/%^=><();]|>=|<=|<>|<<|>>|>>>|,)', Operator), 
    646        ], 
    647        'string': [ 
    648            (r'[^"\n]+', String.Double), 
    649            (r'"', String.Double, '#pop'), 
    650            (r'\n', Error, 'root'),  # Unterminated string 
    651        ], 
    652    } 
    653 
    654    def analyse_text(text): 
    655        if text.startswith('10REM >') or text.startswith('REM >'): 
    656            return 0.9