/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ 'use strict'; export var conf = { comments: { lineComment: '#', }, brackets: [['{', '}'], ['[', ']'], ['(', ')']], autoClosingPairs: [ { open: '{', close: '}' }, { open: '[', close: ']' }, { open: '(', close: ')' }, { open: '"', close: '"' }, { open: "'", close: "'" }, { open: '`', close: '`' }, ], surroundingPairs: [ { open: '{', close: '}' }, { open: '[', close: ']' }, { open: '(', close: ')' }, { open: '"', close: '"' }, { open: "'", close: "'" }, { open: '`', close: '`' }, ], }; export var language = { defaultToken: '', tokenPostfix: '.perl', brackets: [ { token: 'delimiter.bracket', open: '{', close: '}' }, { token: 'delimiter.parenthesis', open: '(', close: ')' }, { token: 'delimiter.square', open: '[', close: ']' }, ], // https://learn.perl.org/docs/keywords.html // Perl syntax keywords: [ '__DATA__', 'else', 'lock', '__END__', 'elsif', 'lt', '__FILE__', 'eq', '__LINE__', 'exp', 'ne', 'sub', '__PACKAGE__', 'for', 'no', 'and', 'foreach', 'or', 'unless', 'cmp', 'ge', 'package', 'until', 'continue', 'gt', 'while', 'CORE', 'if', 'xor', 'do', 'le', '__DIE__', '__WARN__', ], // Perl functions builtinFunctions: [ '-A', 'END', 'length', 'setpgrp', '-B', 'endgrent', 'link', 'setpriority', '-b', 'endhostent', 'listen', 'setprotoent', '-C', 'endnetent', 'local', 'setpwent', '-c', 'endprotoent', 'localtime', 'setservent', '-d', 'endpwent', 'log', 'setsockopt', '-e', 'endservent', 'lstat', 'shift', '-f', 'eof', 'map', 'shmctl', '-g', 'eval', 'mkdir', 'shmget', '-k', 'exec', 'msgctl', 'shmread', '-l', 'exists', 'msgget', 'shmwrite', '-M', 'exit', 'msgrcv', 'shutdown', '-O', 'fcntl', 'msgsnd', 'sin', '-o', 'fileno', 'my', 'sleep', '-p', 'flock', 'next', 'socket', '-r', 'fork', 'not', 'socketpair', '-R', 'format', 'oct', 'sort', '-S', 'formline', 'open', 'splice', '-s', 'getc', 'opendir', 'split', '-T', 'getgrent', 'ord', 'sprintf', '-t', 'getgrgid', 'our', 'sqrt', '-u', 'getgrnam', 'pack', 'srand', '-w', 'gethostbyaddr', 'pipe', 'stat', '-W', 'gethostbyname', 'pop', 'state', '-X', 'gethostent', 'pos', 'study', '-x', 'getlogin', 'print', 'substr', '-z', 'getnetbyaddr', 'printf', 'symlink', 'abs', 'getnetbyname', 'prototype', 'syscall', 'accept', 'getnetent', 'push', 'sysopen', 'alarm', 'getpeername', 'quotemeta', 'sysread', 'atan2', 'getpgrp', 'rand', 'sysseek', 'AUTOLOAD', 'getppid', 'read', 'system', 'BEGIN', 'getpriority', 'readdir', 'syswrite', 'bind', 'getprotobyname', 'readline', 'tell', 'binmode', 'getprotobynumber', 'readlink', 'telldir', 'bless', 'getprotoent', 'readpipe', 'tie', 'break', 'getpwent', 'recv', 'tied', 'caller', 'getpwnam', 'redo', 'time', 'chdir', 'getpwuid', 'ref', 'times', 'CHECK', 'getservbyname', 'rename', 'truncate', 'chmod', 'getservbyport', 'require', 'uc', 'chomp', 'getservent', 'reset', 'ucfirst', 'chop', 'getsockname', 'return', 'umask', 'chown', 'getsockopt', 'reverse', 'undef', 'chr', 'glob', 'rewinddir', 'UNITCHECK', 'chroot', 'gmtime', 'rindex', 'unlink', 'close', 'goto', 'rmdir', 'unpack', 'closedir', 'grep', 'say', 'unshift', 'connect', 'hex', 'scalar', 'untie', 'cos', 'index', 'seek', 'use', 'crypt', 'INIT', 'seekdir', 'utime', 'dbmclose', 'int', 'select', 'values', 'dbmopen', 'ioctl', 'semctl', 'vec', 'defined', 'join', 'semget', 'wait', 'delete', 'keys', 'semop', 'waitpid', 'DESTROY', 'kill', 'send', 'wantarray', 'die', 'last', 'setgrent', 'warn', 'dump', 'lc', 'sethostent', 'write', 'each', 'lcfirst', 'setnetent', ], // File handlers builtinFileHandlers: ['ARGV', 'STDERR', 'STDOUT', 'ARGVOUT', 'STDIN', 'ENV'], // Perl variables builtinVariables: [ '$!', '$^RE_TRIE_MAXBUF', '$LAST_REGEXP_CODE_RESULT', '$"', '$^S', '$LIST_SEPARATOR', '$#', '$^T', '$MATCH', '$$', '$^TAINT', '$MULTILINE_MATCHING', '$%', '$^UNICODE', '$NR', '$&', '$^UTF8LOCALE', '$OFMT', "$'", '$^V', '$OFS', '$(', '$^W', '$ORS', '$)', '$^WARNING_BITS', '$OS_ERROR', '$*', '$^WIDE_SYSTEM_CALLS', '$OSNAME', '$+', '$^X', '$OUTPUT_AUTO_FLUSH', '$,', '$_', '$OUTPUT_FIELD_SEPARATOR', '$-', '$`', '$OUTPUT_RECORD_SEPARATOR', '$.', '$a', '$PERL_VERSION', '$/', '$ACCUMULATOR', '$PERLDB', '$0', '$ARG', '$PID', '$:', '$ARGV', '$POSTMATCH', '$;', '$b', '$PREMATCH', '$<', '$BASETIME', '$PROCESS_ID', '$=', '$CHILD_ERROR', '$PROGRAM_NAME', '$>', '$COMPILING', '$REAL_GROUP_ID', '$?', '$DEBUGGING', '$REAL_USER_ID', '$@', '$EFFECTIVE_GROUP_ID', '$RS', '$[', '$EFFECTIVE_USER_ID', '$SUBSCRIPT_SEPARATOR', '$\\', '$EGID', '$SUBSEP', '$]', '$ERRNO', '$SYSTEM_FD_MAX', '$^', '$EUID', '$UID', '$^A', '$EVAL_ERROR', '$WARNING', '$^C', '$EXCEPTIONS_BEING_CAUGHT', '$|', '$^CHILD_ERROR_NATIVE', '$EXECUTABLE_NAME', '$~', '$^D', '$EXTENDED_OS_ERROR', '%!', '$^E', '$FORMAT_FORMFEED', '%^H', '$^ENCODING', '$FORMAT_LINE_BREAK_CHARACTERS', '%ENV', '$^F', '$FORMAT_LINES_LEFT', '%INC', '$^H', '$FORMAT_LINES_PER_PAGE', '%OVERLOAD', '$^I', '$FORMAT_NAME', '%SIG', '$^L', '$FORMAT_PAGE_NUMBER', '@+', '$^M', '$FORMAT_TOP_NAME', '@-', '$^N', '$GID', '@_', '$^O', '$INPLACE_EDIT', '@ARGV', '$^OPEN', '$INPUT_LINE_NUMBER', '@INC', '$^P', '$INPUT_RECORD_SEPARATOR', '@LAST_MATCH_START', '$^R', '$LAST_MATCH_END', '$^RE_DEBUG_FLAGS', '$LAST_PAREN_MATCH', ], // operators symbols: /[:+\-\^*$&%@=<>!?|\/~\.]/, quoteLikeOps: ['qr', 'm', 's', 'q', 'qq', 'qx', 'qw', 'tr', 'y'], escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/, // The main tokenizer for our languages tokenizer: { root: [ { include: '@whitespace' }, [ /[a-zA-Z\-_][\w\-_]*/, { cases: { '@keywords': 'keyword', '@builtinFunctions': 'type.identifier', '@builtinFileHandlers': 'variable.predefined', '@quoteLikeOps': { token: '@rematch', next: 'quotedConstructs' }, '@default': '', }, }, ], // Perl variables [ /[\$@%][*@#?\+\-\$!\w\\\^><~:;\.]+/, { cases: { '@builtinVariables': 'variable.predefined', '@default': 'variable', }, }, ], { include: '@strings' }, { include: '@dblStrings' }, // Perl Doc { include: '@perldoc' }, // Here Doc { include: '@heredoc' }, [/[{}\[\]()]/, '@brackets'], // RegExp [ /[\/](?:(?:\[(?:\\]|[^\]])+\])|(?:\\\/|[^\]\/]))*[\/]\w*\s*(?=[).,;]|$)/, 'regexp', ], [/@symbols/, 'operators'], { include: '@numbers' }, [/[,;]/, 'delimiter'], ], whitespace: [ [/\s+/, 'white'], [/(^#!.*$)/, 'metatag'], [/(^#.*$)/, 'comment'], ], numbers: [ [/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'], [/0[xX][0-9a-fA-F_]*[0-9a-fA-F]/, 'number.hex'], [/\d+/, 'number'], ], // Single quote string strings: [[/'/, 'string', '@stringBody']], stringBody: [ [/'/, 'string', '@popall'], [/\\'/, 'string.escape'], [/./, 'string'], ], // Double quote string dblStrings: [[/"/, 'string', '@dblStringBody']], dblStringBody: [ [/"/, 'string', '@popall'], [/@escapes/, 'string.escape'], [/\\./, 'string.escape.invalid'], { include: '@variables' }, [/./, 'string'], ], // Quoted constructs // Percent strings in Ruby are similar to quote-like operators in Perl. // This is adapted from pstrings in ../ruby/ruby.ts. quotedConstructs: [ [/(q|qw|tr|y)\s*\(/, { token: 'string.delim', switchTo: '@qstring.(.)' }], [/(q|qw|tr|y)\s*\[/, { token: 'string.delim', switchTo: '@qstring.[.]' }], [/(q|qw|tr|y)\s*\{/, { token: 'string.delim', switchTo: '@qstring.{.}' }], [/(q|qw|tr|y)\s*' }], [/(q|qw|tr|y)#/, { token: 'string.delim', switchTo: '@qstring.#.#' }], [/(q|qw|tr|y)\s*([^A-Za-z0-9#\s])/, { token: 'string.delim', switchTo: '@qstring.$2.$2' }], [/(q|qw|tr|y)\s+(\w)/, { token: 'string.delim', switchTo: '@qstring.$2.$2' }], [/(qr|m|s)\s*\(/, { token: 'regexp.delim', switchTo: '@qregexp.(.)' }], [/(qr|m|s)\s*\[/, { token: 'regexp.delim', switchTo: '@qregexp.[.]' }], [/(qr|m|s)\s*\{/, { token: 'regexp.delim', switchTo: '@qregexp.{.}' }], [/(qr|m|s)\s*' }], [/(qr|m|s)#/, { token: 'regexp.delim', switchTo: '@qregexp.#.#' }], [/(qr|m|s)\s*([^A-Za-z0-9_#\s])/, { token: 'regexp.delim', switchTo: '@qregexp.$2.$2' }], [/(qr|m|s)\s+(\w)/, { token: 'regexp.delim', switchTo: '@qregexp.$2.$2' }], [/(qq|qx)\s*\(/, { token: 'string.delim', switchTo: '@qqstring.(.)' }], [/(qq|qx)\s*\[/, { token: 'string.delim', switchTo: '@qqstring.[.]' }], [/(qq|qx)\s*\{/, { token: 'string.delim', switchTo: '@qqstring.{.}' }], [/(qq|qx)\s*' }], [/(qq|qx)#/, { token: 'string.delim', switchTo: '@qqstring.#.#' }], [/(qq|qx)\s*([^A-Za-z0-9#\s])/, { token: 'string.delim', switchTo: '@qqstring.$2.$2' }], [/(qq|qx)\s+(\w)/, { token: 'string.delim', switchTo: '@qqstring.$2.$2' }], ], // Non-expanded quoted string // qstring. // open = open delimiter // close = close delimiter qstring: [ [/\\./, 'string.escape'], [/./, { cases: { '$#==$S3': { token: 'string.delim', next: '@pop' }, '$#==$S2': { token: 'string.delim', next: '@push' }, '@default': 'string' } }], ], // Quoted regexp // qregexp.. // open = open delimiter // close = close delimiter qregexp: [ { include: '@variables' }, [/\\./, 'regexp.escape'], [/./, { cases: { '$#==$S3': { token: 'regexp.delim', next: '@regexpModifiers' }, '$#==$S2': { token: 'regexp.delim', next: '@push' }, '@default': 'regexp' } }], ], regexpModifiers: [ [/[msixpodualngcer]+/, { token: 'regexp.modifier', next: '@popall' }], ], // Expanded quoted string // qqstring.. // open = open delimiter // close = close delimiter qqstring: [ { include: '@variables' }, { include: '@qstring' }, ], heredoc: [ [ /<<\s*['"`]?([\w\-]+)['"`]?/, { token: 'string.heredoc.delimiter', next: '@heredocBody.$1' }, ], ], heredocBody: [ [ /^([\w\-]+)$/, { cases: { '$1==$S2': [{ token: 'string.heredoc.delimiter', next: '@popall' }], '@default': 'string.heredoc', }, }, ], [/./, 'string.heredoc'], ], perldoc: [[/^=\w/, 'comment.doc', '@perldocBody']], perldocBody: [ [/^=cut\b/, 'type.identifier', '@popall'], [/./, 'comment.doc'], ], variables: [ [/\$\w+/, 'variable'], [/@\w+/, 'variable'], [/%\w+/, 'variable'], ], }, };