Skip to content

Commit

Permalink
PHP: Added support for PHP 8.0 features (#2591)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomPavelec authored Oct 16, 2020
1 parent f59a85f commit df922d9
Show file tree
Hide file tree
Showing 11 changed files with 817 additions and 86 deletions.
235 changes: 166 additions & 69 deletions components/prism-php.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,28 @@
* Modified by Miles Johnson: http://milesj.me
* Rewritten by Tom Pavelec
*
* Supports PHP 5.3 - 7.4
* Supports PHP 5.3 - 8.0
*/
(function (Prism) {
var comment = /\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/;
var constant = [
{
pattern: /\b(?:false|true)\b/i,
alias: 'boolean'
},
/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/,
/\b(?:null)\b/i,
];
var number = /\b0b[01]+\b|\b0x[\da-f]+\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)*|\B\.\d+)(?:e[+-]?\d+)?/i;
var operator = /<?=>|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/;
var punctuation = /[{}\[\](),:;]/;

Prism.languages.php = {
'delimiter': {
pattern: /\?>$|^<\?(?:php(?=\s)|=)?/i,
alias: 'important'
},
'comment': [
/\/\*[\s\S]*?\*\/|\/\/.*|#.*/
],
'comment': comment,
'variable': /\$+(?:\w+\b|(?={))/i,
'package': {
pattern: /(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,
Expand All @@ -30,37 +41,82 @@
lookbehind: true
},
{
pattern: /([(,?]\s*)\b(?:bool|boolean|int|integer|float|string|object|array(?!\s*\()|mixed|self|static|callable|iterable)\b(?=\s*\$)/i,
pattern: /([(,?]\s*)\b(?:bool|int|float|string|object|array(?!\s*\()|mixed|self|static|callable|iterable|(?:null|false)(?=\s*\|))\b(?=\s*\$)/i,
alias: 'type-hint',
greedy: true,
lookbehind: true
},
{
pattern: /(\)\s*:\s*\?*\s*)\b(?:bool|boolean|int|integer|float|string|object|void|array(?!\s*\()|mixed|self|static|callable|iterable)\b/i,
pattern: /([(,?]\s*[a-z0-9_|]\|\s*)(?:null|false)\b(?=\s*\$)/i,
alias: 'type-hint',
greedy: true,
lookbehind: true
},
{
pattern: /(\)\s*:\s*\??\s*)\b(?:bool|int|float|string|object|void|array(?!\s*\()|mixed|self|static|callable|iterable|(?:null|false)(?=\s*\|))\b/i,
alias: 'return-type',
greedy: true,
lookbehind: true
},
{
pattern: /\b(?:bool|boolean|int|integer|float|string|object|void|array(?!\s*\()|mixed|iterable)\b/i,
pattern: /(\)\s*:\s*\??\s*[a-z0-9_|]\|\s*)(?:null|false)\b/i,
alias: 'return-type',
greedy: true,
lookbehind: true
},
{
pattern: /\b(?:bool|int|float|string|object|void|array(?!\s*\()|mixed|iterable|(?:null|false)(?=\s*\|))\b/i,
alias: 'type-declaration',
greedy: true
},
{
pattern: /(\|\s*)(?:null|false)\b/i,
alias: 'type-declaration',
greedy: true,
lookbehind: true
},
{
pattern: /\b(?:parent|self|static)(?=\s*::)/i,
alias: 'static-context',
greedy: true
},
/\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|final|finally|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|match|new|or|parent|print|private|protected|public|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i
],
'argument-name': /\b[a-z_]\w*(?=\s*:(?!:))/i,
'class-name': [
{
pattern: /(\b(?:class|interface|extends|implements|trait|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s+\()\b[a-z_]\w*(?!\\)\b/i,
pattern: /(\b(?:class|interface|extends|implements|trait|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,
greedy: true,
lookbehind: true
},
{
pattern: /(\|\s*)\b[a-z_]\w*(?!\\)\b/i,
greedy: true,
lookbehind: true
},
{
pattern: /(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s+\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,
pattern: /\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,
greedy: true
},
{
pattern: /(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,
alias: 'class-name-fully-qualified',
greedy: true,
lookbehind: true,
inside: {
'punctuation': /\\/
}
},
{
pattern: /(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,
alias: 'class-name-fully-qualified',
greedy: true,
inside: {
'punctuation': /\\/
}
},
{
pattern: /(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,
alias: 'class-name-fully-qualified',
greedy: true,
lookbehind: true,
Expand Down Expand Up @@ -110,13 +166,13 @@
}
},
{
pattern: /(\)\s*:\s*\?*\s*)\b[a-z_]\w*(?!\\)\b/i,
pattern: /(\)\s*:\s*\??\s*)\b[a-z_]\w*(?!\\)\b/i,
alias: 'return-type',
greedy: true,
lookbehind: true
},
{
pattern: /(\)\s*:\s*\?*\s*)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,
pattern: /(\)\s*:\s*\??\s*)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,
alias: ['class-name-fully-qualified', 'return-type'],
greedy: true,
lookbehind: true,
Expand All @@ -125,22 +181,15 @@
}
}
],
'constant': [
{
pattern: /\b(?:false|true)\b/i,
alias: 'boolean'
},
/\b[A-Z_][A-Z0-9_]*\b/,
/\b(?:null)\b/i,
],
'constant': constant,
'function': /\w+\s*(?=\()/,
'property': {
pattern: /(->)[\w]+/,
lookbehind: true
},
'number': /\b0b[01]+\b|\b0x[\da-f]+\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)*|\B\.\d+)(?:e[+-]?\d+)?/i,
'operator': /<?=>|\?\?=?|\.{3}|->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||[?~]|[/^|%*&<>.+-]=?/,
'punctuation': /[{}\[\](),:;]/
'number': number,
'operator': operator,
'punctuation': punctuation
};

var string_interpolation = {
Expand All @@ -149,64 +198,112 @@
inside: Prism.languages.php
};

Prism.languages.insertBefore('php', 'variable', {
'string': [
{
pattern: /<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,
alias: 'nowdoc-string',
greedy: true,
inside: {
'delimiter': {
pattern: /^<<<'[^']+'|[a-z_]\w*;$/i,
alias: 'symbol',
inside: {
'punctuation': /^<<<'?|[';]$/
}
var string = [
{
pattern: /<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,
alias: 'nowdoc-string',
greedy: true,
inside: {
'delimiter': {
pattern: /^<<<'[^']+'|[a-z_]\w*;$/i,
alias: 'symbol',
inside: {
'punctuation': /^<<<'?|[';]$/
}
}
},
{
pattern: /<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,
alias: 'heredoc-string',
greedy: true,
inside: {
'delimiter': {
pattern: /^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,
alias: 'symbol',
inside: {
'punctuation': /^<<<"?|[";]$/
}
},
'interpolation': string_interpolation // See below
}
},
{
pattern: /`(?:\\[\s\S]|[^\\`])*`/,
alias: 'backtick-quoted-string',
greedy: true
},
{
pattern: /'(?:\\[\s\S]|[^\\'])*'/,
alias: 'single-quoted-string',
greedy: true
},
{
pattern: /"(?:\\[\s\S]|[^\\"])*"/,
alias: 'double-quoted-string',
greedy: true,
inside: {
'interpolation': string_interpolation // See below
}
},
{
pattern: /<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,
alias: 'heredoc-string',
greedy: true,
inside: {
'delimiter': {
pattern: /^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,
alias: 'symbol',
inside: {
'punctuation': /^<<<"?|[";]$/
}
},
'interpolation': string_interpolation // See below
}
},
{
pattern: /`(?:\\[\s\S]|[^\\`])*`/,
alias: 'backtick-quoted-string',
greedy: true
},
{
pattern: /'(?:\\[\s\S]|[^\\'])*'/,
alias: 'single-quoted-string',
greedy: true
},
{
pattern: /"(?:\\[\s\S]|[^\\"])*"/,
alias: 'double-quoted-string',
greedy: true,
inside: {
'interpolation': string_interpolation // See below
}
}
];

Prism.languages.insertBefore('php', 'variable', {
'string': string,
});

Prism.languages.insertBefore('php', 'variable', {
'attribute': {
pattern: /#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/mi,
greedy: true,
inside: {
'attribute-content': {
pattern: /^(#\[)[\s\S]+(?=]$)/,
lookbehind: true,
// inside can appear subset of php
inside: {
'comment': comment,
'string': string,
'attribute-class-name': [
{
pattern: /([^:]|^)\b[a-z_]\w*(?!\\)\b/i,
alias: 'class-name',
greedy: true,
lookbehind: true
},
{
pattern: /([^:]|^)(?:\\?\b[a-z_]\w*)+/i,
alias: [
'class-name',
'class-name-fully-qualified'
],
greedy: true,
lookbehind: true,
inside: {
'punctuation': /\\/
}
}
],
'constant': constant,
'number': number,
'operator': operator,
'punctuation': punctuation
}
},
'delimiter': {
pattern: /^#\[|]$/,
alias: 'punctuation'
}
}
],
},
});

Prism.hooks.add('before-tokenize', function(env) {
if (!/<\?/.test(env.code)) {
return;
}

var phpPattern = /<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#)(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|\/\*[\s\S]*?(?:\*\/|$))*?(?:\?>|$)/ig;
var phpPattern = /<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*[\s\S]*?(?:\*\/|$))*?(?:\?>|$)/ig;
Prism.languages['markup-templating'].buildPlaceholders(env, 'php', phpPattern);
});

Expand Down
2 changes: 1 addition & 1 deletion components/prism-php.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit df922d9

Please sign in to comment.