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;
 |