diff options
author | Carlos Maniero <carlos@maniero.me> | 2023-05-02 23:45:51 -0300 |
---|---|---|
committer | Johnny Richard <johnny@johnnyrichard.com> | 2023-05-03 22:45:23 +0200 |
commit | e623c701d2ef41cf4993590e2932c7538c83fc54 (patch) | |
tree | e096ead143fe76d73df5789a3aee5b2b6358c602 /src/parser.c | |
parent | 990f4d3e4c662c401a08e3704a39878fd6c1c1b6 (diff) |
parser: Use lookahead instead of consuming tokens
Previously, during block declaration, the parser consumed the token
which caused some parsers (such as return and variable declaration) to
not be self-contained and to depend on the callee to start the parser.
In this commit, I've refactored the parser to only look for future
tokens using lookahead, and delegate the consumption to child parser
functions. This results in a more modular and self-contained parser that
improves the overall maintainability and readability of the code.
Signed-off-by: Carlos Maniero <carlos@maniero.me>
Diffstat (limited to 'src/parser.c')
-rw-r--r-- | src/parser.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/src/parser.c b/src/parser.c index 8218c87..5f7a709 100644 --- a/src/parser.c +++ b/src/parser.c @@ -224,6 +224,10 @@ parser_parse_expression(parser_t *parser, ast_node_t *node) static ast_node_t * parser_parse_return_stmt(parser_t *parser) { + if (!drop_expected_token(parser, TOKEN_KEYWORD_RETURN)) { + return NULL; + } + ast_node_t *argument_token = ast_node_new(); if (!parser_parse_expression(parser, argument_token)) { ast_node_destroy(argument_token); @@ -241,8 +245,14 @@ parser_parse_return_stmt(parser_t *parser) } static bool -parser_parse_variable_assignment(parser_t *parser, token_t variable_token, ast_node_t *node) +parser_parse_variable_assignment(parser_t *parser, ast_node_t *node) { + token_t variable_token; + + if (!expected_token(&variable_token, parser, TOKEN_NAME)) { + return false; + } + if (!drop_expected_token(parser, TOKEN_EQUAL)) return false; @@ -275,8 +285,13 @@ parser_parse_variable_assignment(parser_t *parser, token_t variable_token, ast_n } static bool -parser_parse_variable_definition(parser_t *parser, string_view_t variable_name, ast_node_t *node) +parser_parse_variable_definition(parser_t *parser, ast_node_t *node) { + token_t variable_name; + if (!expected_token(&variable_name, parser, TOKEN_NAME)) { + return false; + } + if (!drop_expected_token(parser, TOKEN_COLON)) return false; @@ -295,7 +310,7 @@ parser_parse_variable_definition(parser_t *parser, string_view_t variable_name, return false; } - ast_node_init_variable_declaration(node, variable_name, type, expression); + ast_node_init_variable_declaration(node, variable_name.value, type, expression); scope_push(parser->scope, &node->data.variable_declaration.identifier, node); return true; @@ -309,7 +324,7 @@ parser_parse_block_declarations(parser_t *parser) } token_t current_token; - lexer_next_token(parser->lexer, ¤t_token); + lexer_peek_next_token(parser->lexer, ¤t_token); scope_enter(parser->scope); @@ -335,13 +350,13 @@ parser_parse_block_declarations(parser_t *parser) vector_push_back(body, return_node); } else { token_t token; - lexer_peek_next_token(parser->lexer, &token); + lexer_lookahead(parser->lexer, &token, 2); switch (token.kind) { case TOKEN_COLON: { ast_node_t *variable_node = ast_node_new(); - if (!parser_parse_variable_definition(parser, current_token.value, variable_node)) { + if (!parser_parse_variable_definition(parser, variable_node)) { ast_node_destroy(variable_node); vector_destroy(body); return NULL; @@ -353,7 +368,7 @@ parser_parse_block_declarations(parser_t *parser) case TOKEN_EQUAL: { ast_node_t *variable_assignment = ast_node_new(); - if (!parser_parse_variable_assignment(parser, current_token, variable_assignment)) { + if (!parser_parse_variable_assignment(parser, variable_assignment)) { ast_node_destroy(variable_assignment); vector_destroy(body); return NULL; @@ -376,13 +391,17 @@ parser_parse_block_declarations(parser_t *parser) case TOKEN_SLASH: case TOKEN_EOF: case TOKEN_UNKNOWN: + // FIXME: Show an error it means syntax error + lexer_drop_next_token(parser->lexer); break; } } - lexer_next_token(parser->lexer, ¤t_token); + lexer_peek_next_token(parser->lexer, ¤t_token); } + lexer_next_token(parser->lexer, ¤t_token); + if (current_token.kind == TOKEN_EOF) { parser_error_push_unexpected_kind(parser, ¤t_token, TOKEN_CCURLY); scope_leave(parser->scope); |