diff options
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/lex.c | 11 | ||||
| -rw-r--r-- | boot/parse.c | 41 | ||||
| -rw-r--r-- | boot/tree.c | 27 |
3 files changed, 54 insertions, 25 deletions
diff --git a/boot/lex.c b/boot/lex.c index 52760e9..f09e5e3 100644 --- a/boot/lex.c +++ b/boot/lex.c @@ -97,6 +97,7 @@ enum Token_Kind TOKEN_WORD_SWITCH, TOKEN_WORD_RETURN, TOKEN_WORD_VAR, + TOKEN_WORD_LET, TOKEN_WORD_TYPE, TOKEN_WORD_VARIANT, TOKEN_WORD_CLASS, @@ -200,6 +201,8 @@ token_kind_to_string(enum Token_Kind kind) return "WORD_RETURN"; case TOKEN_WORD_VAR: return "WORD_VAR"; + case TOKEN_WORD_LET: + return "WORD_LET"; case TOKEN_WORD_TYPE: return "WORD_TYPE"; case TOKEN_WORD_VARIANT: @@ -407,6 +410,12 @@ token_can_begin_type(const struct Token* t) } bool +token_can_begin_declaration(const struct Token* t) +{ + return token_is(t, TOKEN_WORD_VAR) || token_is(t, TOKEN_WORD_LET); +} + +bool ascii_in_range(ascii c, ascii from, ascii to) { return c >= from && c <= to; @@ -793,6 +802,8 @@ lexer_word_from_name(struct Lexer* l, struct String word_or_name) return TOKEN_WORD_RETURN; case 1662845996: // "var" return TOKEN_WORD_VAR; + case 860722406: + return TOKEN_WORD_LET; case 91700392: // "type" return TOKEN_WORD_TYPE; case 3267162257: // "variant" 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: diff --git a/boot/tree.c b/boot/tree.c index 449f4e6..dff0858 100644 --- a/boot/tree.c +++ b/boot/tree.c @@ -912,8 +912,30 @@ struct Statement_Value_Expression struct Expression* inner; }; +enum Statement_Declaration_Kind +{ + STATEMENT_DECLARATION_NONE, + STATEMENT_DECLARATION_VARIABLE, + STATEMENT_DECLARATION_CONSTANT, +}; + +enum Statement_Declaration_Kind +statement_declaration_kind_from_token(const struct Token* token) +{ + switch (token->kind) { + case TOKEN_WORD_VAR: + return STATEMENT_DECLARATION_VARIABLE; + case TOKEN_WORD_LET: + return STATEMENT_DECLARATION_CONSTANT; + + default: + return STATEMENT_DECLARATION_NONE; + } +} + struct Statement_Value_Declaration { + enum Statement_Declaration_Kind kind; struct String_Array names; struct Expression* initializer; struct Type_Node* type; @@ -1042,6 +1064,11 @@ statement_print(const struct Statement* statement) } case STATEMENT_DECLARATION: { printf("(declaration "); + if (statement->value.declaration.kind == STATEMENT_DECLARATION_VARIABLE) + printf("variable "); + else if (statement->value.declaration.kind == STATEMENT_DECLARATION_CONSTANT) + printf("constant "); + STRING_ARRAY_FOR_EACH(i, name, statement->value.declaration.names) { printf("%s ", name.data); |
