#include "ctx.h" #include bool parse_match(struct ivy_parser *parser, struct ivy_ast_node **out) { if (!parse_keyword(parser, IVY_KW_MATCH)) { parse_trace(parser, "expected `match` keyword"); return false; } struct ivy_ast_match_node *match = create_node(IVY_AST_MATCH); if (!parse_expr(parser, EXPR_PARSE_STOP_LEFT_BRACKET, &match->n_cond)) { parse_trace(parser, "invalid match predicate"); return false; } if (!parse_symbol(parser, IVY_SYM_LEFT_BRACKET)) { parse_trace(parser, "expected `[` after match predicate"); return false; } bool ok = true; while (1) { if (parse_symbol(parser, IVY_SYM_RIGHT_BRACKET)) { break; } if (!fx_queue_empty(&match->n_branches) && !parse_symbol(parser, IVY_SYM_COMMA)) { parse_trace( parser, "expected `,` or `]` after match branch value"); ok = false; break; } struct ivy_ast_node *branch_pred = NULL; struct ivy_ast_node *branch_value = NULL; if (!parse_expr(parser, EXPR_PARSE_NORMAL, &branch_pred)) { parse_trace(parser, "invalid match branch predicate"); ok = false; break; } if (!parse_symbol(parser, IVY_SYM_EQUAL_RIGHT_ANGLE)) { parse_trace( parser, "expected `=>` after match branch predicate"); ok = false; break; } if (peek_symbol(parser, IVY_SYM_LEFT_BRACKET)) { ok = parse_block(parser, &branch_value); } else { ok = parse_expr( parser, EXPR_PARSE_STOP_COMMA, &branch_value); } if (!ok) { parse_trace(parser, "invalid match branch value"); break; } struct ivy_ast_cond_node *cond = create_node(IVY_AST_COND); cond->n_cond = branch_pred; cond->n_body = branch_value; fx_queue_push_back(&match->n_branches, &cond->n_base.n_entry); } *out = generic_node(match); return true; }