Skip to content

Commit

Permalink
enh(haxe) Many improvements and fixes to Haxe grammar (#3789)
Browse files Browse the repository at this point in the history
 - enh(haxe) added `final`, `is`, `macro` keywords and `$` identifiers [Robert Borghese][]
 - enh(haxe) support numeric separators and suffixes [Robert Borghese][]
 - fix(haxe) fixed metadata arguments and support non-colon syntax [Robert Borghese][]
 - fix(haxe) differentiate `abstract` declaration from keyword [Robert Borghese][]
  • Loading branch information
SomeRanDev committed May 21, 2023
1 parent d27be50 commit cc29629
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 52 deletions.
7 changes: 7 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@ Parser:
- (enh) prevent rehighlighting of an element [joshgoebel][]
- added 3rd party Iptables grammar to SUPPORTED_LANGUAGES [Checconio][]

Core Grammars:
- enh(haxe) added `final`, `is`, `macro` keywords and `$` identifiers [Robert Borghese][]
- enh(haxe) support numeric separators and suffixes [Robert Borghese][]
- fix(haxe) fixed metadata arguments and support non-colon syntax [Robert Borghese][]
- fix(haxe) differentiate `abstract` declaration from keyword [Robert Borghese][]

Dev tool:

- (chore) Update dev tool to use the new `highlight` API. [Shah Shabbir Ahmmed][]
- (enh) Auto-update the highlighted output when the language dropdown changes. [Shah Shabbir Ahmmed][]

[Robert Borghese]: https://github.com/RobertBorghese
[Shah Shabbir Ahmmed]: https://github.com/shabbir23ah
[Josh Goebel]: https://github.com/joshgoebel
[Checconio]: https://github.com/Checconio
Expand Down
78 changes: 45 additions & 33 deletions src/languages/haxe.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,19 @@ Website: https://haxe.org

export default function(hljs) {
const IDENT_RE = '[a-zA-Z_$][a-zA-Z0-9_$]*';
const IDENT_FUNC_RETURN_TYPE_RE = '([*]|[a-zA-Z_$][a-zA-Z0-9_$]*)';
const IDENT_FUNC_RETURN_TYPE_RE = /([*]|[a-zA-Z_$][a-zA-Z0-9_$]*)/;

// C_NUMBER_RE with underscores and literal suffixes
const HAXE_NUMBER_RE = /(-?)(\b0[xX][a-fA-F0-9_]+|(\b\d+(\.[\d_]*)?|\.[\d_]+)(([eE][-+]?\d+)|i32|u32|i64|f64)?)/;

const HAXE_BASIC_TYPES = 'Int Float String Bool Dynamic Void Array ';

return {
name: 'Haxe',
aliases: [ 'hx' ],
keywords: {
keyword: 'break case cast catch continue default do dynamic else enum extern '
+ 'for function here if import in inline never new override package private get set '
keyword: 'abstract break case cast catch continue default do dynamic else enum extern '
+ 'final for function here if import in inline is macro never new override package private get set '
+ 'public return static super switch this throw trace try typedef untyped using var while '
+ HAXE_BASIC_TYPES,
built_in:
Expand All @@ -34,24 +37,33 @@ export default function(hljs) {
hljs.BACKSLASH_ESCAPE,
{
className: 'subst', // interpolation
begin: '\\$\\{',
end: '\\}'
begin: /\$\{/,
end: /\}/
},
{
className: 'subst', // interpolation
begin: '\\$',
begin: /\$/,
end: /\W\}/
}
]
},
hljs.QUOTE_STRING_MODE,
hljs.C_LINE_COMMENT_MODE,
hljs.C_BLOCK_COMMENT_MODE,
hljs.C_NUMBER_MODE,
{
className: 'number',
begin: HAXE_NUMBER_RE,
relevance: 0
},
{
className: 'variable',
begin: "\\$" + IDENT_RE,
},
{
className: 'meta', // compiler meta
begin: '@:',
end: '$'
begin: /@:?/,
end: /\(|$/,
excludeEnd: true,
},
{
className: 'meta', // compiler conditionals
Expand All @@ -61,55 +73,55 @@ export default function(hljs) {
},
{
className: 'type', // function types
begin: ':[ \t]*',
end: '[^A-Za-z0-9_ \t\\->]',
begin: /:[ \t]*/,
end: /[^A-Za-z0-9_ \t\->]/,
excludeBegin: true,
excludeEnd: true,
relevance: 0
},
{
className: 'type', // types
begin: ':[ \t]*',
end: '\\W',
begin: /:[ \t]*/,
end: /\W/,
excludeBegin: true,
excludeEnd: true
},
{
className: 'type', // instantiation
begin: 'new *',
end: '\\W',
begin: /new */,
end: /\W/,
excludeBegin: true,
excludeEnd: true
},
{
className: 'class', // enums
className: 'title.class', // enums
beginKeywords: 'enum',
end: '\\{',
end: /\{/,
contains: [ hljs.TITLE_MODE ]
},
{
className: 'class', // abstracts
beginKeywords: 'abstract',
end: '[\\{$]',
className: 'title.class', // abstracts
begin: '\\babstract\\b(?=\\s*' + hljs.IDENT_RE + '\\s*\\()',
end: /[\{$]/,
contains: [
{
className: 'type',
begin: '\\(',
end: '\\)',
begin: /\(/,
end: /\)/,
excludeBegin: true,
excludeEnd: true
},
{
className: 'type',
begin: 'from +',
end: '\\W',
begin: /from +/,
end: /\W/,
excludeBegin: true,
excludeEnd: true
},
{
className: 'type',
begin: 'to +',
end: '\\W',
begin: /to +/,
end: /\W/,
excludeBegin: true,
excludeEnd: true
},
Expand All @@ -118,15 +130,15 @@ export default function(hljs) {
keywords: { keyword: 'abstract from to' }
},
{
className: 'class', // classes
begin: '\\b(class|interface) +',
end: '[\\{$]',
className: 'title.class', // classes
begin: /\b(class|interface) +/,
end: /[\{$]/,
excludeEnd: true,
keywords: 'class interface',
contains: [
{
className: 'keyword',
begin: '\\b(extends|implements) +',
begin: /\b(extends|implements) +/,
keywords: 'extends implements',
contains: [
{
Expand All @@ -140,11 +152,11 @@ export default function(hljs) {
]
},
{
className: 'function',
className: 'title.function',
beginKeywords: 'function',
end: '\\(',
end: /\(/,
excludeEnd: true,
illegal: '\\S',
illegal: /\S/,
contains: [ hljs.TITLE_MODE ]
}
],
Expand Down
72 changes: 54 additions & 18 deletions test/markup/haxe/default.expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,59 +11,87 @@
<span class="hljs-keyword">import</span> Lambda;
<span class="hljs-keyword">using</span> Main.IntExtender;

<span class="hljs-keyword">extern</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Math</span> </span>{
<span class="hljs-keyword">extern</span> <span class="hljs-title class_"><span class="hljs-keyword">class</span> <span class="hljs-title">Math</span> </span>{
<span class="hljs-keyword">static</span> <span class="hljs-keyword">var</span> PI(<span class="hljs-keyword">default</span>,<span class="hljs-literal">null</span>) : <span class="hljs-type">Float</span>;
<span class="hljs-keyword">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">floor</span></span>(v:<span class="hljs-type">Float</span>):<span class="hljs-type">Int</span>;
<span class="hljs-keyword">static</span> <span class="hljs-title function_"><span class="hljs-keyword">function</span> <span class="hljs-title">floor</span></span>(v:<span class="hljs-type">Float</span>):<span class="hljs-type">Int</span>;
}

<span class="hljs-keyword">abstract</span> <span class="hljs-title class_"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span> </span>{
<span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-title function_"><span class="hljs-keyword">function</span> <span class="hljs-title">talk</span></span>(): <span class="hljs-type">String</span>;
}

<span class="hljs-comment">/**
* Abstract forwarding
*/</span>
<span class="hljs-class"><span class="hljs-keyword">abstract</span> <span class="hljs-title">MyAbstract</span>(<span class="hljs-type">Int</span>) <span class="hljs-keyword">from</span> <span class="hljs-type">Int</span> <span class="hljs-keyword">to</span> <span class="hljs-type">Int</span> {</span>
<span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">new</span></span>(i:<span class="hljs-type">Int</span>) {
<span class="hljs-title class_"><span class="hljs-keyword">abstract</span> <span class="hljs-title">MyAbstract</span>(<span class="hljs-type">Int</span>) <span class="hljs-keyword">from</span> <span class="hljs-type">Int</span> <span class="hljs-keyword">to</span> <span class="hljs-type">Int</span> {</span>
<span class="hljs-keyword">inline</span> <span class="hljs-title function_"><span class="hljs-keyword">function</span> <span class="hljs-title">new</span></span>(i:<span class="hljs-type">Int</span>) {
<span class="hljs-built_in">this</span> = i;
}

<span class="hljs-meta">@:op(A * B)</span>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">multiply</span></span>(rhs:<span class="hljs-type">MyAbstract</span>) {
<span class="hljs-meta">@:op</span>(A * B)
<span class="hljs-keyword">public</span> <span class="hljs-title function_"><span class="hljs-keyword">function</span> <span class="hljs-title">multiply</span></span>(rhs:<span class="hljs-type">MyAbstract</span>) {
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span> * rhs;
}
}

<span class="hljs-comment">// an enum</span>
<span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">Color</span> {</span>
<span class="hljs-title class_"><span class="hljs-keyword">enum</span> <span class="hljs-title">Color</span> {</span>
Red;
Green;
Blue;
Rgb(r:<span class="hljs-type">Int</span>, g:<span class="hljs-type">Int</span>, b:<span class="hljs-type">Int</span>);
}

<span class="hljs-meta">@author</span>(<span class="hljs-string">&quot;Santa&quot;</span>, <span class="hljs-number">24</span> - <span class="hljs-number">12</span>)
<span class="hljs-title function_"><span class="hljs-keyword">function</span> <span class="hljs-title">makeWinter</span></span>(callback: <span class="hljs-type"></span>() -&gt; <span class="hljs-keyword">Void</span>) {
<span class="hljs-built_in">trace</span>(<span class="hljs-string">&#x27;it is winter.&#x27;</span>);
callback();
}

<span class="hljs-keyword">macro</span> <span class="hljs-title function_"><span class="hljs-keyword">function</span> <span class="hljs-title">compiletime</span></span>(expr: <span class="hljs-type">haxe</span>.<span class="hljs-keyword">macro</span>.Expr): <span class="hljs-type">haxe</span>.<span class="hljs-keyword">macro</span>.Expr {
<span class="hljs-keyword">final</span> ident = <span class="hljs-string">&quot;length&quot;</span>;
<span class="hljs-keyword">final</span> ct: <span class="hljs-type">haxe</span>.<span class="hljs-keyword">macro</span>.ComplexType = <span class="hljs-keyword">macro</span> : <span class="hljs-type">Map</span>&lt;<span class="hljs-keyword">String</span>, <span class="hljs-keyword">Int</span>&gt;;

<span class="hljs-keyword">return</span> <span class="hljs-keyword">macro</span> {
<span class="hljs-keyword">final</span> s = <span class="hljs-string">&quot;string&quot;</span>;
<span class="hljs-built_in">trace</span>(s.<span class="hljs-variable">$ident</span>);

<span class="hljs-keyword">final</span> m = ([<span class="hljs-string">&quot;a&quot;</span> =&gt; <span class="hljs-number">1</span>] : <span class="hljs-type"></span>$ct);

<span class="hljs-keyword">final</span> arr = <span class="hljs-variable">$a</span>{[<span class="hljs-keyword">macro</span> <span class="hljs-number">0</span>, <span class="hljs-keyword">macro</span> <span class="hljs-number">1</span>, <span class="hljs-keyword">macro</span> <span class="hljs-number">2</span>]};
<span class="hljs-keyword">final</span> field = <span class="hljs-variable">$p</span>{[<span class="hljs-string">&quot;String&quot;</span>, <span class="hljs-string">&quot;fromCharCode&quot;</span>]};
<span class="hljs-keyword">final</span> str = <span class="hljs-variable">$v</span>{ident};

<span class="hljs-variable">$expr</span>;
}
}

<span class="hljs-meta">@:generic</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Gen</span>&lt;<span class="hljs-title">T</span>&gt; </span>{
<span class="hljs-title class_"><span class="hljs-keyword">class</span> <span class="hljs-title">Gen</span>&lt;<span class="hljs-title">T</span>&gt; </span>{
<span class="hljs-keyword">var</span> v:<span class="hljs-type">T</span>;
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">new</span></span>(v:<span class="hljs-type">T</span>) {
<span class="hljs-keyword">public</span> <span class="hljs-title function_"><span class="hljs-keyword">function</span> <span class="hljs-title">new</span></span>(v:<span class="hljs-type">T</span>) {
<span class="hljs-built_in">this</span>.v = v;
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">var</span> x(<span class="hljs-keyword">get</span>, <span class="hljs-keyword">set</span>):<span class="hljs-type">T</span>;

<span class="hljs-keyword">private</span> <span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">get_x</span></span>():<span class="hljs-type">T</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">inline</span> <span class="hljs-title function_"><span class="hljs-keyword">function</span> <span class="hljs-title">get_x</span></span>():<span class="hljs-type">T</span>
<span class="hljs-keyword">return</span> v;

<span class="hljs-keyword">private</span> <span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">set_x</span></span>(x:<span class="hljs-type">T</span>):<span class="hljs-type">T</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">inline</span> <span class="hljs-title function_"><span class="hljs-keyword">function</span> <span class="hljs-title">set_x</span></span>(x:<span class="hljs-type">T</span>):<span class="hljs-type">T</span>
<span class="hljs-keyword">return</span> v = x;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> <span class="hljs-keyword"><span class="hljs-keyword">extends</span> <span class="hljs-type">BaseClass</span></span> <span class="hljs-keyword"><span class="hljs-keyword">implements</span> <span class="hljs-type">SomeFunctionality</span></span> </span>{
<span class="hljs-title class_"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> <span class="hljs-keyword"><span class="hljs-keyword">extends</span> <span class="hljs-type">BaseClass</span></span> <span class="hljs-keyword"><span class="hljs-keyword">implements</span> <span class="hljs-type">SomeFunctionality</span></span> </span>{
<span class="hljs-keyword">var</span> callback:<span class="hljs-type">Void-&gt;Void </span>= <span class="hljs-literal">null</span>;
<span class="hljs-keyword">var</span> myArray:<span class="hljs-type">Array</span>&lt;<span class="hljs-keyword">Float</span>&gt; = <span class="hljs-keyword">new</span> <span class="hljs-type">Array</span>&lt;<span class="hljs-keyword">Float</span>&gt;();
<span class="hljs-keyword">var</span> arr = [<span class="hljs-number">4</span>,<span class="hljs-number">8</span>,<span class="hljs-number">0</span>,<span class="hljs-number">3</span>,<span class="hljs-number">9</span>,<span class="hljs-number">1</span>,<span class="hljs-number">5</span>,<span class="hljs-number">2</span>,<span class="hljs-number">6</span>,<span class="hljs-number">7</span>];

<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">new</span></span>(x) {
<span class="hljs-keyword">public</span> <span class="hljs-title function_"><span class="hljs-keyword">function</span> <span class="hljs-title">new</span></span>(x) {
<span class="hljs-keyword">super</span>(x);
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span></span>() {
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-title function_"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span></span>() {
<span class="hljs-built_in">trace</span>(<span class="hljs-string">&#x27;What\&#x27;s up?&#x27;</span>);
<span class="hljs-built_in">trace</span>(<span class="hljs-string">&#x27;Hi, <span class="hljs-subst">${name}</span>!&#x27;</span>);

Expand Down Expand Up @@ -106,23 +134,31 @@
<span class="hljs-keyword">var</span> f = map.<span class="hljs-keyword">set</span>.bind(<span class="hljs-literal">_</span>, <span class="hljs-string">&quot;12&quot;</span>);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">nothing</span></span>():<span class="hljs-type">Void</span>
<span class="hljs-title function_"><span class="hljs-keyword">function</span> <span class="hljs-title">nothing</span></span>():<span class="hljs-type">Void</span>
<span class="hljs-built_in">trace</span>(<span class="hljs-string">&quot;nothing!&quot;</span>);

<span class="hljs-keyword">private</span> <span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">func</span></span>(a:<span class="hljs-type">Int</span>, b:<span class="hljs-type">Float</span>, ?c:<span class="hljs-type">String</span>, d:<span class="hljs-type">Bool</span>=<span class="hljs-literal">false</span>):<span class="hljs-type">Dynamic </span>{
<span class="hljs-keyword">private</span> <span class="hljs-keyword">inline</span> <span class="hljs-title function_"><span class="hljs-keyword">function</span> <span class="hljs-title">func</span></span>(a:<span class="hljs-type">Int</span>, b:<span class="hljs-type">Float</span>, ?c:<span class="hljs-type">String</span>, d:<span class="hljs-type">Bool</span>=<span class="hljs-literal">false</span>):<span class="hljs-type">Dynamic </span>{
<span class="hljs-keyword">return</span> {
x: <span class="hljs-type">0</span>,
y: <span class="hljs-type">true</span>,
z: <span class="hljs-type">false</span>,

a: <span class="hljs-type">1</span>.<span class="hljs-number">53</span>,
b: <span class="hljs-type">5e10</span>,
c: <span class="hljs-type">-12</span>,
h: <span class="hljs-type">null</span>
d: <span class="hljs-type">1_0_0_0_0</span>,

i: <span class="hljs-type">10000i32</span>,
u: <span class="hljs-type">2147483648u32</span>,
l: <span class="hljs-type">10000000000i64</span>,
f: <span class="hljs-type">5f64</span>,

n: <span class="hljs-type">null</span>,
};
}


<span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">quicksort</span></span>( lo : <span class="hljs-type">Int</span>, hi : <span class="hljs-type">Int </span>) : <span class="hljs-type">Void </span>{
<span class="hljs-keyword">override</span> <span class="hljs-title function_"><span class="hljs-keyword">function</span> <span class="hljs-title">quicksort</span></span>( lo : <span class="hljs-type">Int</span>, hi : <span class="hljs-type">Int </span>) : <span class="hljs-type">Void </span>{
<span class="hljs-keyword">var</span> i = lo;
<span class="hljs-keyword">var</span> j = hi;
<span class="hljs-keyword">var</span> buf = arr;
Expand Down
Loading

0 comments on commit cc29629

Please sign in to comment.