aboutsummaryrefslogtreecommitdiff
path: root/src/parser.c
diff options
context:
space:
mode:
authorMustafa Quraish <[email protected]>2022-02-03 06:22:24 -0500
committerMustafa Quraish <[email protected]>2022-02-03 06:26:17 -0500
commit19c27785a9d1e66ea72f36d4e2a6dad3d492c57f (patch)
tree1bb956b37e6ccd7fa681273e4c43fc53173ba773 /src/parser.c
parentMake `make test` exit early if any of the tests fail (diff)
downloadcup-19c27785a9d1e66ea72f36d4e2a6dad3d492c57f.tar.xz
cup-19c27785a9d1e66ea72f36d4e2a6dad3d492c57f.zip
Add an implicit block around a `for` loop, allow statement init
Now we can have variable declarations as part of the initialization of the for loop, and it can only be accessed within the loop.
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c39
1 files changed, 27 insertions, 12 deletions
diff --git a/src/parser.c b/src/parser.c
index f412c79..e3076f2 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -346,7 +346,7 @@ Node *parse_identifier(Lexer *lexer)
Node *parse_factor(Lexer *lexer)
{
// TODO: We need to properly handle type conversions / operations with different types
- // where we need to cast one of the operands / etc. Perhaps have a separate
+ // where we need to cast one of the operands / etc. Perhaps have a separate
// type-checking / adding casts/conversions pass?
Token token = Lexer_peek(lexer);
Node *expr = NULL;
@@ -409,7 +409,7 @@ Node *parse_factor(Lexer *lexer)
offset->binary.left = expr;
offset->binary.right = index;
offset = handle_binary_expr_types(offset, &token);
-
+
expr = Node_new(OP_DEREF);
expr->unary_expr = offset;
expr = handle_unary_expr_types(expr, &token);
@@ -470,7 +470,7 @@ Node *parse_conditional_exp(Lexer *lexer)
if (!type_equals(then_expr->expr_type, else_expr->expr_type))
die_location(token.loc, "Type mismatch in conditional expression cases");
-
+
conditional->expr_type = then_expr->expr_type;
expr = conditional;
expr->expr_type = then_expr->expr_type;
@@ -547,26 +547,41 @@ Node *parse_statement(Lexer *lexer)
node->loop.body = parse_statement(lexer);
} else if (token.type == TOKEN_FOR) {
Lexer_next(lexer);
- node = Node_new(AST_FOR);
+
+
+ Node *loop = Node_new(AST_FOR);
assert_token(Lexer_next(lexer), TOKEN_OPEN_PAREN);
+ // NOTE: We're going to put the for loop in it's own block
+ // so that any declarations in the init of the loop
+ // can only be referenced within the loop.
+ node = Node_new(AST_BLOCK);
+ Node_add_child(node, loop);
+ block_stack_push(node);
+
// All of the expressions in the for loop are optional
- // TODO: Allow this to be a declaration, need to inject
- // the variable into the symbol table for the block
- if (Lexer_peek(lexer).type != TOKEN_SEMICOLON)
- node->loop.init = parse_expression(lexer);
- assert_token(Lexer_next(lexer), TOKEN_SEMICOLON);
+ token = Lexer_peek(lexer);
+ // FIXME: Maybe `parse_var_declaration` shouldn't consume the semicolon?
+ if (token.type == TOKEN_LET) {
+ loop->loop.init = parse_var_declaration(lexer);
+ } else {
+ if (token.type != TOKEN_SEMICOLON)
+ loop->loop.init = parse_expression(lexer);
+ assert_token(Lexer_next(lexer), TOKEN_SEMICOLON);
+ }
if (Lexer_peek(lexer).type != TOKEN_SEMICOLON)
- node->loop.cond = parse_expression(lexer);
+ loop->loop.cond = parse_expression(lexer);
assert_token(Lexer_next(lexer), TOKEN_SEMICOLON);
if (Lexer_peek(lexer).type != TOKEN_CLOSE_PAREN)
- node->loop.step = parse_expression(lexer);
+ loop->loop.step = parse_expression(lexer);
assert_token(Lexer_next(lexer), TOKEN_CLOSE_PAREN);
- node->loop.body = parse_statement(lexer);
+ loop->loop.body = parse_statement(lexer);
+ block_stack_pop();
+
} else if (token.type == TOKEN_OPEN_BRACE) {
node = parse_block(lexer);
} else if (token.type == TOKEN_DEFER) {