From ed279f799872b83d5f1181deecfb804ba26ea092 Mon Sep 17 00:00:00 2001 From: SimonFJ20 Date: Thu, 12 Dec 2024 12:04:57 +0100 Subject: [PATCH] start multiple file support --- compiler/ast.ts | 8 +++ compiler/lexer.ts | 2 + compiler/main.ts | 13 +++- compiler/parser.ts | 171 +++++++++++++++++++++++---------------------- 4 files changed, 110 insertions(+), 84 deletions(-) diff --git a/compiler/ast.ts b/compiler/ast.ts index cf92922..bb29a98 100644 --- a/compiler/ast.ts +++ b/compiler/ast.ts @@ -1,6 +1,13 @@ import { Pos } from "./token.ts"; import { VType } from "./vtype.ts"; +export type Ast = File[]; + +export type File = { + path: string; + stmts: Stmt[]; +}; + export type UnaryType = "not"; export type BinaryType = | "+" @@ -31,6 +38,7 @@ export type Stmt = { export type StmtKind = | { type: "error" } + | { type: "import"; path: Expr } | { type: "break"; expr?: Expr } | { type: "return"; expr?: Expr } | { diff --git a/compiler/lexer.ts b/compiler/lexer.ts index 3853040..f831e9f 100644 --- a/compiler/lexer.ts +++ b/compiler/lexer.ts @@ -43,6 +43,8 @@ export class Lexer { return this.token("else", pos); case "struct": return this.token("struct", pos); + case "import": + return this.token("import", pos); default: return { ...this.token("ident", pos), identValue: value }; } diff --git a/compiler/main.ts b/compiler/main.ts index 52c706b..e0b7b84 100644 --- a/compiler/main.ts +++ b/compiler/main.ts @@ -1,3 +1,4 @@ +import { Ast, File } from "./ast.ts"; import { Checker } from "./checker.ts"; import { Reporter } from "./info.ts"; import { Lexer } from "./lexer.ts"; @@ -5,6 +6,16 @@ import { Lowerer } from "./lowerer.ts"; import { Parser } from "./parser.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(Deno.args[0]); @@ -13,7 +24,7 @@ const reporter = new Reporter(); const lexer = new Lexer(text, reporter); const parser = new Parser(lexer, reporter); -const ast = parser.parseStmts(); +const ast = parser.parse(); // console.log(JSON.stringify(ast, null, 4)); diff --git a/compiler/parser.ts b/compiler/parser.ts index 0be79c1..f8b110f 100644 --- a/compiler/parser.ts +++ b/compiler/parser.ts @@ -21,51 +21,29 @@ export class Parser { this.currentToken = lexer.next(); } - private step() { - this.currentToken = this.lexer.next(); + public parse(): Stmt[] { + 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(); + + private parseStmts(): Stmt[] { + 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(); + } } - return this.current().pos; - } - - private test(type: string): boolean { - return !this.done() && this.current().type === type; - } - - private report(msg: string, pos = this.pos()) { - 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 }; + return stmts; } private parseMultiLineBlockExpr(): Expr { @@ -108,11 +86,11 @@ export class Parser { this.step(); } - public parseExpr(): Expr { + private parseExpr(): Expr { return this.parsePrefix(); } - public parseBlock(): Expr { + private parseBlock(): Expr { const pos = this.pos(); this.step(); let stmts: Stmt[] = []; @@ -163,28 +141,7 @@ export class Parser { return this.expr({ type: "error" }, pos); } - public parseStmts(): 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 { + private parseFn(): Stmt { const pos = this.pos(); this.step(); if (!this.test("ident")) { @@ -226,7 +183,7 @@ export class Parser { ); } - public parseAnnoArgs(): Expr[] { + private parseAnnoArgs(): Expr[] { this.step(); if (!this.test("(")) { this.report("expected '('"); @@ -252,7 +209,7 @@ export class Parser { return annoArgs; } - public parseAnno(): Anno | null { + private parseAnno(): Anno | null { const pos = this.pos(); this.step(); if (!this.test("[")) { @@ -274,7 +231,7 @@ export class Parser { return { ident, pos, values }; } - public parseFnParams(): Param[] { + private parseFnParams(): Param[] { this.step(); if (this.test(")")) { this.step(); @@ -305,7 +262,7 @@ export class Parser { return params; } - public parseParam(): { ok: true; value: Param } | { ok: false } { + private parseParam(): { ok: true; value: Param } | { ok: false } { const pos = this.pos(); if (this.test("ident")) { const ident = this.current().identValue!; @@ -321,7 +278,7 @@ export class Parser { return { ok: false }; } - public parseLet(): Stmt { + private parseLet(): Stmt { const pos = this.pos(); this.step(); const paramResult = this.parseParam(); @@ -337,7 +294,7 @@ export class Parser { const value = this.parseExpr(); return this.stmt({ type: "let", param, value }, pos); } - public parseAssign(): Stmt { + private parseAssign(): Stmt { const pos = this.pos(); const subject = this.parseExpr(); if (!this.test("=")) { @@ -348,7 +305,7 @@ export class Parser { return this.stmt({ type: "assign", subject, value }, pos); } - public parseReturn(): Stmt { + private parseReturn(): Stmt { const pos = this.pos(); this.step(); if (this.test(";")) { @@ -358,7 +315,7 @@ export class Parser { return this.stmt({ type: "return", expr }, pos); } - public parseBreak(): Stmt { + private parseBreak(): Stmt { const pos = this.pos(); this.step(); if (this.test(";")) { @@ -368,7 +325,7 @@ export class Parser { return this.stmt({ type: "break", expr }, pos); } - public parseLoop(): Expr { + private parseLoop(): Expr { const pos = this.pos(); this.step(); if (!this.test("{")) { @@ -379,7 +336,7 @@ export class Parser { return this.expr({ type: "loop", body }, pos); } - public parseIf(): Expr { + private parseIf(): Expr { const pos = this.pos(); this.step(); const cond = this.parseExpr(); @@ -404,7 +361,7 @@ export class Parser { return this.expr({ type: "if", cond, truthy, falsy }, pos); } - public parsePrefix(): Expr { + private parsePrefix(): Expr { const pos = this.pos(); if (this.test("not")) { this.step(); @@ -435,7 +392,7 @@ export class Parser { return this.parsePostfix(); } - public parseBinary(binaryType: BinaryType, pos: Pos): Expr | null { + private parseBinary(binaryType: BinaryType, pos: Pos): Expr | null { if (this.test(binaryType)) { this.step(); const left = this.parsePrefix(); @@ -445,7 +402,7 @@ export class Parser { return null; } - public parsePostfix(): Expr { + private parsePostfix(): Expr { let subject = this.parseOperand(); while (true) { const pos = this.pos(); @@ -497,7 +454,7 @@ export class Parser { return subject; } - public parseOperand(): Expr { + private parseOperand(): Expr { const pos = this.pos(); if (this.test("ident")) { const value = this.current().identValue!; @@ -551,7 +508,7 @@ export class Parser { return this.expr({ type: "error" }, pos); } - public parseEType(): EType { + private parseEType(): EType { const pos = this.pos(); if (this.test("ident")) { const ident = this.current().identValue!; @@ -581,7 +538,7 @@ export class Parser { return this.etype({ type: "error" }, pos); } - public parseETypeStructFields(): Param[] { + private parseETypeStructFields(): Param[] { this.step(); if (this.test("}")) { this.step(); @@ -611,4 +568,52 @@ export class Parser { this.step(); 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 }; + } }