From 3065f54e3a122dd3d8c2deffdec72ec48ea4f165 Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Wed, 10 May 2023 00:20:01 -0300 Subject: parser: Fixes boolean binary operation precedence The comparators && and || should have precedence over others comparators (> < >= <= == !=). Signed-off-by: Carlos Maniero --- src/parser.c | 48 +++++++++++++++++++++++++++++++++++++++++------- test/parser_test.c | 18 +++++++++--------- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/src/parser.c b/src/parser.c index 9167f1e..e3f157f 100644 --- a/src/parser.c +++ b/src/parser.c @@ -156,7 +156,10 @@ ast_node_t * parser_parse_expression(parser_t *parser); static ast_node_t * -parser_parse_comparison(parser_t *parser); +parser_parse_comparison1(parser_t *parser); + +static ast_node_t * +parser_parse_comparison2(parser_t *parser); static ast_node_t * parser_parse_arithmetic1(parser_t *parser); @@ -169,8 +172,9 @@ parser_parse_factor(parser_t *parser); /** * - * ::= - * ::= (('>' | '>=' | '=' | ...) arithmetic1)* + * ::= + * ::= (('>' | '>=' | '=' | ...) comparison2)* + * ::= (('>' | '>=' | '=' | ...) arithmetic1)* * ::= (('+' | '-') arithmetic2)* * ::= (('*' | '/') factor)* * ::= | '(' ')' @@ -179,11 +183,42 @@ parser_parse_factor(parser_t *parser); ast_node_t * parser_parse_expression(parser_t *parser) { - return parser_parse_comparison(parser); + return parser_parse_comparison1(parser); +} + +static ast_node_t * +parser_parse_comparison1(parser_t *parser) +{ + ast_node_t *node = parser_parse_comparison2(parser); + + if (node == NULL) { + return NULL; + } + + token_t token; + lexer_peek_next_token(parser->lexer, &token); + + while (token.kind == TOKEN_AND || token.kind == TOKEN_OR) { + lexer_drop_next_token(parser->lexer); + + ast_node_t *left = node; + ast_node_t *right = parser_parse_comparison2(parser); + + if (right == NULL) { + ast_node_destroy(node); + return NULL; + } + + node = ast_node_new_binary_operation(token_to_binary_operation_kind(&token), left, right, TYPE_BOOL); + + lexer_peek_next_token(parser->lexer, &token); + } + + return node; } static ast_node_t * -parser_parse_comparison(parser_t *parser) +parser_parse_comparison2(parser_t *parser) { ast_node_t *node = parser_parse_arithmetic1(parser); @@ -195,8 +230,7 @@ parser_parse_comparison(parser_t *parser) lexer_peek_next_token(parser->lexer, &token); while (token.kind == TOKEN_GT || token.kind == TOKEN_LT || token.kind == TOKEN_GT_EQUAL || - token.kind == TOKEN_LT_EQUAL || token.kind == TOKEN_EQUAL || token.kind == TOKEN_NOT_EQUAL || - token.kind == TOKEN_AND || token.kind == TOKEN_OR) { + token.kind == TOKEN_LT_EQUAL || token.kind == TOKEN_EQUAL || token.kind == TOKEN_NOT_EQUAL) { lexer_drop_next_token(parser->lexer); ast_node_t *left = node; diff --git a/test/parser_test.c b/test/parser_test.c index 43eb27b..8565dc8 100644 --- a/test/parser_test.c +++ b/test/parser_test.c @@ -320,35 +320,35 @@ test_parse_all_boolean_expression(const MunitParameter params[], void *user_data ast_node_t *exp1 = ast_expression; assert_int(TYPE_BOOL, ==, exp1->result_type); - assert_int(AST_BINOP_NOT_EQUAL, ==, exp1->data.binary_operation.kind); + assert_int(AST_BINOP_AND, ==, exp1->data.binary_operation.kind); ast_node_t *exp2 = exp1->data.binary_operation.left; assert_int(TYPE_BOOL, ==, exp2->result_type); - assert_int(AST_BINOP_EQUAL, ==, exp2->data.binary_operation.kind); + assert_int(AST_BINOP_OR, ==, exp2->data.binary_operation.kind); - ast_node_t *exp3 = exp2->data.binary_operation.left; + ast_node_t *exp3 = exp1->data.binary_operation.right; assert_int(TYPE_BOOL, ==, exp3->result_type); - assert_int(AST_BINOP_LT_EQUAL, ==, exp3->data.binary_operation.kind); + assert_int(AST_BINOP_NOT_EQUAL, ==, exp3->data.binary_operation.kind); ast_node_t *exp4 = exp3->data.binary_operation.left; assert_int(TYPE_BOOL, ==, exp4->result_type); - assert_int(AST_BINOP_GT_EQUAL, ==, exp4->data.binary_operation.kind); + assert_int(AST_BINOP_EQUAL, ==, exp4->data.binary_operation.kind); ast_node_t *exp5 = exp4->data.binary_operation.left; assert_int(TYPE_BOOL, ==, exp5->result_type); - assert_int(AST_BINOP_LT, ==, exp5->data.binary_operation.kind); + assert_int(AST_BINOP_LT_EQUAL, ==, exp5->data.binary_operation.kind); ast_node_t *exp6 = exp5->data.binary_operation.left; assert_int(TYPE_BOOL, ==, exp6->result_type); - assert_int(AST_BINOP_GT, ==, exp6->data.binary_operation.kind); + assert_int(AST_BINOP_GT_EQUAL, ==, exp6->data.binary_operation.kind); ast_node_t *exp7 = exp6->data.binary_operation.left; assert_int(TYPE_BOOL, ==, exp7->result_type); - assert_int(AST_BINOP_AND, ==, exp7->data.binary_operation.kind); + assert_int(AST_BINOP_LT, ==, exp7->data.binary_operation.kind); ast_node_t *exp8 = exp7->data.binary_operation.left; assert_int(TYPE_BOOL, ==, exp8->result_type); - assert_int(AST_BINOP_OR, ==, exp8->data.binary_operation.kind); + assert_int(AST_BINOP_GT, ==, exp8->data.binary_operation.kind); ast_node_destroy(ast_expression); scope_destroy(scope); -- cgit v1.2.3