123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515 |
- /**
- * @param {string} value
- * @returns {RegExp}
- * */
- /**
- * @param {RegExp | string } re
- * @returns {string}
- */
- function source(re) {
- if (!re) return null;
- if (typeof re === "string") return re;
- return re.source;
- }
- /**
- * @param {...(RegExp | string) } args
- * @returns {string}
- */
- function concat(...args) {
- const joined = args.map((x) => source(x)).join("");
- return joined;
- }
- /**
- * Any of the passed expresssions may match
- *
- * Creates a huge this | this | that | that match
- * @param {(RegExp | string)[] } args
- * @returns {string}
- */
- function either(...args) {
- const joined = '(' + args.map((x) => source(x)).join("|") + ")";
- return joined;
- }
- /*
- Language: Perl
- Author: Peter Leonov <gojpeg@yandex.ru>
- Website: https://www.perl.org
- Category: common
- */
- /** @type LanguageFn */
- function perl(hljs) {
- const KEYWORDS = [
- 'abs',
- 'accept',
- 'alarm',
- 'and',
- 'atan2',
- 'bind',
- 'binmode',
- 'bless',
- 'break',
- 'caller',
- 'chdir',
- 'chmod',
- 'chomp',
- 'chop',
- 'chown',
- 'chr',
- 'chroot',
- 'close',
- 'closedir',
- 'connect',
- 'continue',
- 'cos',
- 'crypt',
- 'dbmclose',
- 'dbmopen',
- 'defined',
- 'delete',
- 'die',
- 'do',
- 'dump',
- 'each',
- 'else',
- 'elsif',
- 'endgrent',
- 'endhostent',
- 'endnetent',
- 'endprotoent',
- 'endpwent',
- 'endservent',
- 'eof',
- 'eval',
- 'exec',
- 'exists',
- 'exit',
- 'exp',
- 'fcntl',
- 'fileno',
- 'flock',
- 'for',
- 'foreach',
- 'fork',
- 'format',
- 'formline',
- 'getc',
- 'getgrent',
- 'getgrgid',
- 'getgrnam',
- 'gethostbyaddr',
- 'gethostbyname',
- 'gethostent',
- 'getlogin',
- 'getnetbyaddr',
- 'getnetbyname',
- 'getnetent',
- 'getpeername',
- 'getpgrp',
- 'getpriority',
- 'getprotobyname',
- 'getprotobynumber',
- 'getprotoent',
- 'getpwent',
- 'getpwnam',
- 'getpwuid',
- 'getservbyname',
- 'getservbyport',
- 'getservent',
- 'getsockname',
- 'getsockopt',
- 'given',
- 'glob',
- 'gmtime',
- 'goto',
- 'grep',
- 'gt',
- 'hex',
- 'if',
- 'index',
- 'int',
- 'ioctl',
- 'join',
- 'keys',
- 'kill',
- 'last',
- 'lc',
- 'lcfirst',
- 'length',
- 'link',
- 'listen',
- 'local',
- 'localtime',
- 'log',
- 'lstat',
- 'lt',
- 'ma',
- 'map',
- 'mkdir',
- 'msgctl',
- 'msgget',
- 'msgrcv',
- 'msgsnd',
- 'my',
- 'ne',
- 'next',
- 'no',
- 'not',
- 'oct',
- 'open',
- 'opendir',
- 'or',
- 'ord',
- 'our',
- 'pack',
- 'package',
- 'pipe',
- 'pop',
- 'pos',
- 'print',
- 'printf',
- 'prototype',
- 'push',
- 'q|0',
- 'qq',
- 'quotemeta',
- 'qw',
- 'qx',
- 'rand',
- 'read',
- 'readdir',
- 'readline',
- 'readlink',
- 'readpipe',
- 'recv',
- 'redo',
- 'ref',
- 'rename',
- 'require',
- 'reset',
- 'return',
- 'reverse',
- 'rewinddir',
- 'rindex',
- 'rmdir',
- 'say',
- 'scalar',
- 'seek',
- 'seekdir',
- 'select',
- 'semctl',
- 'semget',
- 'semop',
- 'send',
- 'setgrent',
- 'sethostent',
- 'setnetent',
- 'setpgrp',
- 'setpriority',
- 'setprotoent',
- 'setpwent',
- 'setservent',
- 'setsockopt',
- 'shift',
- 'shmctl',
- 'shmget',
- 'shmread',
- 'shmwrite',
- 'shutdown',
- 'sin',
- 'sleep',
- 'socket',
- 'socketpair',
- 'sort',
- 'splice',
- 'split',
- 'sprintf',
- 'sqrt',
- 'srand',
- 'stat',
- 'state',
- 'study',
- 'sub',
- 'substr',
- 'symlink',
- 'syscall',
- 'sysopen',
- 'sysread',
- 'sysseek',
- 'system',
- 'syswrite',
- 'tell',
- 'telldir',
- 'tie',
- 'tied',
- 'time',
- 'times',
- 'tr',
- 'truncate',
- 'uc',
- 'ucfirst',
- 'umask',
- 'undef',
- 'unless',
- 'unlink',
- 'unpack',
- 'unshift',
- 'untie',
- 'until',
- 'use',
- 'utime',
- 'values',
- 'vec',
- 'wait',
- 'waitpid',
- 'wantarray',
- 'warn',
- 'when',
- 'while',
- 'write',
- 'x|0',
- 'xor',
- 'y|0'
- ];
- // https://perldoc.perl.org/perlre#Modifiers
- const REGEX_MODIFIERS = /[dualxmsipngr]{0,12}/; // aa and xx are valid, making max length 12
- const PERL_KEYWORDS = {
- $pattern: /[\w.]+/,
- keyword: KEYWORDS.join(" ")
- };
- const SUBST = {
- className: 'subst',
- begin: '[$@]\\{',
- end: '\\}',
- keywords: PERL_KEYWORDS
- };
- const METHOD = {
- begin: /->\{/,
- end: /\}/
- // contains defined later
- };
- const VAR = {
- variants: [
- {
- begin: /\$\d/
- },
- {
- begin: concat(
- /[$%@](\^\w\b|#\w+(::\w+)*|\{\w+\}|\w+(::\w*)*)/,
- // negative look-ahead tries to avoid matching patterns that are not
- // Perl at all like $ident$, @ident@, etc.
- `(?![A-Za-z])(?![@$%])`
- )
- },
- {
- begin: /[$%@][^\s\w{]/,
- relevance: 0
- }
- ]
- };
- const STRING_CONTAINS = [
- hljs.BACKSLASH_ESCAPE,
- SUBST,
- VAR
- ];
- const REGEX_DELIMS = [
- /!/,
- /\//,
- /\|/,
- /\?/,
- /'/,
- /"/, // valid but infrequent and weird
- /#/ // valid but infrequent and weird
- ];
- /**
- * @param {string|RegExp} prefix
- * @param {string|RegExp} open
- * @param {string|RegExp} close
- */
- const PAIRED_DOUBLE_RE = (prefix, open, close = '\\1') => {
- const middle = (close === '\\1')
- ? close
- : concat(close, open);
- return concat(
- concat("(?:", prefix, ")"),
- open,
- /(?:\\.|[^\\\/])*?/,
- middle,
- /(?:\\.|[^\\\/])*?/,
- close,
- REGEX_MODIFIERS
- );
- };
- /**
- * @param {string|RegExp} prefix
- * @param {string|RegExp} open
- * @param {string|RegExp} close
- */
- const PAIRED_RE = (prefix, open, close) => {
- return concat(
- concat("(?:", prefix, ")"),
- open,
- /(?:\\.|[^\\\/])*?/,
- close,
- REGEX_MODIFIERS
- );
- };
- const PERL_DEFAULT_CONTAINS = [
- VAR,
- hljs.HASH_COMMENT_MODE,
- hljs.COMMENT(
- /^=\w/,
- /=cut/,
- {
- endsWithParent: true
- }
- ),
- METHOD,
- {
- className: 'string',
- contains: STRING_CONTAINS,
- variants: [
- {
- begin: 'q[qwxr]?\\s*\\(',
- end: '\\)',
- relevance: 5
- },
- {
- begin: 'q[qwxr]?\\s*\\[',
- end: '\\]',
- relevance: 5
- },
- {
- begin: 'q[qwxr]?\\s*\\{',
- end: '\\}',
- relevance: 5
- },
- {
- begin: 'q[qwxr]?\\s*\\|',
- end: '\\|',
- relevance: 5
- },
- {
- begin: 'q[qwxr]?\\s*<',
- end: '>',
- relevance: 5
- },
- {
- begin: 'qw\\s+q',
- end: 'q',
- relevance: 5
- },
- {
- begin: '\'',
- end: '\'',
- contains: [ hljs.BACKSLASH_ESCAPE ]
- },
- {
- begin: '"',
- end: '"'
- },
- {
- begin: '`',
- end: '`',
- contains: [ hljs.BACKSLASH_ESCAPE ]
- },
- {
- begin: /\{\w+\}/,
- relevance: 0
- },
- {
- begin: '-?\\w+\\s*=>',
- relevance: 0
- }
- ]
- },
- {
- className: 'number',
- begin: '(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b',
- relevance: 0
- },
- { // regexp container
- begin: '(\\/\\/|' + hljs.RE_STARTERS_RE + '|\\b(split|return|print|reverse|grep)\\b)\\s*',
- keywords: 'split return print reverse grep',
- relevance: 0,
- contains: [
- hljs.HASH_COMMENT_MODE,
- {
- className: 'regexp',
- variants: [
- // allow matching common delimiters
- { begin: PAIRED_DOUBLE_RE("s|tr|y", either(...REGEX_DELIMS)) },
- // and then paired delmis
- { begin: PAIRED_DOUBLE_RE("s|tr|y", "\\(", "\\)") },
- { begin: PAIRED_DOUBLE_RE("s|tr|y", "\\[", "\\]") },
- { begin: PAIRED_DOUBLE_RE("s|tr|y", "\\{", "\\}") }
- ],
- relevance: 2
- },
- {
- className: 'regexp',
- variants: [
- {
- // could be a comment in many languages so do not count
- // as relevant
- begin: /(m|qr)\/\//,
- relevance: 0
- },
- // prefix is optional with /regex/
- { begin: PAIRED_RE("(?:m|qr)?", /\//, /\//)},
- // allow matching common delimiters
- { begin: PAIRED_RE("m|qr", either(...REGEX_DELIMS), /\1/)},
- // allow common paired delmins
- { begin: PAIRED_RE("m|qr", /\(/, /\)/)},
- { begin: PAIRED_RE("m|qr", /\[/, /\]/)},
- { begin: PAIRED_RE("m|qr", /\{/, /\}/)}
- ]
- }
- ]
- },
- {
- className: 'function',
- beginKeywords: 'sub',
- end: '(\\s*\\(.*?\\))?[;{]',
- excludeEnd: true,
- relevance: 5,
- contains: [ hljs.TITLE_MODE ]
- },
- {
- begin: '-\\w\\b',
- relevance: 0
- },
- {
- begin: "^__DATA__$",
- end: "^__END__$",
- subLanguage: 'mojolicious',
- contains: [
- {
- begin: "^@@.*",
- end: "$",
- className: "comment"
- }
- ]
- }
- ];
- SUBST.contains = PERL_DEFAULT_CONTAINS;
- METHOD.contains = PERL_DEFAULT_CONTAINS;
- return {
- name: 'Perl',
- aliases: [
- 'pl',
- 'pm'
- ],
- keywords: PERL_KEYWORDS,
- contains: PERL_DEFAULT_CONTAINS
- };
- }
- module.exports = perl;
|