UNPKG

jaycc

Version:

### the Javascript C Compiler

189 lines (188 loc) 4.87 kB
/* 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 };