Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enh(zephir) almost complete rework of the zephir grammar #2387

Merged
merged 17 commits into from Feb 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -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][]
Expand Down
67 changes: 35 additions & 32 deletions src/languages/zephir.js
Expand Up @@ -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(
'/\\*',
'\\*/',
Expand All @@ -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+;',
Expand All @@ -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,
Expand All @@ -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
Expand Down
55 changes: 55 additions & 0 deletions test/markup/zephir/default.expect.txt
@@ -0,0 +1,55 @@
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">testBefore</span><span class="hljs-params">(&lt;Test&gt; a, <span class="hljs-keyword">var</span> b = <span class="hljs-number">5</span>, <span class="hljs-keyword">int</span> c = <span class="hljs-number">10</span>)</span>
</span>{
a-&gt;method1();

<span class="hljs-keyword">return</span> b + c;
}

<span class="hljs-keyword">namespace</span> <span class="hljs-title">Test</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">RuntimeException</span> <span class="hljs-title">as</span> <span class="hljs-title">RE</span>;

<span class="hljs-comment">/**
* Example comment
*/</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Test</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">CustomClass</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">TestInterface</span>
</span>{
<span class="hljs-keyword">const</span> C1 = <span class="hljs-keyword">null</span>;

<span class="hljs-comment">// Magic constant: http://php.net/manual/ru/language.constants.predefined.php</span>
<span class="hljs-keyword">const</span> className = <span class="hljs-keyword">__CLASS__</span>;

<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">method1</span><span class="hljs-params">()</span>
</span>{
<span class="hljs-keyword">int</span> a = <span class="hljs-number">1</span>, b = <span class="hljs-number">2</span>;
<span class="hljs-keyword">return</span> a + b;
}

<span class="hljs-comment">// See fn is allowed like shortcut</span>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">method2</span><span class="hljs-params">()</span> -&gt; &lt;<span class="hljs-title">Test</span>&gt;
</span>{
call_user_func(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">echo</span> <span class="hljs-string">"hello"</span>; });


[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]-&gt;walk(
<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(<span class="hljs-keyword">int</span>! x)</span> </span>{
<span class="hljs-keyword">return</span> x * x;
}
);

[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]-&gt;walk(
<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(_, <span class="hljs-keyword">int</span> key)</span> </span>{ <span class="hljs-keyword">echo</span> key; }
);

<span class="hljs-keyword">array</span> input = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>];

input-&gt;walk(
<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(_, <span class="hljs-keyword">int</span> key)</span> </span>{ <span class="hljs-keyword">echo</span> key; }
);


input-&gt;map(x =&gt; x * x);

<span class="hljs-keyword">return</span> this;
}
}
55 changes: 55 additions & 0 deletions test/markup/zephir/default.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;
}
}