diff options
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 61 |
1 files changed, 33 insertions, 28 deletions
@@ -213,41 +213,46 @@ Node *parse_term(Lexer *l, Proc *p) { return node_peephole(node, p, l); } +NodeType tok_to_bin_op(Token t) { + switch (t) { + case TOK_PLUS: return N_OP_ADD; break; + case TOK_MINUS: return N_OP_SUB; break; + case TOK_ASTERISK: return N_OP_MUL; break; + case TOK_SLASH: return N_OP_DIV; break; + case TOK_NOT: return N_OP_NOT; break; + case TOK_AND: return N_OP_AND; break; + case TOK_OR: return N_OP_OR; break; + case TOK_XOR: return N_OP_XOR; break; + case TOK_SHL: return N_OP_SHL; break; + case TOK_SHR: return N_OP_SHR; break; + case TOK_EQL: return N_CMP_EQL; break; + case TOK_NEQ: return N_CMP_NEQ; break; + case TOK_LES: return N_CMP_LES; break; + case TOK_GTR: return N_CMP_GTR; break; + case TOK_LTE: return N_CMP_LTE; break; + case TOK_GTE: return N_CMP_GTE; break; + default: return N_START; break; + } +} + /* TODO: operator precedence would be kinda nice actually, sad to say */ Node *parse_expr(Lexer *l, Proc *p) { LexSpan pos = l->pos; Node *lhs = parse_term(l, p); - if (TMASK(l->tok) & (TM_PLUS | TM_MINUS | TM_ASTERISK | TM_SLASH - | TM_NOT | TM_AND | TM_XOR | TM_OR | TM_SHL | TM_SHR - | TM_EQL | TM_NEQ | TM_LES | TM_GTR | TM_LTE | TM_GTE)) { - Token t = l->tok; + NodeType nt = tok_to_bin_op(l->tok);; + assert(lhs->refs > 0); + if (nt != N_START) { lex_next(l); + /* necessary because if lhs is a deduplicated literal, it may be an input to rhs + * and therefore culled by peephole optimizations */ + node_add(p, lhs, p->keepalive); Node *rhs = parse_expr(l, p); - NodeType nt = N_OP_ADD; - switch (t) { - case TOK_PLUS: nt = N_OP_ADD; break; - case TOK_MINUS: nt = N_OP_SUB; break; - case TOK_ASTERISK: nt = N_OP_MUL; break; - case TOK_SLASH: nt = N_OP_DIV; break; - case TOK_NOT: nt = N_OP_NOT; break; - case TOK_AND: nt = N_OP_AND; break; - case TOK_OR: nt = N_OP_OR; break; - case TOK_XOR: nt = N_OP_XOR; break; - case TOK_SHL: nt = N_OP_SHL; break; - case TOK_SHR: nt = N_OP_SHR; break; - case TOK_EQL: nt = N_CMP_EQL; break; - case TOK_NEQ: nt = N_CMP_NEQ; break; - case TOK_LES: nt = N_CMP_LES; break; - case TOK_GTR: nt = N_CMP_GTR; break; - case TOK_LTE: nt = N_CMP_LTE; break; - case TOK_GTE: nt = N_CMP_GTE; break; - default: break; - } - lhs = node_new(p, nt, lhs, rhs); + Node *n = node_peephole(node_new(p, nt, lhs, rhs), p, l); + node_remove(p, lhs, p->keepalive); + lhs = n; } - Node *n = node_peephole(lhs, p, l); - n->src_pos = (LexSpan) { pos.ofs, l->pos.ofs - pos.ofs }; - return n; + lhs->src_pos = (LexSpan) { pos.ofs, l->pos.ofs - pos.ofs }; + return lhs; } void parse_toplevel(Lexer *l, Unit *u) { |
