mirror of
				https://git.sfja.dk/Mikkel/slige.git
				synced 2025-10-29 09:58:15 +00:00 
			
		
		
		
	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 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 }; | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user