start multiple file support
This commit is contained in:
		
							parent
							
								
									242d5b16eb
								
							
						
					
					
						commit
						ed279f7998
					
				@ -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 }
 | 
			
		||||
    | {
 | 
			
		||||
 | 
			
		||||
@ -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 };
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -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));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -21,51 +21,29 @@ export class Parser {
 | 
			
		||||
        this.currentToken = lexer.next();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private step() {
 | 
			
		||||
        this.currentToken = this.lexer.next();
 | 
			
		||||
    }
 | 
			
		||||
    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;
 | 
			
		||||
    public parse(): Stmt[] {
 | 
			
		||||
        return this.parseStmts();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private test(type: string): boolean {
 | 
			
		||||
        return !this.done() && this.current().type === type;
 | 
			
		||||
    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();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
    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 };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user