aboutsummaryrefslogtreecommitdiff
path: root/src/as_parser.c
diff options
context:
space:
mode:
authorMistivia <i@mistivia.com>2025-03-25 13:07:21 +0800
committerMistivia <i@mistivia.com>2025-03-25 13:07:21 +0800
commitfb7664e087cb1afb64aae2128365f703beb30b57 (patch)
tree6d4e2a4cc695052e489ec9e3fd28538a79a08f4c /src/as_parser.c
parentdc87ff4b0c9f311be7fad652594e3766a4ddb0c6 (diff)
add result style error handling
Diffstat (limited to 'src/as_parser.c')
-rw-r--r--src/as_parser.c144
1 files changed, 102 insertions, 42 deletions
diff --git a/src/as_parser.c b/src/as_parser.c
index 39f8859..0fcb1f4 100644
--- a/src/as_parser.c
+++ b/src/as_parser.c
@@ -16,20 +16,38 @@
// <label> ::= tag ":"
// <op> ::= "add" | "sub" | "mul" | "div" | "mod" | "eq" | ...
-struct prog * parse_prog(struct allocator * alct, struct token_stream * ts) {
+struct result parse_prog(struct allocator * alct, struct token_stream * ts) {
+ struct result result;
struct prog * p = allocate(alct, sizeof(struct prog));
- p->stmts = parse_stmts(alct, ts);
- return p;
+ result = parse_stmts(alct, ts);
+ if (result.errmsg != NULL) return result;
+ p->stmts = result.value;
+ return (struct result){.value = p, .errmsg = NULL};
}
-struct stmts * parse_stmts(struct allocator * alct, struct token_stream * ts) {
+struct result parse_stmts(struct allocator * alct, struct token_stream * ts) {
+ struct token *token;
+ struct result result;
+ const char* errmsg;
struct stmts * ss = allocate(alct, sizeof(struct stmts));
ss->stmts = allocate(alct, sizeof(struct stmt *));
ss->stmts[0] = NULL;
int capacity = 0;
int len = 0;
- while (peek_token(alct, ts)->type != TK_ENDOFFILE) {
- struct stmt * s = parse_stmt(alct, ts);
+
+ while (1) {
+ result = peek_token(alct, ts);
+ if (result.errmsg != NULL) return result;
+ token = result.value;
+ if (token->type == TK_ENDOFFILE) {
+ break;
+ }
+
+ result = parse_stmt(alct, ts);
+ if (result.errmsg != NULL) {
+ return result;
+ }
+ struct stmt * s = result.value;
if (s == NULL) continue;
if (len == capacity) {
size_t new_capacity = capacity * 2 + 1;
@@ -39,84 +57,126 @@ struct stmts * parse_stmts(struct allocator * alct, struct token_stream * ts) {
capacity = new_capacity;
}
// expect newline
- if (peek_token(alct, ts)->type == TK_NEWLINE) {
- next_token(alct, ts);
+ result = peek_token(alct, ts);
+ if (result.errmsg != NULL) return result;
+ token = result.value;
+ if (token->type == TK_NEWLINE) {
+ result = next_token(alct, ts);
+ if (result.errmsg != NULL) return result;
} else {
- fprintf(stderr, "%d:%d expect newline.\n", peek_token(alct, ts)->line, peek_token(alct, ts)->col);
+ errmsg = safe_sprintf(alct, "%d:%d expect newline.\n", token->line, token->col);
+ return (struct result){.value = NULL, .errmsg = errmsg};
}
ss->stmts[len] = s;
len++;
}
ss->stmts[len] = NULL;
- return ss;
+ return (struct result){.value = ss, .errmsg = NULL};
}
-struct label * parse_label(struct allocator * alct, struct token_stream * ts) {
- struct token * t = next_token(alct, ts);
+struct result parse_label(struct allocator * alct, struct token_stream * ts) {
+ const char *errmsg;
+ struct result result;
+ struct token * t;
+ result = next_token(alct, ts);
+ if (result.errmsg != NULL) return result;
+ t = result.value;
if (t->type != TK_TAG) {
- fprintf(stderr, "%d:%d expect label.\n", t->line, t->col);
- exit(-1);
+ errmsg = safe_sprintf(alct, "%d:%d expect label.\n", t->line, t->col);
+ return (struct result){.value = NULL, .errmsg = errmsg};
}
struct label * l = allocate(alct, sizeof(struct label *));
l->name = t->sval;
- t = next_token(alct, ts);
+ result = next_token(alct, ts);
+ if (result.errmsg != NULL) return result;
+ t = result.value;
if (t->type != TK_COLON) {
- fprintf(stderr, "%d:%d expect colon.\n", t->line, t->col);
- exit(-1);
+ errmsg = safe_sprintf(alct, "%d:%d expect colon.\n", t->line, t->col);
+ return (struct result){.value = NULL, .errmsg = errmsg};
}
- return l;
+ return (struct result){.value = l, .errmsg = NULL};
}
-struct stmt * parse_stmt(struct allocator * alct, struct token_stream * ts) {
- struct token * t = peek_token(alct, ts);
+struct result parse_stmt(struct allocator * alct, struct token_stream * ts) {
+ const char *errmsg;
+ struct result result;
+ struct token * t;
+ result = peek_token(alct, ts);
+ if (result.errmsg != NULL) return result;
+ t = result.value;
struct stmt * stmt = allocate(alct, sizeof(struct stmt));
stmt->label = NULL;
stmt->instr = NULL;
if (t->type == TK_TAG) {
- stmt->label = parse_label(alct, ts);
- if (peek_token(alct, ts)->type == TK_NEWLINE) {
- return stmt;
+ result = parse_label(alct, ts);
+ if (result.errmsg != NULL) return result;
+ stmt->label = result.value;
+ result = peek_token(alct, ts);
+ if (result.errmsg != NULL) return result;
+ t = result.value;
+ if (t->type == TK_NEWLINE) {
+ return (struct result){.value = stmt, .errmsg = NULL};
}
- t = peek_token(alct, ts);
+ result = peek_token(alct, ts);
+ if (result.errmsg != NULL) return result;
+ t = result.value;
}
if (t->type == TK_OP) {
- stmt->instr = parse_instr(alct, ts);
- if (peek_token(alct, ts)->type == TK_NEWLINE) {
- return stmt;
+ result = parse_instr(alct, ts);
+ if (result.errmsg != NULL) return result;
+ stmt->instr = result.value;
+
+ result = peek_token(alct, ts);
+ if (result.errmsg != NULL) return result;
+ t = result.value;
+ if (t->type == TK_NEWLINE) {
+ return (struct result){.value = stmt, .errmsg = NULL};
}
}
if (t->type == TK_NEWLINE) {
- return NULL;
+ return (struct result){.value = NULL, .errmsg = NULL};
}
- fprintf(stderr, "%d:%d expect lable + instruction, lable, or instruction.\n", t->line, t->col);
- exit(-1);
+ errmsg = safe_sprintf(alct, "%d:%d expect lable + instruction, lable, or instruction.\n", t->line, t->col);
+ return (struct result){.value = NULL, .errmsg = errmsg};
}
-enum op parse_op(struct allocator * alct, struct token_stream * ts) {
- struct token * t = next_token(alct, ts);
+struct result parse_op(struct allocator * alct, struct token_stream * ts) {
+ const char *errmsg;
+ struct result result;
+ struct token * t;
+ result = next_token(alct, ts);
+ if (result.errmsg != NULL) return result;
+ t = result.value;
enum op op;
if (t->type == TK_OP) {
op = str2op(t->sval);
if (op == OP_END) {
- fprintf(stderr, "%d:%d invalid op.\n", t->line, t->col);
- exit(-1);
+ errmsg = safe_sprintf(alct, "%d:%d invalid op.\n", t->line, t->col);
+ return (struct result){.value = NULL, .errmsg = errmsg};
}
} else {
- fprintf(stderr, "%d:%d expect op.\n", t->line, t->col);
- exit(-1);
+ errmsg = safe_sprintf(alct, "%d:%d expect op.\n", t->line, t->col);
+ return (struct result){.value = NULL, .errmsg = errmsg};
}
- return op;
+ return (struct result){.value = (void*)op, .errmsg = NULL};
}
-struct instr * parse_instr(struct allocator * alct, struct token_stream * ts) {
- struct token * t = peek_token(alct, ts);
+struct result parse_instr(struct allocator * alct, struct token_stream * ts) {
+ struct result result;
+ struct token * t;
+ result = peek_token(alct, ts);
+ if (result.errmsg != NULL) return result;
+ t = result.value;
struct instr * i = allocate(alct, sizeof(struct instr));
i->tag_name = NULL;
i->arg = NULL;
i->op = OP_END;
if (t->type == TK_OP) {
- i->op = parse_op(alct, ts);
- t = peek_token(alct, ts);
+ result = parse_op(alct, ts);
+ i->op = (enum op)(result.value);
+ result = peek_token(alct, ts);
+ if (result.errmsg != NULL) return result;
+ t = result.value;
if (t->type == TK_ARG) {
struct arg * a = allocate(alct, sizeof(struct arg));
a->ival = t->ival;
@@ -128,5 +188,5 @@ struct instr * parse_instr(struct allocator * alct, struct token_stream * ts) {
next_token(alct, ts);
}
}
- return i;
+ return (struct result){.value = i, .errmsg = NULL};
}