447 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			447 lines
		
	
	
		
			8.6 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 } re
 | 
						|
 * @returns {string}
 | 
						|
 */
 | 
						|
function lookahead(re) {
 | 
						|
  return concat('(?=', re, ')');
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @param {...(RegExp | string) } args
 | 
						|
 * @returns {string}
 | 
						|
 */
 | 
						|
function concat(...args) {
 | 
						|
  const joined = args.map((x) => source(x)).join("");
 | 
						|
  return joined;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
Language: Python
 | 
						|
Description: Python is an interpreted, object-oriented, high-level programming language with dynamic semantics.
 | 
						|
Website: https://www.python.org
 | 
						|
Category: common
 | 
						|
*/
 | 
						|
 | 
						|
function python(hljs) {
 | 
						|
  const RESERVED_WORDS = [
 | 
						|
    'and',
 | 
						|
    'as',
 | 
						|
    'assert',
 | 
						|
    'async',
 | 
						|
    'await',
 | 
						|
    'break',
 | 
						|
    'class',
 | 
						|
    'continue',
 | 
						|
    'def',
 | 
						|
    'del',
 | 
						|
    'elif',
 | 
						|
    'else',
 | 
						|
    'except',
 | 
						|
    'finally',
 | 
						|
    'for',
 | 
						|
    'from',
 | 
						|
    'global',
 | 
						|
    'if',
 | 
						|
    'import',
 | 
						|
    'in',
 | 
						|
    'is',
 | 
						|
    'lambda',
 | 
						|
    'nonlocal|10',
 | 
						|
    'not',
 | 
						|
    'or',
 | 
						|
    'pass',
 | 
						|
    'raise',
 | 
						|
    'return',
 | 
						|
    'try',
 | 
						|
    'while',
 | 
						|
    'with',
 | 
						|
    'yield'
 | 
						|
  ];
 | 
						|
 | 
						|
  const BUILT_INS = [
 | 
						|
    '__import__',
 | 
						|
    'abs',
 | 
						|
    'all',
 | 
						|
    'any',
 | 
						|
    'ascii',
 | 
						|
    'bin',
 | 
						|
    'bool',
 | 
						|
    'breakpoint',
 | 
						|
    'bytearray',
 | 
						|
    'bytes',
 | 
						|
    'callable',
 | 
						|
    'chr',
 | 
						|
    'classmethod',
 | 
						|
    'compile',
 | 
						|
    'complex',
 | 
						|
    'delattr',
 | 
						|
    'dict',
 | 
						|
    'dir',
 | 
						|
    'divmod',
 | 
						|
    'enumerate',
 | 
						|
    'eval',
 | 
						|
    'exec',
 | 
						|
    'filter',
 | 
						|
    'float',
 | 
						|
    'format',
 | 
						|
    'frozenset',
 | 
						|
    'getattr',
 | 
						|
    'globals',
 | 
						|
    'hasattr',
 | 
						|
    'hash',
 | 
						|
    'help',
 | 
						|
    'hex',
 | 
						|
    'id',
 | 
						|
    'input',
 | 
						|
    'int',
 | 
						|
    'isinstance',
 | 
						|
    'issubclass',
 | 
						|
    'iter',
 | 
						|
    'len',
 | 
						|
    'list',
 | 
						|
    'locals',
 | 
						|
    'map',
 | 
						|
    'max',
 | 
						|
    'memoryview',
 | 
						|
    'min',
 | 
						|
    'next',
 | 
						|
    'object',
 | 
						|
    'oct',
 | 
						|
    'open',
 | 
						|
    'ord',
 | 
						|
    'pow',
 | 
						|
    'print',
 | 
						|
    'property',
 | 
						|
    'range',
 | 
						|
    'repr',
 | 
						|
    'reversed',
 | 
						|
    'round',
 | 
						|
    'set',
 | 
						|
    'setattr',
 | 
						|
    'slice',
 | 
						|
    'sorted',
 | 
						|
    'staticmethod',
 | 
						|
    'str',
 | 
						|
    'sum',
 | 
						|
    'super',
 | 
						|
    'tuple',
 | 
						|
    'type',
 | 
						|
    'vars',
 | 
						|
    'zip'
 | 
						|
  ];
 | 
						|
 | 
						|
  const LITERALS = [
 | 
						|
    '__debug__',
 | 
						|
    'Ellipsis',
 | 
						|
    'False',
 | 
						|
    'None',
 | 
						|
    'NotImplemented',
 | 
						|
    'True'
 | 
						|
  ];
 | 
						|
 | 
						|
  // https://docs.python.org/3/library/typing.html
 | 
						|
  // TODO: Could these be supplemented by a CamelCase matcher in certain
 | 
						|
  // contexts, leaving these remaining only for relevance hinting?
 | 
						|
  const TYPES = [
 | 
						|
    "Any",
 | 
						|
    "Callable",
 | 
						|
    "Coroutine",
 | 
						|
    "Dict",
 | 
						|
    "List",
 | 
						|
    "Literal",
 | 
						|
    "Generic",
 | 
						|
    "Optional",
 | 
						|
    "Sequence",
 | 
						|
    "Set",
 | 
						|
    "Tuple",
 | 
						|
    "Type",
 | 
						|
    "Union"
 | 
						|
  ];
 | 
						|
 | 
						|
  const KEYWORDS = {
 | 
						|
    $pattern: /[A-Za-z]\w+|__\w+__/,
 | 
						|
    keyword: RESERVED_WORDS,
 | 
						|
    built_in: BUILT_INS,
 | 
						|
    literal: LITERALS,
 | 
						|
    type: TYPES
 | 
						|
  };
 | 
						|
 | 
						|
  const PROMPT = {
 | 
						|
    className: 'meta',
 | 
						|
    begin: /^(>>>|\.\.\.) /
 | 
						|
  };
 | 
						|
 | 
						|
  const SUBST = {
 | 
						|
    className: 'subst',
 | 
						|
    begin: /\{/,
 | 
						|
    end: /\}/,
 | 
						|
    keywords: KEYWORDS,
 | 
						|
    illegal: /#/
 | 
						|
  };
 | 
						|
 | 
						|
  const LITERAL_BRACKET = {
 | 
						|
    begin: /\{\{/,
 | 
						|
    relevance: 0
 | 
						|
  };
 | 
						|
 | 
						|
  const STRING = {
 | 
						|
    className: 'string',
 | 
						|
    contains: [ hljs.BACKSLASH_ESCAPE ],
 | 
						|
    variants: [
 | 
						|
      {
 | 
						|
        begin: /([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,
 | 
						|
        end: /'''/,
 | 
						|
        contains: [
 | 
						|
          hljs.BACKSLASH_ESCAPE,
 | 
						|
          PROMPT
 | 
						|
        ],
 | 
						|
        relevance: 10
 | 
						|
      },
 | 
						|
      {
 | 
						|
        begin: /([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,
 | 
						|
        end: /"""/,
 | 
						|
        contains: [
 | 
						|
          hljs.BACKSLASH_ESCAPE,
 | 
						|
          PROMPT
 | 
						|
        ],
 | 
						|
        relevance: 10
 | 
						|
      },
 | 
						|
      {
 | 
						|
        begin: /([fF][rR]|[rR][fF]|[fF])'''/,
 | 
						|
        end: /'''/,
 | 
						|
        contains: [
 | 
						|
          hljs.BACKSLASH_ESCAPE,
 | 
						|
          PROMPT,
 | 
						|
          LITERAL_BRACKET,
 | 
						|
          SUBST
 | 
						|
        ]
 | 
						|
      },
 | 
						|
      {
 | 
						|
        begin: /([fF][rR]|[rR][fF]|[fF])"""/,
 | 
						|
        end: /"""/,
 | 
						|
        contains: [
 | 
						|
          hljs.BACKSLASH_ESCAPE,
 | 
						|
          PROMPT,
 | 
						|
          LITERAL_BRACKET,
 | 
						|
          SUBST
 | 
						|
        ]
 | 
						|
      },
 | 
						|
      {
 | 
						|
        begin: /([uU]|[rR])'/,
 | 
						|
        end: /'/,
 | 
						|
        relevance: 10
 | 
						|
      },
 | 
						|
      {
 | 
						|
        begin: /([uU]|[rR])"/,
 | 
						|
        end: /"/,
 | 
						|
        relevance: 10
 | 
						|
      },
 | 
						|
      {
 | 
						|
        begin: /([bB]|[bB][rR]|[rR][bB])'/,
 | 
						|
        end: /'/
 | 
						|
      },
 | 
						|
      {
 | 
						|
        begin: /([bB]|[bB][rR]|[rR][bB])"/,
 | 
						|
        end: /"/
 | 
						|
      },
 | 
						|
      {
 | 
						|
        begin: /([fF][rR]|[rR][fF]|[fF])'/,
 | 
						|
        end: /'/,
 | 
						|
        contains: [
 | 
						|
          hljs.BACKSLASH_ESCAPE,
 | 
						|
          LITERAL_BRACKET,
 | 
						|
          SUBST
 | 
						|
        ]
 | 
						|
      },
 | 
						|
      {
 | 
						|
        begin: /([fF][rR]|[rR][fF]|[fF])"/,
 | 
						|
        end: /"/,
 | 
						|
        contains: [
 | 
						|
          hljs.BACKSLASH_ESCAPE,
 | 
						|
          LITERAL_BRACKET,
 | 
						|
          SUBST
 | 
						|
        ]
 | 
						|
      },
 | 
						|
      hljs.APOS_STRING_MODE,
 | 
						|
      hljs.QUOTE_STRING_MODE
 | 
						|
    ]
 | 
						|
  };
 | 
						|
 | 
						|
  // https://docs.python.org/3.9/reference/lexical_analysis.html#numeric-literals
 | 
						|
  const digitpart = '[0-9](_?[0-9])*';
 | 
						|
  const pointfloat = `(\\b(${digitpart}))?\\.(${digitpart})|\\b(${digitpart})\\.`;
 | 
						|
  const NUMBER = {
 | 
						|
    className: 'number',
 | 
						|
    relevance: 0,
 | 
						|
    variants: [
 | 
						|
      // exponentfloat, pointfloat
 | 
						|
      // https://docs.python.org/3.9/reference/lexical_analysis.html#floating-point-literals
 | 
						|
      // optionally imaginary
 | 
						|
      // https://docs.python.org/3.9/reference/lexical_analysis.html#imaginary-literals
 | 
						|
      // Note: no leading \b because floats can start with a decimal point
 | 
						|
      // and we don't want to mishandle e.g. `fn(.5)`,
 | 
						|
      // no trailing \b for pointfloat because it can end with a decimal point
 | 
						|
      // and we don't want to mishandle e.g. `0..hex()`; this should be safe
 | 
						|
      // because both MUST contain a decimal point and so cannot be confused with
 | 
						|
      // the interior part of an identifier
 | 
						|
      {
 | 
						|
        begin: `(\\b(${digitpart})|(${pointfloat}))[eE][+-]?(${digitpart})[jJ]?\\b`
 | 
						|
      },
 | 
						|
      {
 | 
						|
        begin: `(${pointfloat})[jJ]?`
 | 
						|
      },
 | 
						|
 | 
						|
      // decinteger, bininteger, octinteger, hexinteger
 | 
						|
      // https://docs.python.org/3.9/reference/lexical_analysis.html#integer-literals
 | 
						|
      // optionally "long" in Python 2
 | 
						|
      // https://docs.python.org/2.7/reference/lexical_analysis.html#integer-and-long-integer-literals
 | 
						|
      // decinteger is optionally imaginary
 | 
						|
      // https://docs.python.org/3.9/reference/lexical_analysis.html#imaginary-literals
 | 
						|
      {
 | 
						|
        begin: '\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?\\b'
 | 
						|
      },
 | 
						|
      {
 | 
						|
        begin: '\\b0[bB](_?[01])+[lL]?\\b'
 | 
						|
      },
 | 
						|
      {
 | 
						|
        begin: '\\b0[oO](_?[0-7])+[lL]?\\b'
 | 
						|
      },
 | 
						|
      {
 | 
						|
        begin: '\\b0[xX](_?[0-9a-fA-F])+[lL]?\\b'
 | 
						|
      },
 | 
						|
 | 
						|
      // imagnumber (digitpart-based)
 | 
						|
      // https://docs.python.org/3.9/reference/lexical_analysis.html#imaginary-literals
 | 
						|
      {
 | 
						|
        begin: `\\b(${digitpart})[jJ]\\b`
 | 
						|
      }
 | 
						|
    ]
 | 
						|
  };
 | 
						|
  const COMMENT_TYPE = {
 | 
						|
    className: "comment",
 | 
						|
    begin: lookahead(/# type:/),
 | 
						|
    end: /$/,
 | 
						|
    keywords: KEYWORDS,
 | 
						|
    contains: [
 | 
						|
      { // prevent keywords from coloring `type`
 | 
						|
        begin: /# type:/
 | 
						|
      },
 | 
						|
      // comment within a datatype comment includes no keywords
 | 
						|
      {
 | 
						|
        begin: /#/,
 | 
						|
        end: /\b\B/,
 | 
						|
        endsWithParent: true
 | 
						|
      }
 | 
						|
    ]
 | 
						|
  };
 | 
						|
  const PARAMS = {
 | 
						|
    className: 'params',
 | 
						|
    variants: [
 | 
						|
      // Exclude params in functions without params
 | 
						|
      {
 | 
						|
        className: "",
 | 
						|
        begin: /\(\s*\)/,
 | 
						|
        skip: true
 | 
						|
      },
 | 
						|
      {
 | 
						|
        begin: /\(/,
 | 
						|
        end: /\)/,
 | 
						|
        excludeBegin: true,
 | 
						|
        excludeEnd: true,
 | 
						|
        keywords: KEYWORDS,
 | 
						|
        contains: [
 | 
						|
          'self',
 | 
						|
          PROMPT,
 | 
						|
          NUMBER,
 | 
						|
          STRING,
 | 
						|
          hljs.HASH_COMMENT_MODE
 | 
						|
        ]
 | 
						|
      }
 | 
						|
    ]
 | 
						|
  };
 | 
						|
  SUBST.contains = [
 | 
						|
    STRING,
 | 
						|
    NUMBER,
 | 
						|
    PROMPT
 | 
						|
  ];
 | 
						|
 | 
						|
  return {
 | 
						|
    name: 'Python',
 | 
						|
    aliases: [
 | 
						|
      'py',
 | 
						|
      'gyp',
 | 
						|
      'ipython'
 | 
						|
    ],
 | 
						|
    keywords: KEYWORDS,
 | 
						|
    illegal: /(<\/|->|\?)|=>/,
 | 
						|
    contains: [
 | 
						|
      PROMPT,
 | 
						|
      NUMBER,
 | 
						|
      {
 | 
						|
        // very common convention
 | 
						|
        begin: /\bself\b/
 | 
						|
      },
 | 
						|
      {
 | 
						|
        // eat "if" prior to string so that it won't accidentally be
 | 
						|
        // labeled as an f-string
 | 
						|
        beginKeywords: "if",
 | 
						|
        relevance: 0
 | 
						|
      },
 | 
						|
      STRING,
 | 
						|
      COMMENT_TYPE,
 | 
						|
      hljs.HASH_COMMENT_MODE,
 | 
						|
      {
 | 
						|
        variants: [
 | 
						|
          {
 | 
						|
            className: 'function',
 | 
						|
            beginKeywords: 'def'
 | 
						|
          },
 | 
						|
          {
 | 
						|
            className: 'class',
 | 
						|
            beginKeywords: 'class'
 | 
						|
          }
 | 
						|
        ],
 | 
						|
        end: /:/,
 | 
						|
        illegal: /[${=;\n,]/,
 | 
						|
        contains: [
 | 
						|
          hljs.UNDERSCORE_TITLE_MODE,
 | 
						|
          PARAMS,
 | 
						|
          {
 | 
						|
            begin: /->/,
 | 
						|
            endsWithParent: true,
 | 
						|
            keywords: KEYWORDS
 | 
						|
          }
 | 
						|
        ]
 | 
						|
      },
 | 
						|
      {
 | 
						|
        className: 'meta',
 | 
						|
        begin: /^[\t ]*@/,
 | 
						|
        end: /(?=#)|$/,
 | 
						|
        contains: [
 | 
						|
          NUMBER,
 | 
						|
          PARAMS,
 | 
						|
          STRING
 | 
						|
        ]
 | 
						|
      }
 | 
						|
    ]
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
module.exports = python;
 |