diff options
| author | Mustafa Quraish <[email protected]> | 2022-02-03 06:53:58 -0500 |
|---|---|---|
| committer | Mustafa Quraish <[email protected]> | 2022-02-03 06:55:06 -0500 |
| commit | 108e3fd89cbe6de0c3a293cfd18ca5892a9c9c20 (patch) | |
| tree | 96f9c32a6b1982b5cad4f82dc8592f83e2dc7015 | |
| parent | Add an implicit block around a `for` loop, allow statement init (diff) | |
| download | cup-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.c | 35 | ||||
| -rw-r--r-- | src/types.c | 1 |
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; } |