aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/as_parser.c132
-rw-r--r--src/as_parser.h11
-rw-r--r--src/as_tokenizer.c28
-rw-r--r--src/utils.c8
-rw-r--r--src/utils.h8
5 files changed, 81 insertions, 106 deletions
diff --git a/src/as_parser.c b/src/as_parser.c
index 0fcb1f4..a68fbba 100644
--- a/src/as_parser.c
+++ b/src/as_parser.c
@@ -17,37 +17,28 @@
// <op> ::= "add" | "sub" | "mul" | "div" | "mod" | "eq" | ...
struct result parse_prog(struct allocator * alct, struct token_stream * ts) {
- struct result result;
struct prog * p = allocate(alct, sizeof(struct prog));
- result = parse_stmts(alct, ts);
- if (result.errmsg != NULL) return result;
- p->stmts = result.value;
- return (struct result){.value = p, .errmsg = NULL};
+ p->stmts = unwrap(parse_stmts(alct, ts));
+ return ok(p);
}
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));
+ struct stmt * s;
+
ss->stmts = allocate(alct, sizeof(struct stmt *));
ss->stmts[0] = NULL;
int capacity = 0;
int len = 0;
while (1) {
- result = peek_token(alct, ts);
- if (result.errmsg != NULL) return result;
- token = result.value;
+ token = unwrap(peek_token(alct, ts));
if (token->type == TK_ENDOFFILE) {
break;
}
-
- result = parse_stmt(alct, ts);
- if (result.errmsg != NULL) {
- return result;
- }
- struct stmt * s = result.value;
+
+ s = unwrap(parse_stmt(alct, ts));
if (s == NULL) continue;
if (len == capacity) {
size_t new_capacity = capacity * 2 + 1;
@@ -57,136 +48,97 @@ struct result parse_stmts(struct allocator * alct, struct token_stream * ts) {
capacity = new_capacity;
}
// expect newline
- result = peek_token(alct, ts);
- if (result.errmsg != NULL) return result;
- token = result.value;
+ token = unwrap(peek_token(alct, ts));
if (token->type == TK_NEWLINE) {
- result = next_token(alct, ts);
- if (result.errmsg != NULL) return result;
+ unwrap(next_token(alct, ts));
} else {
- errmsg = safe_sprintf(alct, "%d:%d expect newline.\n", token->line, token->col);
- return (struct result){.value = NULL, .errmsg = errmsg};
+ return err(safe_sprintf(alct, "%d:%d expect newline.\n", token->line, token->col));
}
ss->stmts[len] = s;
len++;
}
ss->stmts[len] = NULL;
- return (struct result){.value = ss, .errmsg = NULL};
+ return ok(ss);
}
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;
+ t = unwrap(next_token(alct, ts));
if (t->type != TK_TAG) {
- errmsg = safe_sprintf(alct, "%d:%d expect label.\n", t->line, t->col);
- return (struct result){.value = NULL, .errmsg = errmsg};
+ return err(safe_sprintf(alct, "%d:%d expect label.\n", t->line, t->col));
}
struct label * l = allocate(alct, sizeof(struct label *));
l->name = t->sval;
- result = next_token(alct, ts);
- if (result.errmsg != NULL) return result;
- t = result.value;
+ t = unwrap(next_token(alct, ts));
if (t->type != TK_COLON) {
- errmsg = safe_sprintf(alct, "%d:%d expect colon.\n", t->line, t->col);
- return (struct result){.value = NULL, .errmsg = errmsg};
+ return err(safe_sprintf(alct, "%d:%d expect colon.\n", t->line, t->col));
}
- return (struct result){.value = l, .errmsg = NULL};
+ return ok(l);
}
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 token * token;
+ token = unwrap(peek_token(alct, ts));
struct stmt * stmt = allocate(alct, sizeof(struct stmt));
stmt->label = NULL;
stmt->instr = NULL;
- if (t->type == TK_TAG) {
- 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};
+ if (token->type == TK_TAG) {
+ stmt->label = unwrap(parse_label(alct, ts));
+ token = unwrap(peek_token(alct, ts));
+ if (token->type == TK_NEWLINE) {
+ return ok(stmt);
}
- result = peek_token(alct, ts);
- if (result.errmsg != NULL) return result;
- t = result.value;
+ token = unwrap(peek_token(alct, ts));
}
- if (t->type == TK_OP) {
- 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 (token->type == TK_OP) {
+ stmt->instr = unwrap(parse_instr(alct, ts));
+ token = unwrap(peek_token(alct, ts));
+ if (token->type == TK_NEWLINE) {
+ return ok(stmt);
}
}
- if (t->type == TK_NEWLINE) {
- return (struct result){.value = NULL, .errmsg = NULL};
+ if (token->type == TK_NEWLINE) {
+ return ok(NULL);
}
- errmsg = safe_sprintf(alct, "%d:%d expect lable + instruction, lable, or instruction.\n", t->line, t->col);
- return (struct result){.value = NULL, .errmsg = errmsg};
+ return err(safe_sprintf(alct, "%d:%d expect lable + instruction, lable, or instruction.\n", token->line, token->col));
}
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;
+ t = unwrap(next_token(alct, ts));
enum op op;
if (t->type == TK_OP) {
op = str2op(t->sval);
if (op == OP_END) {
- errmsg = safe_sprintf(alct, "%d:%d invalid op.\n", t->line, t->col);
- return (struct result){.value = NULL, .errmsg = errmsg};
+ return err(safe_sprintf(alct, "%d:%d invalid op.\n", t->line, t->col));
}
} else {
- errmsg = safe_sprintf(alct, "%d:%d expect op.\n", t->line, t->col);
- return (struct result){.value = NULL, .errmsg = errmsg};
+ return err(safe_sprintf(alct, "%d:%d expect op.\n", t->line, t->col));
}
- return (struct result){.value = (void*)op, .errmsg = NULL};
+ return ok((void*)op);
}
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;
+ t = unwrap(peek_token(alct, ts));
struct instr * i = allocate(alct, sizeof(struct instr));
i->tag_name = NULL;
i->arg = NULL;
i->op = OP_END;
if (t->type == TK_OP) {
- 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;
+ i->op = (enum op)unwrap(parse_op(alct, ts));
+ t = unwrap(peek_token(alct, ts));
if (t->type == TK_ARG) {
struct arg * a = allocate(alct, sizeof(struct arg));
a->ival = t->ival;
a->fval = t->fval;
i->arg = a;
- next_token(alct, ts);
+ unwrap(next_token(alct, ts));
} else if (t->type == TK_TAG) {
i->tag_name = t->sval;
- next_token(alct, ts);
+ unwrap(next_token(alct, ts));
}
}
- return (struct result){.value = i, .errmsg = NULL};
+ return ok(i);
}
diff --git a/src/as_parser.h b/src/as_parser.h
index 5d850c9..2171fe4 100644
--- a/src/as_parser.h
+++ b/src/as_parser.h
@@ -34,11 +34,22 @@ struct prog {
struct stmts * stmts;
};
+// result<prog>
struct result parse_prog(struct allocator * alct, struct token_stream * ts);
+
+// result<stmt>
struct result parse_stmt(struct allocator * alct, struct token_stream * ts);
+
+// result<stmts>
struct result parse_stmts(struct allocator * alct, struct token_stream * ts);
+
+// result<instr>
struct result parse_instr(struct allocator * alct, struct token_stream * ts);
+
+// result<label>
struct result parse_label(struct allocator * alct, struct token_stream * ts);
+
+// result<enum op>
struct result parse_op(struct allocator * alct, struct token_stream * ts);
#endif
diff --git a/src/as_tokenizer.c b/src/as_tokenizer.c
index f2c3ccb..7a71707 100644
--- a/src/as_tokenizer.c
+++ b/src/as_tokenizer.c
@@ -83,12 +83,12 @@ struct result next_token_impl(struct allocator * alct, struct input_stream * s)
if (c == '\n') {
input_stream_next_char(s);
*t = (struct token){.type = TK_NEWLINE, .line = s->line, .col = s->col};
- return (struct result){.value = t, .errmsg = NULL};
+ return ok(t);
}
if (c == ':') {
input_stream_next_char(s);
*t = (struct token){.type = TK_COLON, .line = s->line, .col = s->col};
- return (struct result){.value = t, .errmsg = NULL};
+ return ok(t);
}
if (c == ' ' || c == '\t') {
input_stream_next_char(s);
@@ -105,7 +105,7 @@ struct result next_token_impl(struct allocator * alct, struct input_stream * s)
}
}
*t = (struct token){.type = TK_ARG, .ival = ival, .line = s->line, .col = s->col};
- return (struct result){.value = t, .errmsg = NULL};
+ return ok(t);
}
if (is_start_of_identifier(c)) {
size_t line = s->line;
@@ -114,8 +114,7 @@ struct result next_token_impl(struct allocator * alct, struct input_stream * s)
size_t i = 0;
while (1) {
if (i >= 255) {
- errmsg = safe_sprintf(alct, "error: identifier too long\n");
- return (struct result){.value = NULL, .errmsg = errmsg};
+ return err(safe_sprintf(alct, "error: identifier too long\n"));
}
input_stream_next_char(s);
sval[i++] = c;
@@ -127,36 +126,33 @@ struct result next_token_impl(struct allocator * alct, struct input_stream * s)
sval[i] = '\0';
if (isOp(sval)) {
*t = (struct token){.type = TK_OP, .sval = sval, .line = line, .col = col};
- return (struct result){.value = t, .errmsg = NULL};
+ return ok(t);
}
*t = (struct token){.type = TK_TAG, .sval = sval, .line = line, .col = col};
- return (struct result){.value = t, .errmsg = NULL};
+ return ok(t);
}
- errmsg = safe_sprintf(alct, "error: invalid character %c at line %d, col %d\n", c, s->line, s->col);
- return (struct result){.value = NULL, .errmsg = errmsg};
+ return err(safe_sprintf(alct, "error: invalid character %c at line %d, col %d\n", c, s->line, s->col));
}
// end of file
*t = (struct token){.type = TK_ENDOFFILE};
- return (struct result){.value = t, .errmsg = NULL};
+ return ok(t);
}
struct result next_token(struct allocator * alct, struct token_stream * ts) {
if (ts->buf != NULL) {
struct token * t = ts->buf;
ts->buf = NULL;
- return (struct result){.value = t, .errmsg = NULL};
+ return ok(t);
}
return next_token_impl(alct, ts->s);
}
struct result peek_token(struct allocator * alct, struct token_stream * ts) {
if (ts->buf != NULL) {
- return (struct result){.value = ts->buf, .errmsg = NULL};
+ return ok(ts->buf);
}
- struct result result = next_token_impl(alct, ts->s);
- if (result.errmsg != NULL) return result;
- ts->buf = result.value;
- return result;
+ ts->buf = unwrap(next_token_impl(alct, ts->s));
+ return ok(ts->buf);
}
void print_token(struct token * t) {
diff --git a/src/utils.c b/src/utils.c
index 2a0e286..b79c87c 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -4,6 +4,14 @@
#include <assert.h>
#include <stdarg.h>
+struct result ok(void *value) {
+ return (struct result){.value = value, .errmsg = NULL};
+}
+
+struct result err(const char *errmsg) {
+ return (struct result){.value = NULL, .errmsg = errmsg};
+}
+
struct allocator {
void** bufs;
size_t cap;
diff --git a/src/utils.h b/src/utils.h
index 5f7c0ff..8bc76f8 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -10,6 +10,14 @@ struct result {
const char* errmsg;
};
+#define unwrap(x__) ({ \
+ struct result res__ = (x__); \
+ if (res__.errmsg != NULL) return res__; \
+ res__.value;})
+
+struct result ok(void *value);
+struct result err(const char *errmsg);
+
struct allocator * new_allocator();
void delete_allocator(struct allocator * allocator);