Skip to content

Commit

Permalink
Merge pull request #3993 from b4n/js-keywords
Browse files Browse the repository at this point in the history
JavaScript: Improve support for contextual keywords as identifiers
  • Loading branch information
masatake committed May 9, 2024
2 parents 07cbb8c + eb830ef commit 141a8e0
Show file tree
Hide file tree
Showing 5 changed files with 360 additions and 24 deletions.
95 changes: 95 additions & 0 deletions Units/parser-javascript.r/contextual.d/expected.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
Function input.js /^ Function() { return 0x32 }$/;" m class:Syn3
Function input.js /^ Function() { return Syn2; },$/;" m class:Syn2
Function input.js /^ Function:function() { return Syn1; },$/;" m class:Syn1
Function input.js /^function Function() { return 0x103; }$/;" c
Object input.js /^ Object() { return 0x31 }$/;" m class:Syn3
Object input.js /^ Object() { return this; },$/;" m class:Syn2
Object input.js /^ Object:function() { return this; },$/;" m class:Syn1
Object input.js /^function Object() { return 0x102; }$/;" c
Syn1 input.js /^let Syn1=function(){}$/;" c
Syn2 input.js /^let Syn2=function(){}$/;" c
Syn3 input.js /^class Syn3 {$/;" c
as input.js /^ as() { return 0x21; }$/;" m class:Syn3
as input.js /^ as() { return 0x21; },$/;" m class:Syn2
as input.js /^ as:function() { return 0x21; },$/;" m class:Syn1
as input.js /^function as() { return 0x21; }$/;" f
async input.js /^ async() { return 0x20; }$/;" m class:Syn3
async input.js /^ async() {$/;" m class:Syn2
async input.js /^ async:function() {$/;" m class:Syn1
async input.js /^function async() { return 0x22; }$/;" f
await input.js /^ await() { return 0x01; }$/;" m class:Syn3
await input.js /^ await() { return 0x01; },$/;" m class:Syn2
await input.js /^ await:function() { return 0x01; },$/;" m class:Syn1
await input.js /^function await() { return 0x01; }$/;" f
from input.js /^ from() { return 0x22; }$/;" m class:Syn3
from input.js /^ from() { return 0x22; },$/;" m class:Syn2
from input.js /^ from:function() { return 0x22; },$/;" m class:Syn1
from input.js /^function from() { return 0x23; }$/;" f
get input.js /^ get() { return 0x24; }$/;" m class:Syn3
get input.js /^ get() {$/;" m class:Syn2
get input.js /^ get:function() {$/;" m class:Syn1
get input.js /^function get() { return 0x24; }$/;" f
implements input.js /^ implements() { return 0x13; }$/;" m class:Syn3
implements input.js /^ implements() { return 0x13; },$/;" m class:Syn2
implements input.js /^ implements:function() { return 0x13; },$/;" m class:Syn1
implements input.js /^function implements() { return 0x13; }$/;" f
interface input.js /^ interface() { return 0x14; }$/;" m class:Syn3
interface input.js /^ interface() { return 0x14; },$/;" m class:Syn2
interface input.js /^ interface:function() { return 0x14; },$/;" m class:Syn1
interface input.js /^function interface() { return 0x14; }$/;" f
length input.js /^ length:0,$/;" p class:Syn1
length input.js /^ length:0,$/;" p class:Syn2
let input.js /^ let() { return 0x11; }$/;" m class:Syn3
let input.js /^ let() { return 0x11; },$/;" m class:Syn2
let input.js /^ let:function() { return 0x11; },$/;" m class:Syn1
let input.js /^function let() { return 0x11; }$/;" f
meta input.js /^ meta() { return 0x23; }$/;" m class:Syn3
meta input.js /^ meta() { return 0x23; },$/;" m class:Syn2
meta input.js /^ meta:function() { return 0x23; },$/;" m class:Syn1
meta input.js /^function meta() { return 0x25; }$/;" f
of input.js /^ of() { return 0x24; }$/;" m class:Syn3
of input.js /^ of() { return 0x24; },$/;" m class:Syn2
of input.js /^ of:function() { return 0x24; },$/;" m class:Syn1
of input.js /^function of() { return 0x26; }$/;" f
package input.js /^ package() { return 0x15; }$/;" m class:Syn3
package input.js /^ package() { return 0x15; },$/;" m class:Syn2
package input.js /^ package:function() { return 0x15; },$/;" m class:Syn1
package input.js /^function package() { return 0x15; }$/;" f
private input.js /^ private() { return 0x16; }$/;" m class:Syn3
private input.js /^ private() { return 0x16; },$/;" m class:Syn2
private input.js /^ private:function() { return 0x16; },$/;" m class:Syn1
private input.js /^function private() { return 0x16; }$/;" f
protected input.js /^ protected() { return 0x17; }$/;" m class:Syn3
protected input.js /^ protected() { return 0x17; },$/;" m class:Syn2
protected input.js /^ protected:function() { return 0x17; },$/;" m class:Syn1
protected input.js /^function protected() { return 0x17; }$/;" f
prototype input.js /^ prototype() { return 0x30 }$/;" m class:Syn3
prototype input.js /^ prototype() { return this.prototype; },$/;" m class:Syn2
prototype input.js /^ prototype:function() { return this.prototype; },$/;" m class:Syn1
prototype input.js /^function prototype() { return 0x101; }$/;" f
public input.js /^ public() { return 0x18; }$/;" m class:Syn3
public input.js /^ public() { return 0x18; },$/;" m class:Syn2
public input.js /^ public:function() { return 0x18; },$/;" m class:Syn1
public input.js /^function public() { return 0x18; }$/;" f
s1 input.js /^let s1 = new Syn1();$/;" v
s2 input.js /^let s2 = new Syn2();$/;" v
sap input.js /^ sap() { return "sap"; },$/;" m class:Syn2
sap input.js /^ sap() { return 0x33 }$/;" m class:Syn3
sap input.js /^ sap:function() { return "sap"; },$/;" m class:Syn1
sap input.js /^function sap() { return 0x104; }$/;" f
set input.js /^ set(n) { return 0x25; }$/;" m class:Syn3
set input.js /^ set(n) {$/;" m class:Syn2
set input.js /^ set:function(n) {$/;" m class:Syn1
set input.js /^function set() { return 0x27; }$/;" f
static input.js /^ static() { return 0x12; }$/;" m class:Syn3
static input.js /^ static() { return 0x12; },$/;" m class:Syn2
static input.js /^ static:function() { return 0x12; },$/;" m class:Syn1
static input.js /^function static() { return 0x12; }$/;" f
target input.js /^ target() { return 0x25; },$/;" m class:Syn2
target input.js /^ target() { return 0x26; }$/;" m class:Syn3
target input.js /^ target:function() { return 0x25; },$/;" m class:Syn1
target input.js /^function target() { return 0x28; }$/;" f
yield input.js /^ yield() { return 0x02; }$/;" m class:Syn3
yield input.js /^ yield() { return 0x02; },$/;" m class:Syn2
yield input.js /^ yield:function() { return 0x02; },$/;" m class:Syn1
yield input.js /^function yield() { return 0x02; } \/\/ invalid in strict mode$/;" f
180 changes: 180 additions & 0 deletions Units/parser-javascript.r/contextual.d/input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
#!/usr/bin/env gjs
//~ "use strict"

let Syn1=function(){}
Syn1.prototype = {
await:function() { return 0x01; },
yield:function() { return 0x02; },
// strict-mode keywords (that are still allowed in some situations)
let:function() { return 0x11; },
static:function() { return 0x12; },
implements:function() { return 0x13; },
interface:function() { return 0x14; },
package:function() { return 0x15; },
private:function() { return 0x16; },
protected:function() { return 0x17; },
public:function() { return 0x18; },
// not keywords
as:function() { return 0x21; },
from:function() { return 0x22; },
meta:function() { return 0x23; },
of:function() { return 0x24; },
target:function() { return 0x25; },
get:function() {
return this.length;
},
length:0,
set:function(n) {
this.length=n;
},
async:function() {
return -this.length;
},
// stuff specific to the uctags parser
prototype:function() { return this.prototype; },
Object:function() { return this; },
Function:function() { return Syn1; },
sap:function() { return "sap"; },
}

let Syn2=function(){}
Syn2.prototype = {
await() { return 0x01; },
yield() { return 0x02; },
// strict-mode keywords (that are still allowed in some situations)
let() { return 0x11; },
static() { return 0x12; },
implements() { return 0x13; },
interface() { return 0x14; },
package() { return 0x15; },
private() { return 0x16; },
protected() { return 0x17; },
public() { return 0x18; },
// not keywords
as() { return 0x21; },
from() { return 0x22; },
meta() { return 0x23; },
of() { return 0x24; },
target() { return 0x25; },
get() {
return this.length;
},
length:0,
set(n) {
this.length=n;
},
async() {
return -this.length;
},
// stuff specific to the uctags parser
prototype() { return this.prototype; },
Object() { return this; },
Function() { return Syn2; },
sap() { return "sap"; },
}

class Syn3 {
await() { return 0x01; }
yield() { return 0x02; }
// strict-mode keywords (that are still allowed in some situations)
let() { return 0x11; }
static() { return 0x12; }
implements() { return 0x13; }
interface() { return 0x14; }
package() { return 0x15; }
private() { return 0x16; }
protected() { return 0x17; }
public() { return 0x18; }
// not keywords
async() { return 0x20; }
as() { return 0x21; }
from() { return 0x22; }
get() { return 0x24; }
meta() { return 0x23; }
of() { return 0x24; }
set(n) { return 0x25; }
target() { return 0x26; }
// stuff specific to the uctags parser
prototype() { return 0x30 }
Object() { return 0x31 }
Function() { return 0x32 }
sap() { return 0x33 }
}

let s1 = new Syn1();
let s2 = new Syn2();
console.log(s1.await(), s2.await());
console.log(s1.yield(), s2.yield());
console.log(s1.let(), s2.let());
console.log(s1.static(), s2.static());
console.log(s1.implements(), s2.implements());
console.log(s1.interface(), s2.interface());
console.log(s1.package(), s2.package());
console.log(s1.private(), s2.private());
console.log(s1.protected(), s2.protected());
console.log(s1.public(), s2.public());
console.log(s1.as(), s2.as());
console.log(s1.from(), s2.from());
console.log(s1.meta(), s2.meta());
console.log(s1.of(), s2.of());
console.log(s1.target(), s2.target());
console.log(s1.get(), s2.get());
s1.set(21);
s2.set(21);
console.log(s1.get(), s2.get());
console.log(s1.async(), s2.async());
console.log(s1.prototype(), s2.prototype());
console.log(s1.Object(), s2.Object());
console.log(s1.Function(), s2.Function());
console.log(s1.sap(), s2.sap());

/* functions */

function await() { return 0x01; }
function yield() { return 0x02; } // invalid in strict mode
// strict-mode keywords, all invalid in strict mode in this case
function let() { return 0x11; }
function static() { return 0x12; }
function implements() { return 0x13; }
function interface() { return 0x14; }
function package() { return 0x15; }
function private() { return 0x16; }
function protected() { return 0x17; }
function public() { return 0x18; }
// not keywords
function as() { return 0x21; }
function async() { return 0x22; }
function from() { return 0x23; }
function get() { return 0x24; }
function meta() { return 0x25; }
function of() { return 0x26; }
function set() { return 0x27; }
function target() { return 0x28; }
// stuff specific to the uctags parser
function prototype() { return 0x101; }
function Object() { return 0x102; }
function Function() { return 0x103; }
function sap() { return 0x104; }

console.log(await())
console.log(yield()) // invalid in strict mode
console.log(let()) // invalid in strict mode
console.log(static()) // invalid in strict mode
console.log(implements()) // invalid in strict mode
console.log(interface()) // invalid in strict mode
console.log(package()) // invalid in strict mode
console.log(private()) // invalid in strict mode
console.log(protected()) // invalid in strict mode
console.log(public()) // invalid in strict mode
console.log(as())
console.log(async())
console.log(from())
console.log(get())
console.log(meta())
console.log(of())
console.log(set())
console.log(target())
console.log(prototype())
console.log(Object())
console.log(Function())
console.log(sap())
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Foo input.js /^class Foo {$/;" c
async input.js /^ async async() {}$/;" m class:Foo
async input.js /^ static async async() {}$/;" m class:Foo
static input.js /^ static static() {}$/;" m class:Foo
staticProperty input.js /^ static staticProperty = 42;$/;" M class:Foo
10 changes: 10 additions & 0 deletions Units/parser-javascript.r/qualified-contextual.d/input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

class Foo {
async async() {}
static async async() {}
static static() {}
static staticProperty = 42;
static {
console.log('Class static initialization block called');
}
}

0 comments on commit 141a8e0

Please sign in to comment.