aboutsummaryrefslogtreecommitdiff
path: root/src/parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.cpp')
-rw-r--r--src/parser.cpp38
1 files changed, 34 insertions, 4 deletions
diff --git a/src/parser.cpp b/src/parser.cpp
index 893ce9891..9e684028d 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -685,6 +685,21 @@ Ast *ast_ternary_when_expr(AstFile *f, Ast *x, Ast *cond, Ast *y) {
return result;
}
+Ast *ast_or_else_expr(AstFile *f, Ast *x, Token const &token, Ast *y) {
+ Ast *result = alloc_ast_node(f, Ast_OrElseExpr);
+ result->OrElseExpr.x = x;
+ result->OrElseExpr.token = token;
+ result->OrElseExpr.y = y;
+ return result;
+}
+
+Ast *ast_or_return_expr(AstFile *f, Ast *expr, Token const &token) {
+ Ast *result = alloc_ast_node(f, Ast_OrReturnExpr);
+ result->OrReturnExpr.expr = expr;
+ result->OrReturnExpr.token = token;
+ return result;
+}
+
Ast *ast_type_assertion(AstFile *f, Ast *expr, Token dot, Ast *type) {
Ast *result = alloc_ast_node(f, Ast_TypeAssertion);
result->TypeAssertion.expr = expr;
@@ -1340,6 +1355,8 @@ Token expect_operator(AstFile *f) {
// okay
} else if (prev.kind == Token_if || prev.kind == Token_when) {
// okay
+ } else if (prev.kind == Token_or_else || prev.kind == Token_or_return) {
+ // okay
} else if (!gb_is_between(prev.kind, Token__OperatorBegin+1, Token__OperatorEnd-1)) {
String p = token_to_string(prev);
syntax_error(f->curr_token, "Expected an operator, got '%.*s'",
@@ -2870,6 +2887,8 @@ i32 token_precedence(AstFile *f, TokenKind t) {
case Token_Question:
case Token_if:
case Token_when:
+ case Token_or_else:
+ case Token_or_return:
return 1;
case Token_Ellipsis:
case Token_RangeFull:
@@ -2924,14 +2943,18 @@ Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
// NOTE(bill): This will also catch operators that are not valid "binary" operators
break;
}
- if (op.kind == Token_if || op.kind == Token_when) {
- Token prev = f->prev_token;
+ Token prev = f->prev_token;
+ switch (op.kind) {
+ case Token_if:
+ case Token_when:
+ case Token_or_else:
+ case Token_or_return:
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
- break;
+ goto loop_end;
}
+ break;
}
-
expect_operator(f); // NOTE(bill): error checks too
if (op.kind == Token_Question) {
@@ -2955,6 +2978,12 @@ Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
Token tok_else = expect_token(f, Token_else);
Ast *y = parse_expr(f, lhs);
expr = ast_ternary_when_expr(f, x, cond, y);
+ } else if (op.kind == Token_or_else) {
+ Ast *x = expr;
+ Ast *y = parse_expr(f, lhs);
+ expr = ast_or_else_expr(f, x, op, y);
+ } else if (op.kind == Token_or_return) {
+ expr = ast_or_return_expr(f, expr, op);
} else {
Ast *right = parse_binary_expr(f, false, prec+1);
if (right == nullptr) {
@@ -2965,6 +2994,7 @@ Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
lhs = false;
}
+ loop_end:;
}
return expr;
}