summaryrefslogtreecommitdiff
path: root/parser.c
diff options
context:
space:
mode:
authorCarson Fleming <cflems@cflems.net>2026-03-31 16:30:29 -1000
committerCarson Fleming <cflems@cflems.net>2026-03-31 16:30:29 -1000
commit1dfa2971999b4adf36a33866b0b07af07188da08 (patch)
tree7d65b9a5780a95bf519fed6d435bdade264aac62 /parser.c
parent7cf2065be92855b5b1db31a4bb7afbb4af29a817 (diff)
downloadccc-1dfa2971999b4adf36a33866b0b07af07188da08.tar.gz
math n shi
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c87
1 files changed, 76 insertions, 11 deletions
diff --git a/parser.c b/parser.c
index f9c7047..6a8ad31 100644
--- a/parser.c
+++ b/parser.c
@@ -107,21 +107,18 @@ static void parse_var_ref(struct var_ref_node* p_node) {
p_node->ident = tok.data.ident;
}
-static void expr_to_lval(struct lval_node* l_node, struct expr_node* e_node) {
- switch (e_node->type) {
+static void parse_expr_assign(struct expr_node* p_node) {
+ switch (p_node->type) {
case EXPR_VAR_REF:
- *l_node = (struct lval_node) {
+ p_node->as._assign.lval = (struct lval_node) {
.type = LVAL_VAR_REF,
- .as._var_ref = e_node->as._var_ref,
+ .as._var_ref = p_node->as._var_ref,
};
return;
default:
PARSER_PANIC("expression is not assignable");
}
-}
-static void parse_expr_assign(struct expr_node* p_node) {
- expr_to_lval(&p_node->as._assign.lval, p_node);
p_node->type = EXPR_ASSIGN;
p_node->as._assign.rval = protected_alloc(sizeof(struct expr_node));
@@ -167,6 +164,59 @@ static void parse_expr_call(struct expr_node* p_node) {
expect(TK_RPAREN);
}
+static void parse_unary(struct unary_node* p_node) {
+ peek_or_panic();
+ switch (tok.type) {
+ case TK_NEG:
+ expect(TK_NEG);
+ p_node->op = UNARY_NEG;
+ break;
+ default:
+ PARSER_PANIC("expected unary operator");
+ }
+
+ p_node->expr = protected_alloc(sizeof(struct expr_node));
+ parse_expr(p_node->expr);
+}
+
+static void parse_expr_binary(struct expr_node* p_node) {
+ struct expr_node* lhs = protected_alloc(sizeof(struct expr_node));
+ struct expr_node* rhs = protected_alloc(sizeof(struct expr_node));
+
+ *lhs = *p_node;
+ *p_node = (struct expr_node) {
+ .type = EXPR_BINARY,
+ .as._binary = {
+ .lhs = lhs,
+ .rhs = rhs,
+ },
+ };
+
+ peek_or_panic();
+ switch (tok.type) {
+ case TK_PLUS:
+ expect(TK_PLUS);
+ p_node->as._binary.op = BINARY_ADD;
+ break;
+ case TK_NEG:
+ expect(TK_NEG);
+ p_node->as._binary.op = BINARY_SUB;
+ break;
+ case TK_STAR:
+ expect(TK_STAR);
+ p_node->as._binary.op = BINARY_MUL;
+ break;
+ case TK_DIV:
+ expect(TK_DIV);
+ p_node->as._binary.op = BINARY_DIV;
+ break;
+ default:
+ PARSER_PANIC("expected binary operator");
+ }
+
+ parse_expr(rhs);
+}
+
static void parse_expr(struct expr_node* p_node) {
peek_or_panic();
switch (tok.type) {
@@ -175,6 +225,10 @@ static void parse_expr(struct expr_node* p_node) {
parse_expr(p_node);
expect(TK_RPAREN);
break;
+ case TK_NEG:
+ p_node->type = EXPR_UNARY;
+ parse_unary(&p_node->as._unary);
+ break;
case TK_INT_LIT:
case TK_CHAR_LIT:
case TK_FLOAT_LIT:
@@ -190,10 +244,21 @@ static void parse_expr(struct expr_node* p_node) {
}
peek_or_panic();
- if (tok.type == TK_ASSIGN)
- parse_expr_assign(p_node);
- else if (tok.type == TK_LPAREN)
- parse_expr_call(p_node);
+ switch (tok.type) {
+ case TK_ASSIGN:
+ parse_expr_assign(p_node);
+ break;
+ case TK_LPAREN:
+ parse_expr_call(p_node);
+ break;
+ case TK_PLUS:
+ case TK_NEG:
+ case TK_STAR:
+ case TK_DIV:
+ parse_expr_binary(p_node);
+ break;
+ default:
+ }
}
static void parse_var_decl(struct var_decl_node* p_node) {