stage2 迁移ast解析器 stage1 防止错误死循环
This commit is contained in:
1 parent
bb9d0a9f18
commit
b5a7a811b3
7 files changed
+3000
-71
No files matched your search
+84
-8
@@ -9,6 +9,8 @@ type .{ .ByteBuffer } = @import("./utils/byte_buffer.spl");
|
||||
type .{ .Vec } = @import("./utils/vec.spl");
|
||||
type .{ .Token, .kind_name } = @import("./token.spl");
|
||||
type .{ .Lexer } = @import("./lexer.spl");
|
||||
type Ast = @import("./ast.spl");
|
||||
type Parser = @import("./parser.spl");
|
||||
type .{ .append_usize } = @import("./utils/fmt.spl");
|
||||
type .{ .read_all, .print, .eprint } = @import("./utils/io.spl");
|
||||
type .{ .set_new, .set_add, .set_drop } = @import("./utils/source.spl");
|
||||
@@ -18,9 +20,9 @@ type Logger = @import("./utils/log.spl");
|
||||
fn token_at(tokens: *Vec, index: usize): Token {
|
||||
match Vec.get(tokens, index) {
|
||||
.Ok(ptr) => { ret (ptr as *Token).*; },
|
||||
.Err(error) => { ret Token.make(.Unknown(0), ByteView.empty(), 0, 0); },
|
||||
.Err(error) => { ret Token.make(.Unknown(0), ByteView.empty(), 0, 0, 0); },
|
||||
}
|
||||
ret Token.make(.Unknown(0), ByteView.empty(), 0, 0);
|
||||
ret Token.make(.Unknown(0), ByteView.empty(), 0, 0, 0);
|
||||
}
|
||||
|
||||
// 追加成功返回 true;失败(仅 OOM)返回 false。
|
||||
@@ -136,6 +138,77 @@ fn dump_lex(log: *Logger, path: ByteView): i32 {
|
||||
ret 0;
|
||||
}
|
||||
|
||||
fn dump_ast(log: *Logger, path: ByteView): i32 {
|
||||
var content = ByteBuffer.new();
|
||||
defer { ByteBuffer.drop(&content); }
|
||||
match read_all(path, &content) {
|
||||
.Ok => {},
|
||||
.Err(error) => {
|
||||
Logger.error(log, "cannot read input file");
|
||||
ret 1;
|
||||
},
|
||||
}
|
||||
var text = ByteView.from_slice(ByteBuffer.as_slice(content));
|
||||
|
||||
var sources = set_new();
|
||||
defer { set_drop(&sources); }
|
||||
match set_add(&sources, path, text) {
|
||||
.Ok(index) => {},
|
||||
.Err(error) => {
|
||||
Logger.error(log, "cannot register source");
|
||||
ret 1;
|
||||
},
|
||||
}
|
||||
var diag = Diag.new(&sources);
|
||||
defer { Diag.drop(&diag); }
|
||||
|
||||
var tokens = Vec.blank(@sizeof(Token), @alignof(Token));
|
||||
match Lexer.lex(text, &diag, 0) {
|
||||
.Ok(v) => { tokens = v; },
|
||||
.Err(error) => {
|
||||
Logger.error(log, "lex failed");
|
||||
ret 1;
|
||||
},
|
||||
}
|
||||
defer { Vec.drop(&tokens); }
|
||||
|
||||
var ast: Ast = undefined;
|
||||
match Ast.new(&sources) {
|
||||
.Ok(v) => { ast = v; },
|
||||
.Err(error) => {
|
||||
Logger.error(log, "ast init failed");
|
||||
ret 1;
|
||||
},
|
||||
}
|
||||
defer { Ast.drop(&ast); }
|
||||
|
||||
var p = Parser.new(&ast, tokens, &diag);
|
||||
Parser.parse(&p);
|
||||
|
||||
if Diag.has_error(diag) || p.failed {
|
||||
var rendered = ByteBuffer.new();
|
||||
defer { ByteBuffer.drop(&rendered); }
|
||||
match Diag.render_human(&diag, &rendered) {
|
||||
.Ok => {},
|
||||
.Err(error) => {},
|
||||
}
|
||||
eprint(ByteBuffer.as_slice(rendered));
|
||||
ret 1;
|
||||
}
|
||||
|
||||
var out = ByteBuffer.new();
|
||||
defer { ByteBuffer.drop(&out); }
|
||||
if !Ast.dump(&ast, &out) {
|
||||
Logger.fatal(log, "out of memory while dumping ast");
|
||||
ret 1;
|
||||
}
|
||||
match print(ByteBuffer.as_slice(out)) {
|
||||
.Ok => {},
|
||||
.Err(error) => { ret 1; },
|
||||
}
|
||||
ret 0;
|
||||
}
|
||||
|
||||
fn main(argc: i32, argv: **u8): i32 {
|
||||
// 无参数:自测运行(`nob test stage2`)视为成功。
|
||||
if argc <= 1 { ret 0; }
|
||||
@@ -143,7 +216,7 @@ fn main(argc: i32, argv: **u8): i32 {
|
||||
var log = Logger.new(ByteView.from_slice("splc1"));
|
||||
|
||||
if argc < 4 {
|
||||
Logger.fatal(&log, "usage: splc1 --dump <lex> <file> [out]");
|
||||
Logger.fatal(&log, "usage: splc1 --dump <lex|ast> <file> [out]");
|
||||
ret 1;
|
||||
}
|
||||
|
||||
@@ -152,12 +225,15 @@ fn main(argc: i32, argv: **u8): i32 {
|
||||
var path = ByteView.from_cstr(argv[3]);
|
||||
|
||||
if !ByteView.eq(arg1, ByteView.from_slice("--dump")) {
|
||||
Logger.fatal(&log, "usage: splc1 --dump <lex> <file> [out]");
|
||||
Logger.fatal(&log, "usage: splc1 --dump <lex|ast> <file> [out]");
|
||||
ret 1;
|
||||
}
|
||||
if !ByteView.eq(mode, ByteView.from_slice("lex")) {
|
||||
Logger.fatal(&log, "dump mode not implemented");
|
||||
ret 1;
|
||||
if ByteView.eq(mode, ByteView.from_slice("lex")) {
|
||||
ret dump_lex(&log, path);
|
||||
}
|
||||
ret dump_lex(&log, path);
|
||||
if ByteView.eq(mode, ByteView.from_slice("ast")) {
|
||||
ret dump_ast(&log, path);
|
||||
}
|
||||
Logger.fatal(&log, "dump mode not implemented");
|
||||
ret 1;
|
||||
}
|
||||
Reference in new issue
Block a user