diff options
Diffstat (limited to 'src/as_parser.c')
| -rw-r--r-- | src/as_parser.c | 144 |
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}; } |
