commit 3b8dd3de1d3ca7a1cf2a25a1a457e5a940e44b93
parent 426dea56758255ad86a69a6b931b3332c8d2405c
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Tue, 7 Dec 2021 16:24:47 -0600
report location of errors and add test
Diffstat:
6 files changed, 103 insertions(+), 61 deletions(-)
diff --git a/main.c b/main.c
@@ -21,13 +21,20 @@ struct decls decls;
struct assgns assgns;
struct exprs exprs;
+char *infile;
+
#define ADVANCE(n) \
+ cur->line = line ; \
+ cur->col = line ; \
start.data += (n) ; \
- start.len -= (n) ;
+ start.len -= (n) ; \
+ col += (n) ;
struct token *
lex(struct slice start)
{
+ size_t line = 1;
+ size_t col = 1;
struct token *head = calloc(1, sizeof(struct token));
if (!head)
return NULL;
@@ -88,6 +95,8 @@ lex(struct slice start)
ADVANCE(1);
} else if (*start.data == '\n') {
ADVANCE(1);
+ line += 1;
+ col = 1;
continue;
} else if (*start.data == '+') {
cur->type = TOK_PLUS;
@@ -108,7 +117,7 @@ lex(struct slice start)
cur->slice.len++;
}
} else {
- error("invalid token");
+ error("invalid token", line, col);
}
cur->next = calloc(1, sizeof(struct token));
@@ -120,6 +129,9 @@ lex(struct slice start)
cur = cur->next;
}
+ cur->line = line;
+ cur->col = col;
+
return head;
}
@@ -131,9 +143,9 @@ void
expect(struct token *tok, enum tokentype type)
{
if (!tok)
- error("unexpected null token!");
+ error("unexpected null token!", tok->line, tok->col);
if (tok->type != type) {
- error("mismatch");
+ error("mismatch", tok->line, tok->col);
}
}
@@ -181,7 +193,7 @@ char *exprkind_str(enum exprkind kind)
case EXPR_COND:
return "EXPR_COND";
default:
- error("invalid exprkind");
+ die("invalid exprkind");
}
}
@@ -214,7 +226,7 @@ dumpbinop(enum binop op)
fprintf(stderr, "OP_GREATER");
break;
default:
- error("invalid binop");
+ die("invalid binop");
}
}
@@ -245,7 +257,7 @@ dumpexpr(int indent, struct expr *expr)
fprintf(stderr, "%.*s\n", (int)expr->d.call.name.len, expr->d.call.name.data);
break;
default:
- error("dumpexpr: bad expression");
+ die("dumpexpr: bad expression");
}
}
@@ -257,13 +269,15 @@ parseexpr(struct token **tok)
struct expr expr = { 0 };
switch ((*tok)->type) {
case TOK_LOOP:
- *tok = (*tok)->next;
+ expr.start = *tok;
expr.kind = EXPR_LOOP;
+ *tok = (*tok)->next;
expr.d.loop.block = parse(tok);
break;
case TOK_IF:
- *tok = (*tok)->next;
+ expr.start = *tok;
expr.kind = EXPR_COND;
+ *tok = (*tok)->next;
expr.d.cond.cond = parseexpr(tok);
expr.d.cond.bif = parse(tok);
if ((*tok)->type == TOK_ELSE) {
@@ -283,6 +297,7 @@ parseexpr(struct token **tok)
if ((*tok)->next && (*tok)->next->type == TOK_LPAREN) {
size_t pidx;
expr.d.call.name = (*tok)->slice;
+ expr.start = *tok;
*tok = (*tok)->next->next;
expr.kind = EXPR_FCALL;
@@ -297,6 +312,7 @@ parseexpr(struct token **tok)
expect(*tok, TOK_RPAREN);
// an ident
} else {
+ expr.start = *tok;
expr.kind = EXPR_IDENT;
expr.d.s = (*tok)->slice;
}
@@ -321,14 +337,16 @@ parseexpr(struct token **tok)
expr.kind = EXPR_BINARY;
expr.d.op = OP_MINUS;
binary_common:
+ expr.start = *tok;
*tok = (*tok)->next;
expr.left = parseexpr(tok);
expr.right = parseexpr(tok);
if (exprs.data[expr.left].class != exprs.data[expr.right].class)
- error("expected binary expression operands to be of same class");
+ error("expected binary expression operands to be of same class", (*tok)->line, (*tok)->col);
expr.class = exprs.data[expr.left].class;
break;
case TOK_STRING:
+ expr.start = *tok;
expr.kind = EXPR_LIT;
expr.class = C_STR;
expr.d.v.v.s = (struct slice){ 0 };
@@ -348,10 +366,10 @@ binary_common:
array_add((&expr.d.v.v.s), c);
break;
default:
- error("invalid string escape!");
+ error("invalid string escape!", (*tok)->line, (*tok)->col);
}
} else {
- error("string escape without parameter");
+ error("string escape without parameter", (*tok)->line, (*tok)->col);
}
break;
default:
@@ -361,7 +379,7 @@ binary_common:
*tok = (*tok)->next;
break;
default:
- error("invalid token for expression");
+ error("invalid token for expression", (*tok)->line, (*tok)->col);
}
array_add((&exprs), expr);
@@ -383,8 +401,10 @@ parse(struct token **tok)
while ((*tok)->type != TOK_NONE && (*tok)->type != TOK_RCURLY) {
item = (struct item){ 0 };
+ item.start = *tok;
if ((*tok)->type == TOK_LET) {
struct decl decl = { 0 };
+ decl.start = *tok;
item.kind = ITEM_DECL;
*tok = (*tok)->next;
@@ -398,7 +418,7 @@ parse(struct token **tok)
} else if (strncmp((*tok)->slice.data, "str", 3) == 0) {
decl.type = TYPE_STR;
} else {
- error("unknown type");
+ error("unknown type", (*tok)->line, (*tok)->col);
}
*tok = (*tok)->next;
@@ -407,7 +427,7 @@ parse(struct token **tok)
// FIXME: scoping
if (finddecl(&items, decl.s)) {
- error("repeat declaration!");
+ error("repeat declaration!", (*tok)->line, (*tok)->col);
}
decl.val = parseexpr(tok);
@@ -416,7 +436,8 @@ parse(struct token **tok)
item.idx = decls.len - 1;
array_add((&items), item);
} else if ((*tok)->type == TOK_NAME && (*tok)->next && (*tok)->next->type == TOK_EQUAL) {
- struct assgn assgn;
+ struct assgn assgn = { 0 };
+ assgn.start = *tok;
item.kind = ITEM_ASSGN;
assgn.s = (*tok)->slice;
@@ -445,50 +466,52 @@ void
typecheck(struct block items)
{
for (size_t i = 0; i < items.len; i++) {
+ struct item *item = &items.data[i];
struct expr *expr;
struct decl *decl;
switch (items.data[i].kind) {
case ITEM_DECL:
- decl = &decls.data[items.data[i].idx];
+ decl = &decls.data[item->idx];
switch (decl->type) {
case TYPE_I64:
expr = &exprs.data[decl->val];
// FIXME: we should be able to deal with ident or fcalls
- if (expr->class != C_INT) error("expected integer expression for integer declaration");
+ if (expr->class != C_INT)
+ error("expected integer expression for integer declaration", decl->start->line, decl->start->col);
break;
case TYPE_STR:
expr = &exprs.data[decl->val];
// FIXME: we should be able to deal with ident or fcalls
- if (expr->class != C_STR) error("expected string expression for string declaration");
+ if (expr->class != C_STR) error("expected string expression for string declaration", decl->start->line, decl->start->col);
break;
default:
- error("unknown decl type");
+ error("unknown decl type", decl->start->line, decl->start->col);
}
break;
case ITEM_ASSGN:
- struct assgn *assgn = &assgns.data[items.data[i].idx];
+ struct assgn *assgn = &assgns.data[item->idx];
decl = finddecl(&items, assgn->s);
if (decl == NULL)
- error("unknown name");
+ error("unknown name", assgn->start->line, assgn->start->col);
switch (decl->type) {
case TYPE_I64:
expr = &exprs.data[assgn->val];
// FIXME: we should be able to deal with ident or fcalls
- if (expr->class != C_INT) error("expected integer expression for integer variable");
+ if (expr->class != C_INT) error("expected integer expression for integer variable", assgn->start->line, assgn->start->col);
break;
case TYPE_STR:
expr = &exprs.data[assgn->val];
// FIXME: we should be able to deal with ident or fcalls
- if (expr->class != C_STR) error("expected string expression for string variable");
+ if (expr->class != C_STR) error("expected string expression for string variable", assgn->start->line, assgn->start->col);
break;
default:
- error("unknown decl type");
+ error("unknown decl type", assgn->start->line, assgn->start->col);
}
break;
case ITEM_EXPR:
break;
default:
- error("unknown item type");
+ error("unknown item type", item->start->line, item->start->col);
}
}
}
@@ -510,7 +533,7 @@ genexpr(char *buf, size_t idx, enum reg reg)
break;
}
default:
- error("genexpr: unknown value type!");
+ error("genexpr: unknown value type!", expr->start->line, expr->start->col);
}
} else if (expr->kind == EXPR_BINARY) {
len += genexpr(ptr ? ptr + len : ptr, expr->left, reg);
@@ -531,27 +554,28 @@ genexpr(char *buf, size_t idx, enum reg reg)
break;
}
default:
- error("genexpr: unknown binary op!");
+ error("genexpr: unknown binary op!", expr->start->line, expr->start->col);
}
freereg(rreg);
} else if (expr->kind == EXPR_IDENT) {
struct decl *decl = finddecl(curitems, expr->d.s);
if (decl == NULL) {
- error("unknown name!");
+ error("unknown name!", expr->start->line, expr->start->col);
}
len += mov_r64_m64(ptr ? ptr + len : ptr, reg, decl->addr);
} else {
- error("genexpr: could not generate code for expression");
+ error("genexpr: could not generate code for expression", expr->start->line, expr->start->col);
}
return len;
}
size_t
-gensyscall(char *buf, struct fparams *params)
+gensyscall(char *buf, struct expr *expr)
{
size_t len = 0;
+ struct fparams *params = &expr->d.call.params;
if (params->len > 7)
- error("syscall can take at most 7 parameters");
+ error("syscall can take at most 7 parameters", expr->start->line, expr->start->col);
// encoding for argument registers in ABI order
for (int i = 0; i < params->len; i++) {
@@ -579,38 +603,38 @@ genblock(char *buf, struct block *block)
for (int i = 0; i < block->len; i++) {
struct item *item = &block->data[i];
if (item->kind == ITEM_EXPR) {
- struct expr expr = exprs.data[item->idx];
+ struct expr *expr = &exprs.data[item->idx];
// FIXME: 7 should not be hardcoded here
- if (expr.kind == EXPR_FCALL) {
- if (slice_cmplit(&exprs.data[item->idx].d.call.name, "syscall") == 0) {
- total += gensyscall(buf ? buf + total : NULL, &(exprs.data[item->idx].d.call.params));
+ if (expr->kind == EXPR_FCALL) {
+ if (slice_cmplit(&expr->d.call.name, "syscall") == 0) {
+ total += gensyscall(buf ? buf + total : NULL, expr);
} else {
- error("unknown function!");
+ error("unknown function!", expr->start->line, expr->start->col);
}
- } else if (expr.kind == EXPR_COND) {
- struct expr *binary = &exprs.data[expr.d.cond.cond];
+ } else if (expr->kind == EXPR_COND) {
+ struct expr *binary = &exprs.data[expr->d.cond.cond];
// FIXME this should go away
assert(binary->kind == EXPR_BINARY);
enum reg reg = getreg();
- total += genexpr(buf ? buf + total : NULL, expr.d.cond.cond, reg);
- size_t iflen = genblock(NULL, &expr.d.cond.bif) + jmp(NULL, 0);
- size_t elselen = genblock(NULL, &expr.d.cond.belse);
+ total += genexpr(buf ? buf + total : NULL, expr->d.cond.cond, reg);
+ size_t iflen = genblock(NULL, &expr->d.cond.bif) + jmp(NULL, 0);
+ size_t elselen = genblock(NULL, &expr->d.cond.belse);
switch (binary->d.op) {
case OP_GREATER:
total += jng(buf ? buf + total : NULL, iflen);
break;
default:
- error("unknown binop for conditional");
+ error("unknown binop for conditional", expr->start->line, expr->start->col);
}
- total += genblock(buf ? buf + total : NULL, &expr.d.cond.bif);
+ total += genblock(buf ? buf + total : NULL, &expr->d.cond.bif);
total += jmp(buf ? buf + total: NULL, elselen);
- total += genblock(buf ? buf + total : NULL, &expr.d.cond.belse);
- } else if (expr.kind == EXPR_LOOP) {
- size_t back = genblock(NULL, &expr.d.loop.block) + jmp(NULL, 0);
- total += genblock(buf ? buf + total : NULL, &expr.d.loop.block);
+ total += genblock(buf ? buf + total : NULL, &expr->d.cond.belse);
+ } else if (expr->kind == EXPR_LOOP) {
+ size_t back = genblock(NULL, &expr->d.loop.block) + jmp(NULL, 0);
+ total += genblock(buf ? buf + total : NULL, &expr->d.loop.block);
total += jmp(buf ? buf + total: NULL, -back);
} else {
- error("unhandled toplevel expression type!");
+ error("unhandled toplevel expression type!", expr->start->line, expr->start->col);
}
} else if (item->kind == ITEM_DECL) {
struct expr *expr = &exprs.data[decls.data[item->idx].val];
@@ -635,17 +659,17 @@ genblock(char *buf, struct block *block)
decls.data[item->idx].addr = data_pushint(data_push(expr->d.v.v.s.data, expr->d.v.v.s.len));
break;
default:
- error("cannot generate code for unknown expression class");
+ error("cannot generate code for unknown expression class", expr->start->line, expr->start->col);
}
} else if (item->kind == ITEM_ASSGN) {
struct expr *expr = &exprs.data[assgns.data[item->idx].val];
struct assgn *assgn = &assgns.data[item->idx];
struct decl *decl = finddecl(block, assgn->s);
if (decl == NULL)
- error("unknown name");
+ error("unknown name", assgn->start->line, assgn->start->col);
if (buf && decl->addr == 0)
- error("assignment before declaration");
+ error("assignment before declaration", assgn->start->line, assgn->start->col);
switch (expr->class) {
case C_INT:
@@ -662,10 +686,10 @@ genblock(char *buf, struct block *block)
total += mov_m64_r64(buf ? buf + total : NULL, decl->addr, reg);
break;
default:
- error("cannot generate code for unknown expression class");
+ error("cannot generate code for unknown expression class", expr->start->line, expr->start->col);
}
} else {
- error("cannot generate code for type");
+ error("cannot generate code for type", item->start->line, item->start->col);
}
}
@@ -682,7 +706,8 @@ main(int argc, char *argv[])
return 1;
}
- int in = open(argv[1], 0, O_RDONLY);
+ infile = argv[1];
+ int in = open(infile, 0, O_RDONLY);
if (in < 0) {
fprintf(stderr, "couldn't open input\n");
return 1;
diff --git a/nooc.h b/nooc.h
@@ -34,6 +34,7 @@ struct slice {
struct token {
enum tokentype type;
+ size_t line, col;
struct slice slice;
struct token *next;
};
@@ -58,6 +59,7 @@ enum type {
struct assgn {
struct slice s;
size_t val; // struct exprs
+ struct token *start;
};
struct assgns {
@@ -71,6 +73,7 @@ struct decl {
enum type type;
size_t val; // struct exprs
size_t addr;
+ struct token *start;
};
struct decls {
@@ -92,6 +95,7 @@ struct item {
ITEM_EXPR,
} kind;
size_t idx;
+ struct token *start;
};
struct block {
@@ -151,6 +155,7 @@ struct expr {
} d;
size_t left;
size_t right;
+ struct token *start;
};
struct exprs {
diff --git a/test/syntax1.fail.nooc b/test/syntax1.fail.nooc
@@ -0,0 +1 @@
+a i64 =+
\ No newline at end of file
diff --git a/util.c b/util.c
@@ -7,6 +7,8 @@
#include "array.h"
#include "util.h"
+extern char *infile;
+
int
slice_cmplit(struct slice *s1, char *s2)
{
@@ -18,7 +20,14 @@ slice_cmplit(struct slice *s1, char *s2)
}
void
-error(char *error)
+error(char *error, size_t line, size_t col)
+{
+ fprintf(stderr, "%s:%u:%u: %s\n", infile, line, col, error);
+ exit(1);
+}
+
+void
+die(char *error)
{
fprintf(stderr, "%s\n", error);
exit(1);
diff --git a/util.h b/util.h
@@ -1,2 +1,3 @@
int slice_cmplit(struct slice *s1, char *s2);
-void error(char *error);
+void error(char *error, size_t line, size_t col);
+void die(char *error);
diff --git a/x64.c b/x64.c
@@ -26,7 +26,7 @@ getreg()
}
}
- error("out of registers!");
+ die("out of registers!");
}
void
@@ -164,7 +164,7 @@ jng(char *buf, int64_t offset)
}
return 2;
} else {
- error("unimplemented jng offet!");
+ die("unimplemented jng offet!");
}
}
@@ -179,7 +179,7 @@ jg(char *buf, int64_t offset)
}
return 2;
} else {
- error("unimplemented jg offet!");
+ die("unimplemented jg offet!");
}
}
@@ -194,6 +194,6 @@ jmp(char *buf, int64_t offset)
}
return 2;
} else {
- error("unimplemented jmp offet!");
+ die("unimplemented jmp offet!");
}
}