jaycc
Version:
### the Javascript C Compiler
189 lines (188 loc) • 4.87 kB
JavaScript
/* parser.tsplus */
import { closecurly, closeround, eof, eq, keyword, numberconst, opencurly, openround, semicolon } from './lexer.js';
import { identifier as tokenid } from './lexer.js';
import { identifier as astid, Program } from './ast.js';
import { REX } from './rex.js';
import { ASTfunction, Codeblock, datatype, Etype, numberconstant, Returnstm, SyntaxException } from './ast.js';
class Parser {
curtokens;
savedtokens;
constructor(ts) {
this.curtokens =
this.savedtokens = ts;
}
fail(msg = 'Parse error') {
this.curtokens = this.savedtokens;
throw new SyntaxException(msg);
return void 0;
}
expression() {
let numconst;
let node;
let t;
t = this.curtokens.shift()
|| this.fail();
if (eq(t, numberconst()))
numconst = t.contents;
else
return this.fail();
node = numberconstant(numconst);
this.savedtokens = this.curtokens;
return node;
}
returnstm() {
let kw;
let e;
let node;
let t;
t = this.curtokens.shift()
|| this.fail();
if ((eq(t, keyword()) && (t.contents === 'return')))
kw = t.contents;
else
return this.fail();
e = this.expression();
node = new Returnstm(e);
this.savedtokens = this.curtokens;
return node;
}
statement() {
let r;
let node;
let t;
r = this.returnstm();
t = this.curtokens.shift()
|| this.fail();
if (eq(t, semicolon()))
node = r;
else
return this.fail();
this.savedtokens = this.curtokens;
return node;
}
codeblock() {
let t;
let ts;
let ss;
let s;
let node;
let parses;
let err;
let fatal;
parses = 0;
err = false;
fatal = false;
ss = [];
t = this.curtokens.shift()
|| this.fail();
if (!eq(t, opencurly()))
this.fail();
ts = new Array(...this.curtokens);
while (!err) {
try {
ts = new Array(...this.curtokens);
s = this.statement();
ss.push(s);
parses++;
this.savedtokens = this.curtokens;
}
catch {
err = true;
this.curtokens = ts;
}
if (fatal)
this.fail();
}
if (!parses)
return this.fail();
t = this.curtokens.shift()
|| this.fail();
if (!eq(t, closecurly()))
this.fail();
node = new Codeblock(ss);
return node;
}
datatype() {
let node;
let t;
let kw;
let et;
t = this.curtokens.shift()
|| this.fail();
if (((eq(t, keyword())) && t.contents === 'int'))
kw = t.contents;
else
this.fail();
et = Etype.Int;
node = datatype(et);
this.savedtokens = this.curtokens;
return node;
}
fun() {
let d;
let i;
let c;
let node;
let t;
d = this.datatype();
t = this.curtokens.shift()
|| this.fail();
if (eq(t, tokenid()))
i = astid(t.contents);
else
return this.fail();
t = this.curtokens.shift()
|| this.fail();
if (!eq(t, openround()))
return this.fail();
t = this.curtokens.shift()
|| this.fail();
if (!eq(t, closeround()))
return this.fail();
this.savedtokens = this.curtokens;
c = this.codeblock();
this.savedtokens = this.curtokens;
node = new ASTfunction(d, i, c);
return node;
}
program() {
let f;
let fs;
let p;
let parsed;
let err;
let t;
let ts;
err = false;
parsed = 0;
fs = [];
ts = new Array(...this.curtokens);
while (!err) {
try {
ts = new Array(...this.curtokens);
f = this.fun();
this.savedtokens = this.curtokens;
fs.push(f);
parsed++;
}
catch {
err = true;
this.curtokens = ts;
}
}
if (!parsed)
this.fail();
t = this.curtokens.shift()
|| this.fail();
if ((!eq(t, eof())) || (this.curtokens.length))
this.fail();
p = new Program(fs);
return p;
}
parse() {
let a;
a = this.program();
return a;
}
}
export { Parser };