#include #include #include #include #include #include "lex.h" #include "arena.h" #include "dynarr.h" /* node graph */ typedef enum { N_START, N_STOP, N_LIT_INT, N_OP_ADD, N_OP_SUB, N_OP_MUL, N_OP_DIV, N_OP_NEG, } NodeType; typedef struct Node { int id; NodeType type; DYNARR(struct Node *) in, out; union { int64_t i; } v; } Node; typedef struct { Arena arena; int last_id; Node *start, *stop; } Proc; typedef struct { DYNARR(Proc) procs; } Unit; void unit_init(Unit *u) { (void)u; } void unit_fini(Unit *u) { free(u->procs.data); } Node *node_new(Proc *p, NodeType t) { Node *n = new(&p->arena, Node); n->type = t; n->id = p->last_id++; return n; } void node_add(Proc *p, Node *src, Node *dest) { ZDA_PUSH(&src->out, dest, &p->arena); ZDA_PUSH(&dest->in, src, &p->arena); } /* parsing */ Node *parse_expr(Lexer *l, Proc *p); void parse_return(Lexer *l, Proc *p) { lex_next(l); Node *n = parse_expr(l, p); node_add(p, n, p->stop); } void parse_stmt(Lexer *l, Proc *p) { /* TODO */ (void)l; switch (l->tok) { case TOK_RETURN: parse_return(l, p); break; default: lex_expected(l, TM_RBRACE); } } void parse_proc(Lexer *l, Unit *u) { DA_FIT(&u->procs, u->procs.len + 1); Proc *proc = &u->procs.data[u->procs.len++]; memset(proc, 0, sizeof(Proc)); proc->start = node_new(proc, N_START); proc->stop = node_new(proc, N_STOP); lex_expect(l, TM_IDENT); lex_expect(l, TM_LBRACE); lex_next(l); while (l->tok != TOK_RBRACE) { lex_expected_not(l, TM_EOF); parse_stmt(l, proc); } lex_expected(l, TM_RBRACE); lex_next(l); } Node *parse_term(Lexer *l, Proc *p) { Node *node = NULL; int negate_after = l->tok == TOK_MINUS; if (TMASK(l->tok) & (TM_MINUS | TM_PLUS)) { lex_next(l); } if (l->tok == TOK_LPAREN) { lex_next(l); node = parse_expr(l, p); lex_expected(l, TM_RPAREN); lex_next(l); } else { lex_expected(l, TM_LIT_NUM); int64_t val = 0; for (int i = 0; i < l->ident.n; i++) { if (!(l->ident.s[i] >= '0' && l->ident.s[i] <= '9')) { lex_error(l, LE_ERROR, S("Not a digit")); break; } val = (val * 10) + (l->ident.s[i] - '0'); } node = node_new(p, N_LIT_INT); node_add(p, p->start, node); node->v.i = val; lex_next(l); } if (negate_after) { Node *neg = node_new(p, N_OP_NEG); node_add(p, node, neg); return neg; } return node; } Node *parse_expr(Lexer *l, Proc *p) { Node *lhs = parse_term(l, p); if (l->tok == TOK_LPAREN) { lex_next(l); puts("args_start"); for (;;) { parse_expr(l, p); lex_expected(l, TM_COMMA | TM_RPAREN); if (l->tok == TOK_RPAREN) break; lex_next(l); } lex_next(l); puts("args_end"); puts("func_call"); } if (TMASK(l->tok) & (TM_PLUS | TM_MINUS | TM_ASTERISK | TM_SLASH)) { lex_expected(l, TM_PLUS); lex_next(l); Node *rhs = parse_expr(l, p); Node *add = node_new(p, N_OP_ADD); node_add(p, lhs, add); node_add(p, rhs, add); return add; } return lhs; } void parse_toplevel(Lexer *l, Unit *u) { switch (l->tok) { case TOK_PROC: parse_proc(l, u); break; default: lex_expected(l, TM_PROC); break; } } void parse_unit(Lexer *l) { Unit u = { 0 }; unit_init(&u); while (l->tok != TOK_EOF) { parse_toplevel(l, &u); } unit_fini(&u); } int main(int argc, const char **argv) { if (argc != 2) { fprintf(stderr, "Usage: %s FILE\n", argv[0]); return 1; } Lexer l = { 0 }; lex_start(&l, argv[1]); parse_unit(&l); lex_free(&l); return 0; }