aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMustafa Quraish <[email protected]>2022-02-03 06:53:58 -0500
committerMustafa Quraish <[email protected]>2022-02-03 06:55:06 -0500
commit108e3fd89cbe6de0c3a293cfd18ca5892a9c9c20 (patch)
tree96f9c32a6b1982b5cad4f82dc8592f83e2dc7015
parentAdd an implicit block around a `for` loop, allow statement init (diff)
downloadcup-108e3fd89cbe6de0c3a293cfd18ca5892a9c9c20.tar.xz
cup-108e3fd89cbe6de0c3a293cfd18ca5892a9c9c20.zip
Add pre-increment and pre-decrement operators.
The implementation is very hacky, maybe there's a better way to go about doing this. Maybe just keep it as single AST node and do the work during codegen?
-rw-r--r--src/parser.c35
-rw-r--r--src/types.c1
2 files changed, 34 insertions, 2 deletions
diff --git a/src/parser.c b/src/parser.c
index e3076f2..2bb5649 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -360,6 +360,33 @@ Node *parse_factor(Lexer *lexer)
expr = Node_new(OP_BWINV);
expr->unary_expr = parse_factor(lexer);
expr = handle_unary_expr_types(expr, &token);
+
+ // ++x is changed to (x = x + 1)
+ } else if (token.type == TOKEN_PLUSPLUS) {
+ Lexer_next(lexer);
+ expr = Node_new(OP_ASSIGN);
+ expr->assign.var = parse_factor(lexer);
+ if (!is_lvalue(expr->assign.var->type))
+ die_location(token.loc, "Cannot increment non-lvalue");
+ expr->assign.value = Node_new(OP_PLUS);
+ expr->assign.value->binary.left = expr->assign.var;
+ expr->assign.value->binary.right = Node_from_int_literal(1);
+ expr->assign.value = handle_binary_expr_types(expr->assign.value, &token);
+ expr->expr_type = expr->assign.var->expr_type;
+
+ // --x is changed to (x = x - 1)
+ } else if (token.type == TOKEN_MINUSMINUS) {
+ Lexer_next(lexer);
+ expr = Node_new(OP_ASSIGN);
+ expr->assign.var = parse_factor(lexer);
+ if (!is_lvalue(expr->assign.var->type))
+ die_location(token.loc, "Cannot decrement non-lvalue");
+ expr->assign.value = Node_new(OP_MINUS);
+ expr->assign.value->binary.left = expr->assign.var;
+ expr->assign.value->binary.right = Node_from_int_literal(1);
+ expr->assign.value = handle_binary_expr_types(expr->assign.value, &token);
+ expr->expr_type = expr->assign.var->expr_type;
+
} else if (token.type == TOKEN_EXCLAMATION) {
Lexer_next(lexer);
expr = Node_new(OP_NOT);
@@ -398,8 +425,8 @@ Node *parse_factor(Lexer *lexer)
token = Lexer_peek(lexer);
// Convert indexing into pointer arithmetic + dereferencing
if (token.type == TOKEN_OPEN_BRACKET) {
- // if (expr->expr_type->type != TYPE_PTR)
- // die_location(token.loc, "Cannot index non-pointer type");
+ if (expr->expr_type->type != TYPE_PTR)
+ die_location(token.loc, "Cannot index non-pointer type");
Lexer_next(lexer);
Node *index = parse_expression(lexer);
@@ -413,6 +440,10 @@ Node *parse_factor(Lexer *lexer)
expr = Node_new(OP_DEREF);
expr->unary_expr = offset;
expr = handle_unary_expr_types(expr, &token);
+ } else if (token.type == TOKEN_PLUSPLUS) {
+ die_location(token.loc, "Post-incrementing is not supported\n");
+ } else if (token.type == TOKEN_MINUSMINUS) {
+ die_location(token.loc, "Post-decrementing is not supported\n");
} else {
break;
}
diff --git a/src/types.c b/src/types.c
index 6c7c0e5..abbba86 100644
--- a/src/types.c
+++ b/src/types.c
@@ -146,6 +146,7 @@ Node *handle_unary_expr_types(Node *node, Token *token)
// Default to not changing the type
node->expr_type = old_type;
}
+
return node;
}