aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMistivia <i@mistivia.com>2025-03-18 21:32:58 +0800
committerMistivia <i@mistivia.com>2025-03-18 21:32:58 +0800
commitafb5ae7905c666eb259288ba0d3b47f71a13958f (patch)
tree9d754a68179a4b7736f3d02f9a5dd5a910c65841
parentc684a4a302e95d860210a9ddaa891adf9775eadc (diff)
add parser unit test
-rw-r--r--Makefile8
-rw-r--r--src/as_parser.c15
-rw-r--r--src/utils.c5
-rw-r--r--tests/test_as_parser.c40
4 files changed, 61 insertions, 7 deletions
diff --git a/Makefile b/Makefile
index bdf1afb..46d01fd 100644
--- a/Makefile
+++ b/Makefile
@@ -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;
+}