Skip to content

Commit

Permalink
Integrate more ECMA6 features to JavaScript target (#29)
Browse files Browse the repository at this point in the history
* Make use of statics in Parser class

* Export class @@prefixParser in javascript.tlt
  • Loading branch information
phorward committed Jul 21, 2022
1 parent 9f61b62 commit bad5c2e
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 73 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

This file is used to document any relevant changes done to UniCC.

## [main]

Current main branch.

- Target `javascript` updated to more recent JS/ECMAScript6 features

## [v1.7]

Released on Jan 20, 2021
Expand Down
139 changes: 66 additions & 73 deletions targets/javascript.tlt
Original file line number Diff line number Diff line change
Expand Up @@ -269,55 +269,48 @@ class @@prefixParserControlBlock {

// Parser

class @@prefixParser {
#grammar;
#lexer;
#parser;

constructor() {
this.#grammar = {
"symbols": [
export default class @@prefixParser {
static #grammar = {
"symbols": [
@@symbols
],
"productions": [
],
"productions": [
@@productions
],
"goal": @@goal
};

this.#lexer = {
"select": [
@@dfa-select
],
"index": [
],
"goal": @@goal
};

static #lexer = {
"select": [
@@dfa-select
],
"index": [
@@dfa-index
],
"chars": [
],
"chars": [
@@dfa-char
],
"transitions": [
],
"transitions": [
@@dfa-trans
],
"accept": [
],
"accept": [
@@dfa-accept
]
};

this.#parser = {
"action": [
]
};
static #parser = {
"action": [
@@action-table
],
"goto": [
],
"goto": [
@@goto-table
],
"default-production": [
@@default-productions
]
};
}

],
"default-production": [
@@default-productions
]
};

