about summary refs log tree commit diff
path: root/boot/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'boot/parse.c')
-rw-r--r--boot/parse.c41
1 files changed, 16 insertions, 25 deletions
diff --git a/boot/parse.c b/boot/parse.c
index a0dd12c..6129950 100644
--- a/boot/parse.c
+++ b/boot/parse.c
@@ -193,26 +193,6 @@ parser_end_statement(struct Parser* p, struct Parser_Error* error)
     parser_next(p);
 }
 
-// checks if the next 2 tokens could begin a variable declaration.
-bool
-parser_could_be_variable_declaration(struct Parser* p)
-{
-    // NOTE: these can be a variable declaration:
-    //     x uint = 123
-    //     me, them Obj = create()
-    // otherwise without a type, it is instead counted as an assignment:
-    //     a = "hi!"
-
-    // NOTE: maybe move this into `lex.c`?
-    // or change the API a bit, this isn't really a parser method.
-    struct Token first = parser_peek(p);
-    struct Token second = parser_peek_further(p);
-
-    bool first_matches = token_is(&first, TOKEN_NAME);
-    bool second_matches = token_is(&second, TOKEN_COMMA) || token_can_begin_type(&second);
-    return first_matches && second_matches;
-}
-
 struct Block_Node
 parser_block_node(struct Parser* p, struct Parser_Error* error)
 {
@@ -795,6 +775,12 @@ parser_expression(struct Parser* p, struct Parser_Error* error)
 struct Statement*
 parser_statement_declaration(struct Parser* p, struct Parser_Error* error)
 {
+    struct Token declaration_token = parser_next(p);
+
+    enum Statement_Declaration_Kind declaration_kind =
+        statement_declaration_kind_from_token(&declaration_token);
+    check(declaration_kind, "expected valid declaration token");
+
     struct String_Array names = string_array_new();
 
     struct Span span = { 0 };
@@ -819,6 +805,7 @@ parser_statement_declaration(struct Parser* p, struct Parser_Error* error)
     span = span_merge(span, initializer->span);
     union Statement_Value value = {
         .declaration = {
+            .kind = declaration_kind,
             .names = names,
             .type = type,
             .initializer = initializer,
@@ -882,16 +869,20 @@ parser_statement_loop(struct Parser* p, struct Parser_Error* error)
     struct Token for_token = CHECK(parser_need(p, TOKEN_WORD_FOR, error));
 
     // these are the possible for loop variants:
-    // * `for String name = collection {}`, as iteration over container
+    // * `for var name String = collection {}`, as iteration over container
     // * `for check() {}`, as a simple while-style loop
-    // * `for u8 i = 0, i < 10, i++ {}`, as a c-style semi-semi loop
+    // * `for var i u8 = 0, i < 10, i++ {}`, as a c-style semi-semi loop
     // * `for {}`, as an infinite loop
 
     struct Statement* declaration = nil;
     struct Expression *condition = nil, *iteration = nil;
 
     // c-style or iterator-style
-    if (parser_could_be_variable_declaration(p)) {
+    struct Token next = parser_peek(p);
+    // TODO: i do not like the `for var` combination, it is too verbose.
+    // it would be beneficial to bring back `while`, so that declarations without `var`
+    // are no longer ambiguous.
+    if (token_can_begin_declaration(&next)) {
         declaration = CHECK(parser_statement_declaration(p, error));
 
         // c-style
@@ -905,7 +896,7 @@ parser_statement_loop(struct Parser* p, struct Parser_Error* error)
     }
 
     // while-style
-    if (!parser_probe(p, TOKEN_CURLY_OPEN)) condition = CHECK(parser_expression(p, error));
+    if (!token_is(&next, TOKEN_CURLY_OPEN)) condition = CHECK(parser_expression(p, error));
 
     struct Block_Node body = CHECK(parser_block_node(p, error));
     struct Span span = span_merge(for_token.span, body.span);
@@ -1007,7 +998,7 @@ parser_statement(struct Parser* p, struct Parser_Error* error)
         token = parser_peek(p);
     }
 
-    if (parser_could_be_variable_declaration(p)) return parser_statement_declaration(p, error);
+    if (token_can_begin_declaration(&token)) return parser_statement_declaration(p, error);
 
     switch (token.kind) {
     case TOKEN_WORD_IF: