start multiple file support

This commit is contained in:
SimonFJ20 2024-12-12 12:04:57 +01:00
parent 242d5b16eb
commit ed279f7998
4 changed files with 110 additions and 84 deletions

View File

@ -1,6 +1,13 @@
import { Pos } from "./token.ts"; import { Pos } from "./token.ts";
import { VType } from "./vtype.ts"; import { VType } from "./vtype.ts";
export type Ast = File[];
export type File = {
path: string;
stmts: Stmt[];
};
export type UnaryType = "not"; export type UnaryType = "not";
export type BinaryType = export type BinaryType =
| "+" | "+"
@ -31,6 +38,7 @@ export type Stmt = {
export type StmtKind = export type StmtKind =
| { type: "error" } | { type: "error" }
| { type: "import"; path: Expr }
| { type: "break"; expr?: Expr } | { type: "break"; expr?: Expr }
| { type: "return"; expr?: Expr } | { type: "return"; expr?: Expr }
| { | {

View File

@ -43,6 +43,8 @@ export class Lexer {
return this.token("else", pos); return this.token("else", pos);
case "struct": case "struct":
return this.token("struct", pos); return this.token("struct", pos);
case "import":
return this.token("import", pos);
default: default:
return { ...this.token("ident", pos), identValue: value }; return { ...this.token("ident", pos), identValue: value };
} }

View File

@ -1,3 +1,4 @@
import { Ast, File } from "./ast.ts";
import { Checker } from "./checker.ts"; import { Checker } from "./checker.ts";
import { Reporter } from "./info.ts"; import { Reporter } from "./info.ts";
import { Lexer } from "./lexer.ts"; import { Lexer } from "./lexer.ts";
@ -5,6 +6,16 @@ import { Lowerer } from "./lowerer.ts";
import { Parser } from "./parser.ts"; import { Parser } from "./parser.ts";
import { Resolver } from "./resolver.ts"; import { Resolver } from "./resolver.ts";
class Compilation {
private files: File[] = [];
public constructor(private startFile: string) {}
public compile(): Ast {
throw new Error();
}
}
//const text = await Deno.readTextFile("example.slg"); //const text = await Deno.readTextFile("example.slg");
const text = await Deno.readTextFile(Deno.args[0]); const text = await Deno.readTextFile(Deno.args[0]);
@ -13,7 +24,7 @@ const reporter = new Reporter();
const lexer = new Lexer(text, reporter); const lexer = new Lexer(text, reporter);
const parser = new Parser(lexer, reporter); const parser = new Parser(lexer, reporter);
const ast = parser.parseStmts(); const ast = parser.parse();
// console.log(JSON.stringify(ast, null, 4)); // console.log(JSON.stringify(ast, null, 4));

View File

@ -21,51 +21,29 @@ export class Parser {
this.currentToken = lexer.next(); this.currentToken = lexer.next();
} }
private step() { public parse(): Stmt[] {
this.currentToken = this.lexer.next(); return this.parseStmts();
}
public done(): boolean {
return this.currentToken == null;
}
private current(): Token {
return this.currentToken!;
}
private pos(): Pos {
if (this.done()) {
return this.lexer.currentPos();
}
return this.current().pos;
} }
private test(type: string): boolean { private parseStmts(): Stmt[] {
return !this.done() && this.current().type === type; const stmts: Stmt[] = [];
while (!this.done()) {
if (this.test("fn")) {
stmts.push(this.parseFn());
} else if (
this.test("let") || this.test("return") || this.test("break")
) {
stmts.push(this.parseSingleLineBlockStmt());
this.eatSemicolon();
} else if (this.test("{") || this.test("if") || this.test("loop")) {
const expr = this.parseMultiLineBlockExpr();
stmts.push(this.stmt({ type: "expr", expr }, expr.pos));
} else {
stmts.push(this.parseAssign());
this.eatSemicolon();
} }
private report(msg: string, pos = this.pos()) {
this.reporter.reportError({
msg,
pos,
reporter: "Parser",
});
printStackTrace();
} }
return stmts;
private stmt(kind: StmtKind, pos: Pos): Stmt {
const id = this.nextNodeId;
this.nextNodeId += 1;
return { kind, pos, id };
}
private expr(kind: ExprKind, pos: Pos): Expr {
const id = this.nextNodeId;
this.nextNodeId += 1;
return { kind, pos, id };
}
private etype(kind: ETypeKind, pos: Pos): EType {
const id = this.nextNodeId;
this.nextNodeId += 1;
return { kind, pos, id };
} }
private parseMultiLineBlockExpr(): Expr { private parseMultiLineBlockExpr(): Expr {
@ -108,11 +86,11 @@ export class Parser {
this.step(); this.step();
} }
public parseExpr(): Expr { private parseExpr(): Expr {
return this.parsePrefix(); return this.parsePrefix();
} }
public parseBlock(): Expr { private parseBlock(): Expr {
const pos = this.pos(); const pos = this.pos();
this.step(); this.step();
let stmts: Stmt[] = []; let stmts: Stmt[] = [];
@ -163,28 +141,7 @@ export class Parser {
return this.expr({ type: "error" }, pos); return this.expr({ type: "error" }, pos);
} }
public parseStmts(): Stmt[] { private parseFn(): Stmt {
let stmts: Stmt[] = [];
while (!this.done()) {
if (this.test("fn")) {
stmts.push(this.parseFn());
} else if (
this.test("let") || this.test("return") || this.test("break")
) {
stmts.push(this.parseSingleLineBlockStmt());
this.eatSemicolon();
} else if (this.test("{") || this.test("if") || this.test("loop")) {
const expr = this.parseMultiLineBlockExpr();
stmts.push(this.stmt({ type: "expr", expr }, expr.pos));
} else {
stmts.push(this.parseAssign());
this.eatSemicolon();
}
}
return stmts;
}
public parseFn(): Stmt {
const pos = this.pos(); const pos = this.pos();
this.step(); this.step();
if (!this.test("ident")) { if (!this.test("ident")) {
@ -226,7 +183,7 @@ export class Parser {
); );
} }
public parseAnnoArgs(): Expr[] { private parseAnnoArgs(): Expr[] {
this.step(); this.step();
if (!this.test("(")) { if (!this.test("(")) {
this.report("expected '('"); this.report("expected '('");
@ -252,7 +209,7 @@ export class Parser {
return annoArgs; return annoArgs;
} }
public parseAnno(): Anno | null { private parseAnno(): Anno | null {
const pos = this.pos(); const pos = this.pos();
this.step(); this.step();
if (!this.test("[")) { if (!this.test("[")) {
@ -274,7 +231,7 @@ export class Parser {
return { ident, pos, values }; return { ident, pos, values };
} }
public parseFnParams(): Param[] { private parseFnParams(): Param[] {
this.step(); this.step();
if (this.test(")")) { if (this.test(")")) {
this.step(); this.step();
@ -305,7 +262,7 @@ export class Parser {
return params; return params;
} }
public parseParam(): { ok: true; value: Param } | { ok: false } { private parseParam(): { ok: true; value: Param } | { ok: false } {
const pos = this.pos(); const pos = this.pos();
if (this.test("ident")) { if (this.test("ident")) {
const ident = this.current().identValue!; const ident = this.current().identValue!;
@ -321,7 +278,7 @@ export class Parser {
return { ok: false }; return { ok: false };
} }
public parseLet(): Stmt { private parseLet(): Stmt {
const pos = this.pos(); const pos = this.pos();
this.step(); this.step();
const paramResult = this.parseParam(); const paramResult = this.parseParam();
@ -337,7 +294,7 @@ export class Parser {
const value = this.parseExpr(); const value = this.parseExpr();
return this.stmt({ type: "let", param, value }, pos); return this.stmt({ type: "let", param, value }, pos);
} }
public parseAssign(): Stmt { private parseAssign(): Stmt {
const pos = this.pos(); const pos = this.pos();
const subject = this.parseExpr(); const subject = this.parseExpr();
if (!this.test("=")) { if (!this.test("=")) {
@ -348,7 +305,7 @@ export class Parser {
return this.stmt({ type: "assign", subject, value }, pos); return this.stmt({ type: "assign", subject, value }, pos);
} }
public parseReturn(): Stmt { private parseReturn(): Stmt {
const pos = this.pos(); const pos = this.pos();
this.step(); this.step();
if (this.test(";")) { if (this.test(";")) {
@ -358,7 +315,7 @@ export class Parser {
return this.stmt({ type: "return", expr }, pos); return this.stmt({ type: "return", expr }, pos);
} }
public parseBreak(): Stmt { private parseBreak(): Stmt {
const pos = this.pos(); const pos = this.pos();
this.step(); this.step();
if (this.test(";")) { if (this.test(";")) {
@ -368,7 +325,7 @@ export class Parser {
return this.stmt({ type: "break", expr }, pos); return this.stmt({ type: "break", expr }, pos);
} }
public parseLoop(): Expr { private parseLoop(): Expr {
const pos = this.pos(); const pos = this.pos();
this.step(); this.step();
if (!this.test("{")) { if (!this.test("{")) {
@ -379,7 +336,7 @@ export class Parser {
return this.expr({ type: "loop", body }, pos); return this.expr({ type: "loop", body }, pos);
} }
public parseIf(): Expr { private parseIf(): Expr {
const pos = this.pos(); const pos = this.pos();
this.step(); this.step();
const cond = this.parseExpr(); const cond = this.parseExpr();
@ -404,7 +361,7 @@ export class Parser {
return this.expr({ type: "if", cond, truthy, falsy }, pos); return this.expr({ type: "if", cond, truthy, falsy }, pos);
} }
public parsePrefix(): Expr { private parsePrefix(): Expr {
const pos = this.pos(); const pos = this.pos();
if (this.test("not")) { if (this.test("not")) {
this.step(); this.step();
@ -435,7 +392,7 @@ export class Parser {
return this.parsePostfix(); return this.parsePostfix();
} }
public parseBinary(binaryType: BinaryType, pos: Pos): Expr | null { private parseBinary(binaryType: BinaryType, pos: Pos): Expr | null {
if (this.test(binaryType)) { if (this.test(binaryType)) {
this.step(); this.step();
const left = this.parsePrefix(); const left = this.parsePrefix();
@ -445,7 +402,7 @@ export class Parser {
return null; return null;
} }
public parsePostfix(): Expr { private parsePostfix(): Expr {
let subject = this.parseOperand(); let subject = this.parseOperand();
while (true) { while (true) {
const pos = this.pos(); const pos = this.pos();
@ -497,7 +454,7 @@ export class Parser {
return subject; return subject;
} }
public parseOperand(): Expr { private parseOperand(): Expr {
const pos = this.pos(); const pos = this.pos();
if (this.test("ident")) { if (this.test("ident")) {
const value = this.current().identValue!; const value = this.current().identValue!;
@ -551,7 +508,7 @@ export class Parser {
return this.expr({ type: "error" }, pos); return this.expr({ type: "error" }, pos);
} }
public parseEType(): EType { private parseEType(): EType {
const pos = this.pos(); const pos = this.pos();
if (this.test("ident")) { if (this.test("ident")) {
const ident = this.current().identValue!; const ident = this.current().identValue!;
@ -581,7 +538,7 @@ export class Parser {
return this.etype({ type: "error" }, pos); return this.etype({ type: "error" }, pos);
} }
public parseETypeStructFields(): Param[] { private parseETypeStructFields(): Param[] {
this.step(); this.step();
if (this.test("}")) { if (this.test("}")) {
this.step(); this.step();
@ -611,4 +568,52 @@ export class Parser {
this.step(); this.step();
return params; return params;
} }
private step() {
this.currentToken = this.lexer.next();
}
private done(): boolean {
return this.currentToken == null;
}
private current(): Token {
return this.currentToken!;
}
private pos(): Pos {
if (this.done()) {
return this.lexer.currentPos();
}
return this.current().pos;
}
private test(type: string): boolean {
return !this.done() && this.current().type === type;
}
private report(msg: string, pos = this.pos()) {
console.log(`Parser: ${msg} at ${pos.line}:${pos.col}`);
this.reporter.reportError({
msg,
pos,
reporter: "Parser",
});
printStackTrace();
}
private stmt(kind: StmtKind, pos: Pos): Stmt {
const id = this.nextNodeId;
this.nextNodeId += 1;
return { kind, pos, id };
}
private expr(kind: ExprKind, pos: Pos): Expr {
const id = this.nextNodeId;
this.nextNodeId += 1;
return { kind, pos, id };
}
private etype(kind: ETypeKind, pos: Pos): EType {
const id = this.nextNodeId;
this.nextNodeId += 1;
return { kind, pos, id };
}
} }