diff --git a/CHANGES.md b/CHANGES.md index c0fadbf799..295c930a63 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,7 @@ Core Changes: Language Improvements: +- enh(zephir) almost complete rework of the zephir grammar (#2387) [Josh Goebel][] - (markdown) much improved code block support (#2382) [Josh Goebel][] - (markdown) improve bold/italic nesting (#2382) [Josh Goebel][] - enh(csharp) Support `where` keyword as class constraint (#2378) [Josh Goebel][] diff --git a/src/languages/zephir.js b/src/languages/zephir.js index 45d74075ca..96635280f3 100644 --- a/src/languages/zephir.js +++ b/src/languages/zephir.js @@ -10,33 +10,44 @@ function(hljs) { className: 'string', contains: [hljs.BACKSLASH_ESCAPE], variants: [ - { - begin: 'b"', end: '"' - }, - { - begin: 'b\'', end: '\'' - }, hljs.inherit(hljs.APOS_STRING_MODE, {illegal: null}), hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null}) ] }; + var TITLE_MODE = hljs.UNDERSCORE_TITLE_MODE; var NUMBER = {variants: [hljs.BINARY_NUMBER_MODE, hljs.C_NUMBER_MODE]}; + var KEYWORDS = + // classes and objects + 'namespace class interface use extends ' + + 'function return ' + + 'abstract final public protected private static deprecated ' + + // error handling + 'throw try catch Exception ' + + // keyword-ish things their website does NOT seem to highlight (in their own snippets) + // 'typeof fetch in ' + + // operators/helpers + 'echo empty isset instanceof unset ' + + // assignment/variables + 'let var new const self ' + + // control + 'require ' + + 'if else elseif switch case default ' + + 'do while loop for continue break ' + + 'likely unlikely ' + + // magic constants + // https://github.com/phalcon/zephir/blob/master/Library/Expression/Constants.php + '__LINE__ __FILE__ __DIR__ __FUNCTION__ __CLASS__ __TRAIT__ __METHOD__ __NAMESPACE__ ' + + // types - https://docs.zephir-lang.com/0.12/en/types + 'array boolean float double integer object resource string ' + + 'char long unsigned bool int uint ulong uchar ' + + // built-ins + 'true false null undefined'; + return { aliases: ['zep'], - case_insensitive: true, - keywords: - 'and include_once list abstract global private echo interface as static endswitch ' + - 'array null if endwhile or const for endforeach self var let while isset public ' + - 'protected exit foreach throw elseif include __FILE__ empty require_once do xor ' + - 'return parent clone use __CLASS__ __LINE__ else break print eval new ' + - 'catch __METHOD__ case exception default die require __FUNCTION__ ' + - 'enddeclare final try switch continue endfor endif declare unset true false ' + - 'trait goto instanceof insteadof __DIR__ __NAMESPACE__ ' + - 'yield finally int uint long ulong char uchar double float bool boolean string' + - 'likely unlikely', + keywords: KEYWORDS, contains: [ hljs.C_LINE_COMMENT_MODE, - hljs.HASH_COMMENT_MODE, hljs.COMMENT( '/\\*', '\\*/', @@ -49,15 +60,6 @@ function(hljs) { ] } ), - hljs.COMMENT( - '__halt_compiler.+?;', - false, - { - endsWithParent: true, - keywords: '__halt_compiler', - lexemes: hljs.UNDERSCORE_IDENT_RE - } - ), { className: 'string', begin: '<<<[\'"]?\\w+[\'"]?$', end: '^\\w+;', @@ -69,13 +71,14 @@ function(hljs) { }, { className: 'function', - beginKeywords: 'function', end: /[;{]/, excludeEnd: true, + beginKeywords: 'function fn', end: /[;{]/, excludeEnd: true, illegal: '\\$|\\[|%', contains: [ - hljs.UNDERSCORE_TITLE_MODE, + TITLE_MODE, { className: 'params', begin: '\\(', end: '\\)', + keywords: KEYWORDS, contains: [ 'self', hljs.C_BLOCK_COMMENT_MODE, @@ -91,17 +94,17 @@ function(hljs) { illegal: /[:\(\$"]/, contains: [ {beginKeywords: 'extends implements'}, - hljs.UNDERSCORE_TITLE_MODE + TITLE_MODE ] }, { beginKeywords: 'namespace', end: ';', illegal: /[\.']/, - contains: [hljs.UNDERSCORE_TITLE_MODE] + contains: [TITLE_MODE] }, { beginKeywords: 'use', end: ';', - contains: [hljs.UNDERSCORE_TITLE_MODE] + contains: [TITLE_MODE] }, { begin: '=>' // No markup, just a relevance booster diff --git a/test/markup/zephir/default.expect.txt b/test/markup/zephir/default.expect.txt new file mode 100644 index 0000000000..099d29299a --- /dev/null +++ b/test/markup/zephir/default.expect.txt @@ -0,0 +1,55 @@ +function testBefore(<Test> a, var b = 5, int c = 10) +{ + a->method1(); + + return b + c; +} + +namespace Test; + +use RuntimeException as RE; + +/** + * Example comment + */ +class Test extends CustomClass implements TestInterface +{ + const C1 = null; + + // Magic constant: http://php.net/manual/ru/language.constants.predefined.php + const className = __CLASS__; + + public function method1() + { + int a = 1, b = 2; + return a + b; + } + + // See fn is allowed like shortcut + public fn method2() -> <Test> + { + call_user_func(function() { echo "hello"; }); + + + [1, 2, 3, 4, 5]->walk( + function(int! x) { + return x * x; + } + ); + + [1, 2, 3, 4, 5]->walk( + function(_, int key) { echo key; } + ); + + array input = [1, 2, 3, 4, 5]; + + input->walk( + function(_, int key) { echo key; } + ); + + + input->map(x => x * x); + + return this; + } +} diff --git a/test/markup/zephir/default.txt b/test/markup/zephir/default.txt new file mode 100644 index 0000000000..8142e7f10c --- /dev/null +++ b/test/markup/zephir/default.txt @@ -0,0 +1,55 @@ +function testBefore( a, var b = 5, int c = 10) +{ + a->method1(); + + return b + c; +} + +namespace Test; + +use RuntimeException as RE; + +/** + * Example comment + */ +class Test extends CustomClass implements TestInterface +{ + const C1 = null; + + // Magic constant: http://php.net/manual/ru/language.constants.predefined.php + const className = __CLASS__; + + public function method1() + { + int a = 1, b = 2; + return a + b; + } + + // See fn is allowed like shortcut + public fn method2() -> + { + call_user_func(function() { echo "hello"; }); + + + [1, 2, 3, 4, 5]->walk( + function(int! x) { + return x * x; + } + ); + + [1, 2, 3, 4, 5]->walk( + function(_, int key) { echo key; } + ); + + array input = [1, 2, 3, 4, 5]; + + input->walk( + function(_, int key) { echo key; } + ); + + + input->map(x => x * x); + + return this; + } +}