diff options
| author | Mistivia <i@mistivia.com> | 2025-03-18 21:32:58 +0800 |
|---|---|---|
| committer | Mistivia <i@mistivia.com> | 2025-03-18 21:32:58 +0800 |
| commit | afb5ae7905c666eb259288ba0d3b47f71a13958f (patch) | |
| tree | 9d754a68179a4b7736f3d02f9a5dd5a910c65841 | |
| parent | c684a4a302e95d860210a9ddaa891adf9775eadc (diff) | |
add parser unit test
| -rw-r--r-- | Makefile | 8 | ||||
| -rw-r--r-- | src/as_parser.c | 15 | ||||
| -rw-r--r-- | src/utils.c | 5 | ||||
| -rw-r--r-- | tests/test_as_parser.c | 40 |
4 files changed, 61 insertions, 7 deletions
@@ -1,6 +1,6 @@ target = fvm -cflags = -g -O3 -ldflags = -lm +cflags = -g -fsanitize=address -fno-omit-frame-pointer +ldflags = -lm -fsanitize=address -fno-omit-frame-pointer cc = gcc csc = chicken-csc @@ -19,7 +19,9 @@ full: all $(tests_bin) $(target): $(obj) src/main.o $(cc) $(cflags) $(ldflags) -o $@ $^ -test: $(tests_bin) +buildtest: $(tests_bin) + +test: buildtest @echo @echo "Run tests:" @scripts/runall.sh $^ diff --git a/src/as_parser.c b/src/as_parser.c index f848730..990bc1c 100644 --- a/src/as_parser.c +++ b/src/as_parser.c @@ -4,6 +4,7 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> // BNF // === @@ -32,8 +33,11 @@ Stmts parseStmts(Allocator alct, TokenStream ts) { Stmt s = parseStmt(alct, ts); if (s == NULL) continue; if (len == capacity) { - capacity = capacity * 2 + 1; - ss->stmts = realloc(ss->stmts, sizeof(Stmt*) * capacity); + size_t newCapacity = capacity * 2 + 1; + void* newStmts = allocate(alct, sizeof(Stmt*) * newCapacity); + memcpy(newStmts, ss->stmts, sizeof(Stmt*) * capacity); + ss->stmts = newStmts; + capacity = newCapacity; } // expect newline if (peekToken(alct, ts)->type == NEWLINE) { @@ -74,6 +78,7 @@ Stmt parseStmt(Allocator alct, TokenStream ts) { if (peekToken(alct, ts)->type == NEWLINE) { return stmt; } + t = peekToken(alct, ts); } if (t->type == OP) { stmt->instr = parseInstr(alct, ts); @@ -84,7 +89,7 @@ Stmt parseStmt(Allocator alct, TokenStream ts) { if (t->type == NEWLINE) { return NULL; } - fprintf(stderr, "%d:%d Expect lable + instruction, lable, or instruction.", t->line, t->col); + fprintf(stderr, "%d:%d Expect lable + instruction, lable, or instruction.\n", t->line, t->col); exit(-1); } @@ -105,9 +110,11 @@ enum op parseOp(Allocator alct, TokenStream ts) { } Instr parseInstr(Allocator alct, TokenStream ts) { - Token t = nextToken(alct, ts); + Token t = peekToken(alct, ts); Instr i = allocate(alct, sizeof(struct instr)); i->tagName = NULL; + i->arg = NULL; + i->op = OPEND; if (t->type == OP) { i->op = parseOp(alct, ts); t = peekToken(alct, ts); diff --git a/src/utils.c b/src/utils.c index 354159b..1baf283 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,5 +1,8 @@ #include "utils.h" +#include <stdio.h> +#include <assert.h> + struct allocator { void** bufs; size_t cap; @@ -19,10 +22,12 @@ void deleteAllocator(Allocator alct) { for (size_t i = 0; i < alct->len; i++) { free(alct->bufs[i]); } + free(alct->bufs); free(alct); } void * allocate(Allocator alct, size_t size) { + assert(size > 0); if (alct->len >= alct->cap) { alct->cap = alct->cap * 2; // Doubling the capacity alct->bufs = realloc(alct->bufs, sizeof(void*) * alct->cap); diff --git a/tests/test_as_parser.c b/tests/test_as_parser.c new file mode 100644 index 0000000..e11a353 --- /dev/null +++ b/tests/test_as_parser.c @@ -0,0 +1,40 @@ +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include "as_tokenizer.h" +#include "as_parser.h" +#include "utils.h" + +char *inputBuffer = + "start:\n" + " add 1\n" + " sub start\n" + " div\n" + "end: eq\n"; + +int main(int argc, char** argv) { + printf("[TEST] assembler parser\n"); + // make a memory buffer to FILE* + FILE *fp = fmemopen(inputBuffer, strlen(inputBuffer), "r"); + Allocator alct = newAllocator(); + TokenStream ts = makeTokenStream(alct, fp); + Prog prog = parseProg(alct, ts); + + // compare output + Stmt* stmts = prog->stmts->stmts; + + assert(stmts[0]->instr == NULL); + assert(strcmp("start", stmts[0]->label->name) == 0); + + assert(stmts[1]->label == NULL); + assert(stmts[1]->instr->op == ADD); + assert(stmts[1]->instr->arg->ival == 1); + + assert(strcmp("end", stmts[4]->label->name) == 0); + assert(stmts[4]->instr->op == EQ); + + printf("[PASS] assembler parser\n"); + deleteAllocator(alct); + return 0; +} |
