1 /*! `php` grammar compiled for Highlight.js 11.11.1 */
2 var hljsGrammar
= (function () {
7 Author: Victor Karamzin <Victor.Karamzin@enterra-inc.com>
8 Contributors: Evgeny Stepanischev <imbolk@gmail.com>, Ivan Sagalaev <maniac@softwaremaniacs.org>
9 Website: https://www.php.net
14 * @param {HLJSApi} hljs
15 * @returns {LanguageDetail}
18 const regex
= hljs
.regex
;
19 // negative look-ahead tries to avoid matching patterns that are not
20 // Perl at all like $ident$, @ident@, etc.
21 const NOT_PERL_ETC
= /(?![A-Za-z0-9])(?![$])/;
22 const IDENT_RE
= regex
.concat(
23 /[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/,
25 // Will not detect camelCase classes
26 const PASCAL_CASE_CLASS_NAME_RE
= regex
.concat(
27 /(\\?[A-Z][a-z0-9_\x7f-\xff]+|\\?[A-Z]+(?=[A-Z][a-z0-9_\x7f-\xff])){1,}/,
29 const UPCASE_NAME_RE
= regex
.concat(
34 match: '\\$+' + IDENT_RE
,
36 const PREPROCESSOR
= {
39 { begin: /<\?php/, relevance: 10 }, // boost for obvious PHP
41 // less relevant per PSR-1 which says not to use short-tags
42 { begin: /<\?/, relevance: 0.1 },
43 { begin: /\?>/ } // end php tag
56 const SINGLE_QUOTED
= hljs
.inherit(hljs
.APOS_STRING_MODE
, { illegal: null, });
57 const DOUBLE_QUOTED
= hljs
.inherit(hljs
.QUOTE_STRING_MODE
, {
59 contains: hljs
.QUOTE_STRING_MODE
.contains
.concat(SUBST
),
63 begin: /<<<[ \t]*(?:(\w
+)|"(\w+)")\n/,
65 contains: hljs
.QUOTE_STRING_MODE
.contains
.concat(SUBST
),
66 'on:begin': (m
, resp
) => { resp
.data
._beginMatch
= m
[1] || m
[2]; },
67 'on:end': (m
, resp
) => { if (resp
.data
._beginMatch
!== m
[1]) resp
.ignoreMatch(); },
70 const NOWDOC
= hljs
.END_SAME_AS_BEGIN({
71 begin: /<<<[ \t]*'(\w+)'\n/,
74 // list of valid whitespaces because non-breaking space might be part of a IDENT_RE
75 const WHITESPACE
= '[ \t\n]';
88 { begin: `\\b0[bB][01]+(?:_[01]+)*\\b` }, // Binary w/ underscore support
89 { begin: `\\b0[oO][0-7]+(?:_[0-7]+)*\\b` }, // Octals w/ underscore support
90 { begin: `\\b0[xX][\\da-fA-F]+(?:_[\\da-fA-F]+)*\\b` }, // Hex w/ underscore support
91 // Decimals w/ underscore support, with optional fragments and scientific exponent (e) suffix.
92 { begin: `(?:\\b\\d+(?:_\\d+)*(\\.(?:\\d+(?:_\\d+)*))?|\\B\\.\\d+)(?:[eE][+-]?\\d+)?` }
103 // <https://www.php.net/manual/en/language.constants.predefined.php>
108 "__COMPILER_HALT_OFFSET__",
113 // Function that look like language construct or language construct that look like function:
114 // List of keywords that may not require parenthesis
123 // These are not language construct (function) but operate on the currently-executing function and can access the current symbol table
124 // 'compact extract func_get_arg func_get_args func_num_args get_called_class get_parent_class ' +
126 // <https://www.php.net/manual/en/reserved.php>
127 // <https://www.php.net/manual/en/language.types.type-juggling.php>
204 // Standard PHP library:
205 // <https://www.php.net/manual/en/book.spl.php>
208 "ArgumentCountError",
213 "BadFunctionCallException",
214 "BadMethodCallException",
216 "CallbackFilterIterator",
220 "DivisionByZeroError",
225 "FilesystemIterator",
229 "InvalidArgumentException",
236 "OutOfBoundsException",
237 "OutOfRangeException",
243 "RecursiveArrayIterator",
244 "RecursiveCachingIterator",
245 "RecursiveCallbackFilterIterator",
246 "RecursiveDirectoryIterator",
247 "RecursiveFilterIterator",
249 "RecursiveIteratorIterator",
250 "RecursiveRegexIterator",
251 "RecursiveTreeIterator",
255 "SplDoublyLinkedList",
270 "UnderflowException",
271 "UnexpectedValueException",
272 "UnhandledMatchError",
273 // Reserved interfaces:
274 // <https://www.php.net/manual/en/reserved.interfaces.php>
290 // <https://www.php.net/manual/en/reserved.classes.php>
292 "__PHP_Incomplete_Class",
300 /** Dual-case keywords
303 * ["then", "THEN", "FILE", "file"]
305 * @param {string[]} items */
306 const dualCase
= (items
) => {
307 /** @type string[] */
309 items
.forEach(item
=> {
311 if (item
.toLowerCase() === item
) {
312 result
.push(item
.toUpperCase());
314 result
.push(item
.toLowerCase());
322 literal: dualCase(LITERALS
),
327 * @param {string[]} items */
328 const normalizeKeywords
= (items
) => {
329 return items
.map(item
=> {
330 return item
.replace(/\|\d+$/, "");
334 const CONSTRUCTOR_CALL
= { variants: [
338 regex
.concat(WHITESPACE
, "+"),
339 // to prevent built ins from being confused as the class constructor call
340 regex
.concat("(?!", normalizeKeywords(BUILT_INS
).join("\\b|"), "\\b)"),
341 PASCAL_CASE_CLASS_NAME_RE
,
350 const CONSTANT_REFERENCE
= regex
.concat(IDENT_RE
, "\\b(?!\\()");
352 const LEFT_AND_RIGHT_SIDE_OF_DOUBLE_COLON
= { variants: [
357 regex
.lookahead(/(?!class\b)/)
361 scope: { 2: "variable.constant", },
368 scope: { 2: "variable.language", },
372 PASCAL_CASE_CLASS_NAME_RE
,
375 regex
.lookahead(/(?!class\b)/)
381 3: "variable.constant",
386 PASCAL_CASE_CLASS_NAME_RE
,
389 regex
.lookahead(/(?!class\b)/)
392 scope: { 1: "title.class", },
396 PASCAL_CASE_CLASS_NAME_RE
,
402 3: "variable.language",
407 const NAMED_ARGUMENT
= {
409 match: regex
.concat(IDENT_RE
, regex
.lookahead(':'), regex
.lookahead(/(?!::)/)),
411 const PARAMS_MODE
= {
419 LEFT_AND_RIGHT_SIDE_OF_DOUBLE_COLON
,
420 hljs
.C_BLOCK_COMMENT_MODE
,
426 const FUNCTION_INVOKE
= {
430 // to prevent keywords from being confused as the function title
431 regex
.concat("(?!fn\\b|function\\b|", normalizeKeywords(KWS
).join("\\b|"), "|", normalizeKeywords(BUILT_INS
).join("\\b|"), "\\b)"),
433 regex
.concat(WHITESPACE
, "*"),
434 regex
.lookahead(/(?=\()/)
436 scope: { 3: "title.function.invoke", },
437 contains: [ PARAMS_MODE
]
439 PARAMS_MODE
.contains
.push(FUNCTION_INVOKE
);
441 const ATTRIBUTE_CONTAINS
= [
443 LEFT_AND_RIGHT_SIDE_OF_DOUBLE_COLON
,
444 hljs
.C_BLOCK_COMMENT_MODE
,
451 begin: regex
.concat(/#\[\s*\\?/,
453 PASCAL_CASE_CLASS_NAME_RE
,
480 ...ATTRIBUTE_CONTAINS
,
483 ...ATTRIBUTE_CONTAINS
,
487 { match: PASCAL_CASE_CLASS_NAME_RE
},
488 { match: UPCASE_NAME_RE
}
495 case_insensitive: false,
499 hljs
.HASH_COMMENT_MODE
,
500 hljs
.COMMENT('//', '$'),
512 match: /__halt_compiler\(\);/,
513 keywords: '__halt_compiler',
516 end: hljs
.MATCH_NOTHING_RE
,
528 scope: 'variable.language',
533 LEFT_AND_RIGHT_SIDE_OF_DOUBLE_COLON
,
542 3: "variable.constant",
549 beginKeywords: 'fn function',
554 { beginKeywords: 'use', },
555 hljs
.UNDERSCORE_TITLE_MODE
,
557 begin: '=>', // No markup, just a relevance booster
571 LEFT_AND_RIGHT_SIDE_OF_DOUBLE_COLON
,
572 hljs
.C_BLOCK_COMMENT_MODE
,
583 beginKeywords: "enum",
587 beginKeywords: "class interface trait",
595 { beginKeywords: 'extends implements' },
596 hljs
.UNDERSCORE_TITLE_MODE
599 // both use and namespace still use "old style" rules (vs multi-match)
600 // because the namespace name can include `\` and we still want each
601 // element to be treated as its own *individual* title
603 beginKeywords: 'namespace',
607 contains: [ hljs
.inherit(hljs
.UNDERSCORE_TITLE_MODE
, { scope: "title.class" }) ]
610 beginKeywords: 'use',
614 // TODO: title.function vs title.class
616 match: /\b(as|const|function)\b/,
619 // TODO: could be title.class or title.function
620 hljs
.UNDERSCORE_TITLE_MODE
633 export default hljsGrammar
;