From d86d70fc7c6751713a6b9f02d9f77814e2f75718 Mon Sep 17 00:00:00 2001 From: Johnny Richard Date: Fri, 21 Apr 2023 15:11:17 +0200 Subject: parser: Parse integers arithmetic expression This patch implements the AST creation for arithmetic expressions. NOTE: The implementation works only for integer numbers. Signed-off-by: Johnny Richard Reviewed-by: Carlos Maniero --- src/parser.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 4 deletions(-) (limited to 'src/parser.c') diff --git a/src/parser.c b/src/parser.c index 176a4a8..ad38125 100644 --- a/src/parser.c +++ b/src/parser.c @@ -109,16 +109,20 @@ parser_literal_integer_node(ast_node_t *node, token_t *token) } bool -parser_parse_next_expression(parser_t *parser, ast_node_t *node) +parser_parse_factor(parser_t *parser, ast_node_t *node) { token_t token; lexer_next_token(parser->lexer, &token); - if (token.kind == TOKEN_NUMBER) - { + if (token.kind == TOKEN_NUMBER) { return parser_literal_integer_node(node, &token); + } else if (token.kind == TOKEN_OPAREN) { + parser_parse_expression(parser, node); + if (!drop_expected_token(parser, TOKEN_CPAREN)) return false; + return true; } + // FIXME: Extract this erros logic to a function parser_error_t error; error.token = token; sprintf( @@ -128,9 +132,75 @@ parser_parse_next_expression(parser_t *parser, ast_node_t *node) SVARG(&token.value) ); parser->errors[parser->errors_len++] = error; + return false; } +bool +parser_parse_term(parser_t *parser, ast_node_t *node) +{ + if (!parser_parse_factor(parser, node)) return false; + + token_t token; + lexer_next_token(parser->lexer, &token); + + while (token.kind == TOKEN_OP && (string_view_eq(token.value, string_view_from_str("*")) || string_view_eq(token.value, string_view_from_str("/")))) { + ast_node_t *binary_op = ast_node_new(); + binary_op->kind = AST_BINARY_OPERATION; + binary_op->data.binary_operation.op = token.value; + + binary_op->data.binary_operation.left = ast_node_new(); + *binary_op->data.binary_operation.left = *node; + + binary_op->data.binary_operation.right = ast_node_new(); + if (!parser_parse_factor(parser, binary_op->data.binary_operation.right)) return false; + + *node = *binary_op; + + lexer_next_token(parser->lexer, &token); + } + + lexer_step_back_to(parser->lexer, &token); + + return true; +} + +/** + * + * ::= (('+' | '-') term)* + * ::= (('*' | '/') factor)* + * ::= | '(' ')' + * + */ +bool +parser_parse_expression(parser_t *parser, ast_node_t *node) +{ + if (!parser_parse_term(parser, node)) return false; + + token_t token; + lexer_next_token(parser->lexer, &token); + + while (token.kind == TOKEN_OP && (string_view_eq(token.value, string_view_from_str("+")) || string_view_eq(token.value, string_view_from_str("-")))) { + + ast_node_t *binary_op = ast_node_new(); + binary_op->kind = AST_BINARY_OPERATION; + binary_op->data.binary_operation.op = token.value; + + binary_op->data.binary_operation.left = ast_node_new(); + *binary_op->data.binary_operation.left = *node; + + binary_op->data.binary_operation.right = ast_node_new(); + if (!parser_parse_term(parser, binary_op->data.binary_operation.right)) return false; + + *node = *binary_op; + lexer_next_token(parser->lexer, &token); + } + + lexer_step_back_to(parser->lexer, &token); + + return true; +} + bool parser_parse_return_stmt(parser_t *parser, ast_node_t *node) { @@ -155,7 +225,7 @@ parser_parse_return_stmt(parser_t *parser, ast_node_t *node) } ast_node_t *argument_token = ast_node_new(); - if (!parser_parse_next_expression(parser, argument_token)) return false; + if (!parser_parse_expression(parser, argument_token)) return false; if (!drop_expected_token(parser, TOKEN_SEMICOLON)) return false; if (!drop_expected_token(parser, TOKEN_CCURLY)) return false; -- cgit v1.2.3