diff --git a/README.md b/README.md index f358d1e..f039167 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # acc -A (WIP) zero-dependence (sub) C compiler written in pure ISO C11, minimal but aims to implement all 4 passes(lex, parse, build ir, code generation) and a set of machine-independent optimizations. +A (WIP) zero-dependence (sub) C compiler written in pure ISO C, minimal but aims to implement all 4 passes(lex, parse, build ir, code generation) and a set of machine-independent optimizations. diff --git a/include/fatals.h b/include/fatals.h index 1ed2542..3730927 100644 --- a/include/fatals.h +++ b/include/fatals.h @@ -8,8 +8,8 @@ void* malloc_or_fail(size_t s, const char *func_name); noreturn void fail_target(const char *target_name); noreturn void fail_malloc(const char *func_name); noreturn void fail_ast_op(int op, const char *func_name); -noreturn void fail_ce_expect(const char *expected, const char *got); -noreturn void fail_ce(const char *reason); -noreturn void fail_char(int c); +noreturn void fail_ce_expect(int line, const char *expected, const char *got); +noreturn void fail_ce(int line, const char *reason); +noreturn void fail_char(int line, int c); #endif diff --git a/include/scan.h b/include/scan.h index 99fe6f3..4d01cb6 100644 --- a/include/scan.h +++ b/include/scan.h @@ -3,7 +3,6 @@ #include "util/linklist.h" -extern int Line; struct linklist scan_tokens(const char *name); #endif diff --git a/include/token.h b/include/token.h index 14069c5..5cf6bab 100644 --- a/include/token.h +++ b/include/token.h @@ -7,6 +7,7 @@ // Token structure struct token { struct llist_node n; + int line; // token location line number int type; // token type union { // hold the value of the literal that we scanned in int16_t val_i16; diff --git a/main.c b/main.c index 3b8aa61..19d4998 100644 --- a/main.c +++ b/main.c @@ -19,7 +19,7 @@ void unload(void) { } int main(int argc, char *argv[]) { -// atexit(unload); + atexit(unload); if (argc < 3) { usage(argv[0]); } diff --git a/src/ast.c b/src/ast.c index df4e09d..97eacde 100644 --- a/src/ast.c +++ b/src/ast.c @@ -101,7 +101,7 @@ void ast_free(struct ASTnode *x) { switch (x->op) { case A_IF: { ast_free(((struct ASTifnode*)x)->cond); - } // dont break + } [[fallthrough]]; case A_ASSIGN: case A_ADD: case A_SUB: case A_MUL: case A_DIV: @@ -111,7 +111,7 @@ void ast_free(struct ASTnode *x) { ast_free(t->left); ast_free(t->right); } break; - + case A_PRINT: case A_RETURN: { struct ASTunnode *t = (struct ASTunnode*)x; ast_free(t->left); @@ -122,7 +122,7 @@ void ast_free(struct ASTnode *x) { struct llist_node *p = t->st.head, *nxt; while (p) { nxt = p->nxt; - ast_free(p); + ast_free((struct ASTnode*)p); p = nxt; } llist_free(&t->st); diff --git a/src/fatals.c b/src/fatals.c index 8458ada..d479f4a 100644 --- a/src/fatals.c +++ b/src/fatals.c @@ -25,18 +25,18 @@ void fail_ast_op(int op, const char *func_name) { exit(1); } -void fail_ce_expect(const char *expected, const char *got) { - fprintf(stderr, "syntax error on line %d: expected %s, got %s.\n", Line, expected, got); +void fail_ce_expect(int line, const char *expected, const char *got) { + fprintf(stderr, "syntax error on line %d: expected %s, got %s.\n", line, expected, got); exit(1); } -void fail_ce(const char *reason) { - fprintf(stderr, "syntax error on line %d: %s.\n", Line, reason); +void fail_ce(int line, const char *reason) { + fprintf(stderr, "syntax error on line %d: %s.\n", line, reason); exit(1); } -void fail_char(int c) { - fprintf(stderr, "Unrecognised character %c on line %d.\n", c, Line); +void fail_char(int line, int c) { + fprintf(stderr, "Unrecognised character %c on line %d.\n", c, line); exit(1); } diff --git a/src/parse.c b/src/parse.c index 5aed65e..f90862a 100644 --- a/src/parse.c +++ b/src/parse.c @@ -11,8 +11,8 @@ static struct linklist Tokens; // current token for parsing // Check that we have a binary operator and return its precedence. // operators with larger precedence value will be evaluated first -static int op_precedence(int t) { - switch (t) { +static int op_precedence(struct token *t) { + switch (t->type) { case T_ASSIGN: return (20); case T_GT: case T_GE: case T_LT: case T_LE: @@ -24,12 +24,12 @@ static int op_precedence(int t) { case T_STAR: case T_SLASH: return (90); default: - fail_ce_expect("an operator", token_typename[t]); + fail_ce_expect(t->line, "an operator", token_typename[t->type]); } } // Convert a arithmetic token into an AST operation. -static int arithop(int t) { +static int arithop(struct token *t) { static const int map[][2] = { {T_PLUS, A_ADD}, {T_MINUS, A_SUB}, @@ -46,11 +46,11 @@ static int arithop(int t) { }; for (int i = 0; map[i][0] != -1; ++i) { - if (t == map[i][0]) { + if (t->type == map[i][0]) { return map[i][1]; } } - fail_ce_expect("an binary operator", token_typename[t]); + fail_ce_expect(t->line, "an binary operator", token_typename[t->type]); } // operator ssociativity direction @@ -95,14 +95,14 @@ static void match(int t) { if (current()->type == t) { next(); } else { - fail_ce_expect(token_typename[current()->type], token_typename[t]); + fail_ce_expect(current()->line, token_typename[t], token_typename[current()->type]); } } // check current token's type or report syntax error. static void expect(int t) { if (current()->type != t) { - fail_ce_expect(token_typename[current()->type], token_typename[t]); + fail_ce_expect(current()->line, token_typename[t], token_typename[current()->type]); } } @@ -113,20 +113,21 @@ static struct ASTnode* expression(void); // AST node representing it. static struct ASTnode* primary(void) { struct ASTnode *res; - - if (current()->type == T_LP) { + struct token *t = current(); + if (t->type == T_LP) { // ( expr ) considered as primary next(); res = expression(); match(T_RP); - } else if (current()->type == T_I32_LIT) { - res = ast_make_lit_i32(current()->val_i32); + } else if (t->type == T_I32_LIT) { + res = ast_make_lit_i32(t->val_i32); next(); - } else if (current()->type == T_I64_LIT) { + } else if (t->type == T_I64_LIT) { res = ast_make_lit_i64(current()->val_i64); next(); - } else if (current()->type == T_ID) { + } else if (t->type == T_ID) { // TODO: identifier. + fail_ce(t->line, "got an identifier"); /* int id = findglob((char*)current()->val); if (id == -1) { @@ -136,11 +137,8 @@ static struct ASTnode* primary(void) { next(); return (ast_make_var(id)); */ - res = NULL; - next(); } else { - fprintf(stderr, "syntax error on line %d: primary expression excpeted.\n", Line); - exit(1); + fail_ce(t->line, "primary expression expected"); } return (res); } @@ -155,28 +153,28 @@ static struct ASTnode* binexpr(int precedence) { struct ASTnode *left, *right; left = primary(); - int tt = current()->type; - if (!is_binop(tt)) { + struct token *op = current(); + if (!is_binop(op->type)) { return (left); } - int tp = op_precedence(tt); + int tp = op_precedence(op); while (tp > precedence) { next(); - if (direction_rtl(tt)) { + if (direction_rtl(op->type)) { right = binexpr(precedence); - left = ast_make_assign(arithop(tt), ((struct ASTvarnode*)left)->id, right); + left = ast_make_assign(arithop(op), left, right); } else { right = binexpr(tp); - left = ast_make_binary(arithop(tt), left, right); // join right into left + left = ast_make_binary(arithop(op), left, right); // join right into left } - tt = current()->type; - if (!is_binop(tt)) { + op = current(); + if (!is_binop(op->type)) { return (left); } - tp = op_precedence(tt); + tp = op_precedence(op); } return (left); } diff --git a/src/print_ast.c b/src/print_ast.c index ce30d96..0fb0552 100644 --- a/src/print_ast.c +++ b/src/print_ast.c @@ -23,7 +23,7 @@ static void ast_dfs(FILE* Outfile, struct ASTnode *x) { switch(x->op) { case A_RETURN: case A_PRINT: { - struct ASTunnode *t = x; + struct ASTunnode *t = (struct ASTunnode*)x; fprintf(Outfile, "--->UNOP(%s)\n", ast_opname[x->op]); tabs += 1; ast_dfs(Outfile, t->left); @@ -31,22 +31,22 @@ static void ast_dfs(FILE* Outfile, struct ASTnode *x) { } break; case A_LIT_I32: { - struct ASTi32node *t = x; + struct ASTi32node *t = (struct ASTi32node*)x; fprintf(Outfile, "--->INT32(%d)\n", t->val); } break; case A_LIT_I64: { - struct ASTi64node *t = x; + struct ASTi64node *t = (struct ASTi64node*)x; fprintf(Outfile, "--->INT64(%lld)\n", t->val); } break; case A_BLOCK: { - struct ASTblocknode *t = x; + struct ASTblocknode *t = (struct ASTblocknode*)x; fprintf(Outfile, "--->BLOCK(%d statements)\n", t->st.length); tabs += 1; struct llist_node *p = t->st.head; while (p) { - ast_dfs(Outfile, p); + ast_dfs(Outfile, (struct ASTnode*)p); p = p->nxt; } tabs -= 1; diff --git a/src/scan.c b/src/scan.c index 208755a..656fab4 100644 --- a/src/scan.c +++ b/src/scan.c @@ -8,7 +8,7 @@ #include "fatals.h" #include "util/misc.h" -int Line = 1; +static int Line = 1; static int Preview; static FILE *Infile; @@ -155,9 +155,11 @@ static bool scan_1c(struct token *t) { // Scan and return the next token found in the input. static struct token* scan(void) { - struct token *t = malloc_or_fail(sizeof(struct token), __FUNCTION__); - skip_whitespaces(); + + struct token *t = malloc_or_fail(sizeof(struct token), __FUNCTION__); + t->line = Line; + int c = preview(); if (c == EOF) { t->type = T_EOF; @@ -183,7 +185,8 @@ static struct token* scan(void) { t->type = T_NE; next(); } else { - fail_char(c); + // TODO: the not operator + fail_char(t->line, c); } } else if (c == '<') { t->type = T_LT; @@ -212,7 +215,7 @@ static struct token* scan(void) { t->type = T_ID; } } else { // cannot match to anything we know, report error. - fail_char(c); + fail_char(t->line, c); } } return (t); diff --git a/xmake.lua b/xmake.lua index cbce619..048aff1 100644 --- a/xmake.lua +++ b/xmake.lua @@ -4,6 +4,8 @@ set_basename("acc") set_languages("c11") set_targetdir(".") +set_policy("build.warning", true) + target("build") set_kind("binary") set_default(true)