jaycc
Version:
### the Javascript C Compiler
244 lines (201 loc) • 5.04 kB
text/typescript
/* ast.ts */
enum Etype {
Int
};
type Numberconstant = number & {tag:string};
type Expr =
Numberconstant;
type Decl = any;
type Assignment = any;
type Identifier = string & {tag:string};
type Datatype = Etype & {tag:string};
type AST =
| Program
| Numberconstant
| Decl
| Assignment
| Identifier
| Datatype
| ASTfunction
| Codeblock
| Stm
| Returnstm;
type Tstm =
(
| (Decl & {tag:string})
| (Assignment & {tag:string})
| Returnstm
);
/*abstract*/ interface Iase {
constructor: Function;
tag: string;
}
interface Ireturnstm extends Iase {
expr: Expr;
}
interface Istm {
decl?: Decl;
assignment?: Assignment;
returnstm?: Returnstm;
}
interface IsyntaxE extends Error {
constructor: Function;
}
interface Icodeblock extends Iase {
stms: Stm[];
}
interface Ifunction extends Iase {
type: Datatype;
name: Identifier;
/* params: Variable[]; */
body: Codeblock;
}
interface Iprogram extends Iase {
fns:ASTfunction[];
}
let test:()=>void;
let log:(...data:any[])=>void;
let numberconstant:(input:number)=>Numberconstant;
let expr:(input:Numberconstant)=>Expr;
let identifier:(input:string)=>Identifier;
let datatype:(input:Etype)=>Datatype;
log = console.log;
numberconstant = (input:number): Numberconstant => {
let ret:Numberconstant;
ret = new Number(input) as Numberconstant;
ret.tag = 'Numberconstant';
return ret;
}
expr = (input:Numberconstant): Expr => {
let ret: Expr;
ret = new Number(input as number) as Expr;
ret.tag = 'Expr';
return ret;
}
identifier = (input:string): Identifier => {
let ret: Identifier;
ret = new String(input) as Identifier;
ret.tag = 'Identifier';
return ret;
}
datatype = (input:Etype): Datatype => {
let ret: Datatype;
ret = new Number(input as number) as Datatype;
ret.tag = 'Datatype';
return ret;
}
class SyntaxException extends Error implements IsyntaxE {
constructor(msg:string) {
super(msg);
}
}
abstract class ASE implements Iase {
abstract tag: string;
constructor() {
void 0;
}
}
class ASTfunction extends ASE implements Ifunction {
tag: string;
type: Datatype;
name: Identifier;
body: Codeblock;
constructor(type:Datatype,name:Identifier,body:Codeblock) {
super();
this.tag = 'Function';
this.type = type;
this.name = name;
this.body = body;
}
}
class Codeblock extends ASE implements Icodeblock {
tag: string;
stms: Stm[];
constructor(input:Stm[]) {
super();
this.tag = 'Codeblock';
this.stms = input;
}
}
class Returnstm extends ASE implements Ireturnstm {
tag: string;
expr: Expr;
constructor(input:Expr) {
super();
this.tag = 'Returnstm';
this.expr = input;
}
}
class Stm implements Istm {
tag: string;
decl?: Decl;
assignment?: Assignment;
returnstm?: Returnstm;
constructor(input:Decl);
constructor(input:Assignment);
constructor(input:Returnstm);
constructor(input:Tstm) {
let ok:boolean;
this.tag = 'Stm';
ok = false;
switch(input.tag) {
case 'Decl':
this.decl = input;
ok = true;
break;
case 'Assigment':
this.assignment = input;
ok = true;
break;
case 'Returnstm':
this.returnstm = input;
ok = true;
break;
default:
ok = false;
break;
}
if (!ok)
throw new SyntaxException('Syntax error in statement');
}
}
class Program extends ASE implements Iprogram {
tag: string;
fns:ASTfunction[];
constructor(input:ASTfunction[]) {
super();
this.tag = 'Program';
this.fns = input;
}
}
test = (): void => {
let r:Returnstm;
let e:Expr;
let s:Stm;
let n:Numberconstant;
let c:Codeblock;
let i:Identifier;
let d:Datatype;
let f:ASTfunction;
let p:Program;
let ast:AST;
n = numberconstant(5);
e = expr(n);
r = new Returnstm(e);
s = new Stm(r);
c = new Codeblock([s]);
i = identifier('main');
d = datatype(Etype.Int);
f = new ASTfunction(d, i, c);
p = new Program([f]);
ast = p;
log(JSON.stringify(ast,null,3));
return void 0;
}
export { test };
export type { AST };
export type { Numberconstant, Expr, Decl, Assignment,
Identifier, Datatype };
export { numberconstant, expr, identifier, datatype };
export { ASTfunction, Codeblock, Returnstm, Stm,
Program, SyntaxException, Etype };