// Get character
get_char(pcb) {
static #get_char(pcb) {
// Get next character from input stream
if( typeof pcb.input === "function" )
return pcb.input();
Expand All @@ -332,13 +325,13 @@ class @@prefixParser {
return ch;
}

get_input(pcb, offset) {
static #get_input(pcb, offset) {
// Input buffering
while( offset >= pcb.buf.length ) {
if( pcb.is_eof )
return pcb.eof;

let ch = this.get_char(pcb);
let ch = this.#get_char(pcb);
if( ch === pcb.eof ) {
pcb.is_eof = true;
return pcb.eof;
Expand All @@ -347,12 +340,12 @@ class @@prefixParser {
pcb.buf += ch;
}

//console.log("get_input %s, %d, %s, %d", pcb.buf, offset, pcb.buf.charAt(offset), pcb.buf.charCodeAt(offset))
//console.log("#get_input %s, %d, %s, %d", pcb.buf, offset, pcb.buf.charAt(offset), pcb.buf.charCodeAt(offset))

return pcb.buf.charCodeAt(offset);
}

clear_input(pcb) {
static #clear_input(pcb) {
// Purge input from buffer that is not necessary anymore

if( pcb.buf.length ) {
Expand All @@ -373,12 +366,12 @@ class @@prefixParser {
pcb.sym = -1;
}

lex(pcb) {
static #lex(pcb) {
// Perform lexical analysis
let state = 0, length = 0;

let machine = Boolean(@@mode) ? 0 : this.#lexer["select"][pcb.tos.state];
let next = this.get_input(pcb, length);
let next = this.#get_input(pcb, length);

if( next === pcb.eof ) {
pcb.sym = @@eof;
Expand Down Expand Up @@ -413,7 +406,7 @@ class @@prefixParser {
}
}

next = this.get_input(pcb, length);
next = this.#get_input(pcb, length);
break;
}

Expand All @@ -426,7 +419,7 @@ class @@prefixParser {
//console.log("lex sym = %d, len = %d", pcb.sym, pcb.len);
}

get_sym(pcb) {
static #get_sym(pcb) {
// Get lookahead symbol
pcb.sym = -1;
pcb.len = 0;
Expand All @@ -435,11 +428,11 @@ class @@prefixParser {
if( Boolean(@@mode) )
while( true )
{
this.lex(pcb);
this.#lex(pcb);

// check for whitespace
if( pcb.sym > -1 && Boolean(this.#grammar["symbols"][pcb.sym]["is-whitespace"]) ) {
this.clear_input(pcb);
this.#clear_input(pcb);
continue;
}

Expand All @@ -448,11 +441,11 @@ class @@prefixParser {

// sensitive mode
else if( this.#lexer["select"][pcb.tos.state] > -1 )
this.lex(pcb);
this.#lex(pcb);

// If there is no matching DFA state machine, try to identify the
// end-of-file symbol. If this also fails, a parse error will raise.
else if( this.get_input(pcb, 0) === pcb.eof )
else if( this.constructor.#get_input(pcb, 0) === pcb.eof )
pcb.sym = @@eof;

return Boolean(pcb.sym > -1);
Expand All @@ -479,9 +472,9 @@ class @@prefixParser {
// Reduce
while( pcb.act & REDUCE ) {
// Set default left-hand side
pcb.lhs = this.#grammar["productions"][pcb.idx]["left-hand-side"];
pcb.lhs = this.constructor.#grammar["productions"][pcb.idx]["left-hand-side"];

//console.log("REDUCE idx = %d, prod = %s", pcb.idx, this.#grammar["productions"][pcb.idx]["production"]);
//console.log("REDUCE idx = %d, prod = %s", pcb.idx, this.constructor.#grammar["productions"][pcb.idx]["production"]);
// print("state", pcb.tos.state);

// Call reduce function
Expand All @@ -493,7 +486,7 @@ class @@prefixParser {
// Drop right-hand side
let cnodes = null, node = null;

for( let i = 0; i < this.#grammar["productions"][pcb.idx]["length"]; i++ ) {
for( let i = 0; i < this.constructor.#grammar["productions"][pcb.idx]["length"]; i++ ) {
let item = pcb.stack.pop();

if( item.node )
Expand All @@ -512,27 +505,27 @@ class @@prefixParser {
pcb.tos.value = pcb.ret;

// Handle AST nodes
if( Boolean( this.#grammar["productions"][pcb.idx]["emit"] ) ) {
//console.log("%s = %s", this.#grammar["productions"][pcb.idx]["production"], this.#grammar["productions"][pcb.idx]["emit"]);
node = new @@prefixNode(this.#grammar["productions"][pcb.idx]["emit"], null, cnodes);
if( Boolean( this.constructor.#grammar["productions"][pcb.idx]["emit"] ) ) {
//console.log("%s = %s", this.constructor.#grammar["productions"][pcb.idx]["production"], this.#grammar["productions"][pcb.idx]["emit"]);
node = new @@prefixNode(this.constructor.#grammar["productions"][pcb.idx]["emit"], null, cnodes);
}

// Goal symbol reduced, and stack is empty?
if( pcb.lhs === @@goal && pcb.stack.length === 1 ) {
pcb.tos.node = node ? node : cnodes;
this.clear_input(pcb);
this.constructor.#clear_input(pcb);
pcb.act = SUCCESS;
break;
}

// Get goto table entry
pcb.act = this.#parser["goto"][pcb.tos.state][pcb.lhs][0];
pcb.idx = this.#parser["goto"][pcb.tos.state][pcb.lhs][1];
pcb.act = this.constructor.#parser["goto"][pcb.tos.state][pcb.lhs][0];
pcb.idx = this.constructor.#parser["goto"][pcb.tos.state][pcb.lhs][1];

pcb.tos = new @@prefixParserToken();
pcb.stack.push(pcb.tos)

pcb.tos.symbol = this.#grammar["symbols"][pcb.lhs];
pcb.tos.symbol = this.constructor.#grammar["symbols"][pcb.lhs];
pcb.tos.state = pcb.act & REDUCE ? -1 : pcb.idx;
pcb.tos.value = pcb.ret;

Expand All @@ -547,18 +540,18 @@ class @@prefixParser {
break;

// Get next input symbol
this.get_sym(pcb);
this.constructor.#get_sym(pcb);

//console.log("pcb.sym = %d (%s)", pcb.sym, this.#grammar["symbols"][pcb.sym]["symbol"]);
//console.log("pcb.sym = %d (%s)", pcb.sym, this.constructor.#grammar["symbols"][pcb.sym]["symbol"]);
//console.log("pcb.len = %d", pcb.len);

// Get action table entry
if( pcb.sym in this.#parser["action"][pcb.tos.state] ) {
pcb.act = this.#parser["action"][pcb.tos.state][pcb.sym][0];
pcb.idx = this.#parser["action"][pcb.tos.state][pcb.sym][1];
if( pcb.sym in this.constructor.#parser["action"][pcb.tos.state] ) {
pcb.act = this.constructor.#parser["action"][pcb.tos.state][pcb.sym][0];
pcb.idx = this.constructor.#parser["action"][pcb.tos.state][pcb.sym][1];
} else {
// Otherwise, apply default production
pcb.idx = this.#parser["default-production"][pcb.tos.state];
pcb.idx = this.constructor.#parser["default-production"][pcb.tos.state];

if( pcb.idx > -1 ) {
pcb.act = REDUCE;
Expand All @@ -573,14 +566,14 @@ class @@prefixParser {
pcb.line,
pcb.column,
Object.keys(
this.#parser["action"][pcb.tos.state]
).map(sym => this.#grammar.symbols[sym].symbol).sort()
this.constructor.#parser["action"][pcb.tos.state]
).map(sym => this.constructor.#grammar.symbols[sym].symbol).sort()
);
}

// Shift
if( pcb.act & SHIFT ) {
//console.log("SHIFT sym = %d (%s)", pcb.sym, this.#grammar["symbols"][pcb.sym]["symbol"]);
//console.log("SHIFT sym = %d (%s)", pcb.sym, this.constructor.#grammar["symbols"][pcb.sym]["symbol"]);

pcb.tos = new @@prefixParserToken();
pcb.stack.push(pcb.tos);
Expand All @@ -590,7 +583,7 @@ class @@prefixParser {
pcb[ "parse_" + pcb.idx ]();

pcb.tos.state = pcb.act & REDUCE ? -1 : pcb.idx;
pcb.tos.symbol = this.#grammar["symbols"][pcb.sym];
pcb.tos.symbol = this.constructor.#grammar["symbols"][pcb.sym];

pcb.tos.line = pcb.line;
pcb.tos.column = pcb.column;
Expand All @@ -600,7 +593,7 @@ class @@prefixParser {
pcb.tos.node = new @@prefixNode(pcb.tos.symbol["emit"], pcb.top);

if( pcb.sym !== @@eof && pcb.sym !== @@error ) {
this.clear_input(pcb);
this.constructor.#clear_input(pcb);
pcb.old_sym = -1
}
}
Expand Down

0 comments on commit bad5c2e

Please sign in to comment.