aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2022-02-22 22:53:13 +0000
committergingerBill <bill@gingerbill.org>2022-02-22 22:53:13 +0000
commitcad753e3986183fa180abae480a85432b4b36af1 (patch)
tree95993489a7c1373b70eb78bd2982e3e5cf883dd6
parente6a7b85da44e141f170a528321ce02452731a3d4 (diff)
Simplify `parse_binary_expr`
-rw-r--r--src/parser.cpp157
1 files changed, 109 insertions, 48 deletions
diff --git a/src/parser.cpp b/src/parser.cpp
index 8a7ab2d20..c214df782 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -3013,66 +3013,127 @@ i32 token_precedence(AstFile *f, TokenKind t) {
return 0;
}
+// Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
+// Ast *expr = parse_unary_expr(f, lhs);
+// for (i32 prec = token_precedence(f, f->curr_token.kind); prec >= prec_in; prec--) {
+// for (;;) {
+// Token op = f->curr_token;
+// i32 op_prec = token_precedence(f, op.kind);
+// if (op_prec != prec) {
+// // NOTE(bill): This will also catch operators that are not valid "binary" operators
+// break;
+// }
+// Token prev = f->prev_token;
+// switch (op.kind) {
+// case Token_if:
+// case Token_when:
+// if (prev.pos.line < op.pos.line) {
+// // NOTE(bill): Check to see if the `if` or `when` is on the same line of the `lhs` condition
+// goto loop_end;
+// }
+// break;
+// }
+// expect_operator(f); // NOTE(bill): error checks too
+
+// if (op.kind == Token_Question) {
+// Ast *cond = expr;
+// // Token_Question
+// Ast *x = parse_expr(f, lhs);
+// Token token_c = expect_token(f, Token_Colon);
+// Ast *y = parse_expr(f, lhs);
+// expr = ast_ternary_if_expr(f, x, cond, y);
+// } else if (op.kind == Token_if || op.kind == Token_when) {
+// Ast *x = expr;
+// Ast *cond = parse_expr(f, lhs);
+// Token tok_else = expect_token(f, Token_else);
+// Ast *y = parse_expr(f, lhs);
+
+// switch (op.kind) {
+// case Token_if:
+// expr = ast_ternary_if_expr(f, x, cond, y);
+// break;
+// case Token_when:
+// expr = ast_ternary_when_expr(f, x, cond, y);
+// break;
+// }
+// } else {
+// Ast *right = parse_binary_expr(f, false, prec+1);
+// if (right == nullptr) {
+// syntax_error(op, "Expected expression on the right-hand side of the binary operator '%.*s'", LIT(op.string));
+// }
+// if (op.kind == Token_or_else) {
+// // NOTE(bill): easier to handle its logic different with its own AST kind
+// expr = ast_or_else_expr(f, expr, op, right);
+// } else {
+// expr = ast_binary_expr(f, op, expr, right);
+// }
+// }
+
+// lhs = false;
+// }
+// loop_end:;
+// }
+// return expr;
+// }
+
Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
Ast *expr = parse_unary_expr(f, lhs);
- for (i32 prec = token_precedence(f, f->curr_token.kind); prec >= prec_in; prec--) {
- for (;;) {
- Token op = f->curr_token;
- i32 op_prec = token_precedence(f, op.kind);
- if (op_prec != prec) {
- // NOTE(bill): This will also catch operators that are not valid "binary" operators
- break;
+ for (;;) {
+ Token op = f->curr_token;
+ i32 op_prec = token_precedence(f, op.kind);
+ if (op_prec < prec_in) {
+ // NOTE(bill): This will also catch operators that are not valid "binary" operators
+ break;
+ }
+ Token prev = f->prev_token;
+ switch (op.kind) {
+ case Token_if:
+ case Token_when:
+ if (prev.pos.line < op.pos.line) {
+ // NOTE(bill): Check to see if the `if` or `when` is on the same line of the `lhs` condition
+ goto loop_end;
}
- Token prev = f->prev_token;
+ break;
+ }
+ expect_operator(f); // NOTE(bill): error checks too
+
+ if (op.kind == Token_Question) {
+ Ast *cond = expr;
+ // Token_Question
+ Ast *x = parse_expr(f, lhs);
+ Token token_c = expect_token(f, Token_Colon);
+ Ast *y = parse_expr(f, lhs);
+ expr = ast_ternary_if_expr(f, x, cond, y);
+ } else if (op.kind == Token_if || op.kind == Token_when) {
+ Ast *x = expr;
+ Ast *cond = parse_expr(f, lhs);
+ Token tok_else = expect_token(f, Token_else);
+ Ast *y = parse_expr(f, lhs);
+
switch (op.kind) {
case Token_if:
+ expr = ast_ternary_if_expr(f, x, cond, y);
+ break;
case Token_when:
- if (prev.pos.line < op.pos.line) {
- // NOTE(bill): Check to see if the `if` or `when` is on the same line of the `lhs` condition
- goto loop_end;
- }
+ expr = ast_ternary_when_expr(f, x, cond, y);
break;
}
- expect_operator(f); // NOTE(bill): error checks too
-
- if (op.kind == Token_Question) {
- Ast *cond = expr;
- // Token_Question
- Ast *x = parse_expr(f, lhs);
- Token token_c = expect_token(f, Token_Colon);
- Ast *y = parse_expr(f, lhs);
- expr = ast_ternary_if_expr(f, x, cond, y);
- } else if (op.kind == Token_if || op.kind == Token_when) {
- Ast *x = expr;
- Ast *cond = parse_expr(f, lhs);
- Token tok_else = expect_token(f, Token_else);
- Ast *y = parse_expr(f, lhs);
-
- switch (op.kind) {
- case Token_if:
- expr = ast_ternary_if_expr(f, x, cond, y);
- break;
- case Token_when:
- expr = ast_ternary_when_expr(f, x, cond, y);
- break;
- }
+ } else {
+ Ast *right = parse_binary_expr(f, false, op_prec+1);
+ if (right == nullptr) {
+ syntax_error(op, "Expected expression on the right-hand side of the binary operator '%.*s'", LIT(op.string));
+ }
+ if (op.kind == Token_or_else) {
+ // NOTE(bill): easier to handle its logic different with its own AST kind
+ expr = ast_or_else_expr(f, expr, op, right);
} else {
- Ast *right = parse_binary_expr(f, false, prec+1);
- if (right == nullptr) {
- syntax_error(op, "Expected expression on the right-hand side of the binary operator '%.*s'", LIT(op.string));
- }
- if (op.kind == Token_or_else) {
- // NOTE(bill): easier to handle its logic different with its own AST kind
- expr = ast_or_else_expr(f, expr, op, right);
- } else {
- expr = ast_binary_expr(f, op, expr, right);
- }
+ expr = ast_binary_expr(f, op, expr, right);
}
-
- lhs = false;
}
- loop_end:;
+
+ lhs = false;
}
+ loop_end:;
return expr;
}