516 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			516 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * @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;
 | 
