summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarlos Maniero <carlos@maniero.me>2023-05-10 00:20:01 -0300
committerCarlos Maniero <carlos@maniero.me>2023-05-10 12:15:59 -0300
commit3065f54e3a122dd3d8c2deffdec72ec48ea4f165 (patch)
treebe0722fc9c6b28d2c68e5fdd3c35da8247e225c8 /src
parent5de2e1fd9f426348127a66d2c51c300cb90cc3a4 (diff)
parser: Fixes boolean binary operation precedence
The comparators && and || should have precedence over others comparators (> < >= <= == !=). Signed-off-by: Carlos Maniero <carlos@maniero.me>
Diffstat (limited to 'src')
-rw-r--r--src/parser.c48
1 files changed, 41 insertions, 7 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);
/**
*
- * <expression> ::= <comparison>
- * <comparison> ::= <arithmetic1> (('>' | '>=' | '=' | ...) arithmetic1)*
+ * <expression> ::= <comparison1>
+ * <comparison1> ::= <comparison2> (('>' | '>=' | '=' | ...) comparison2)*
+ * <comparison2> ::= <arithmetic1> (('>' | '>=' | '=' | ...) arithmetic1)*
* <arithmetic1> ::= <arithmetic2> (('+' | '-') arithmetic2)*
* <arithmetic2> ::= <factor> (('*' | '/') factor)*
* <factor> ::= <integer> | '(' <expression> ')'
@@ -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;