#include "ctx.h" #include bool parse_if(struct ivy_parser *parser, struct ivy_ast_node **out) { if (!parse_keyword(parser, IVY_KW_IF)) { parse_trace(parser, "expected `if` keyword"); return false; } struct ivy_ast_cond_group_node *cond_group = create_node(IVY_AST_COND_GROUP); struct ivy_ast_cond_node *cond = create_node(IVY_AST_COND); if (!parse_expr(parser, EXPR_PARSE_STOP_LEFT_BRACKET, &cond->n_cond)) { parse_trace(parser, "invalid if predicate"); return false; } if (!parse_block(parser, &cond->n_body)) { parse_trace(parser, "invalid if body"); return false; } fx_queue_push_back(&cond_group->n_branches, &cond->n_base.n_entry); bool ok = true; while (1) { struct ivy_ast_node *branch_pred = NULL; struct ivy_ast_node *branch_block = NULL; if (parse_keyword(parser, IVY_KW_ELIF)) { if (!parse_expr( parser, EXPR_PARSE_STOP_LEFT_BRACKET, &branch_pred)) { parse_trace( parser, "invalid elif branch predicate"); ok = false; break; } } else if (!parse_keyword(parser, IVY_KW_ELSE)) { break; } if (!parse_block(parser, &branch_block)) { parse_trace(parser, "invalid branch body"); ok = false; break; } struct ivy_ast_cond_node *cond = create_node(IVY_AST_COND); cond->n_cond = branch_pred; cond->n_body = branch_block; fx_queue_push_back(&cond_group->n_branches, &cond->n_base.n_entry); if (!branch_pred) { break; } } *out = generic_node(cond_group); return true; } bool parse_if_inline( struct ivy_parser *parser, struct ivy_ast_node *body, struct ivy_ast_node **out) { if (!parse_keyword(parser, IVY_KW_IF)) { parse_trace(parser, "expected `if` keyword"); return false; } struct ivy_ast_cond_group_node *cond_group = create_node(IVY_AST_COND_GROUP); struct ivy_ast_cond_node *cond = create_node(IVY_AST_COND); cond->n_body = body; if (!parse_expr(parser, EXPR_PARSE_NORMAL, &cond->n_cond)) { parse_trace(parser, "invalid if predicate"); return false; } fx_queue_push_back(&cond_group->n_branches, &cond->n_base.n_entry); if (parse_keyword(parser, IVY_KW_ELSE)) { struct ivy_ast_cond_node *cond = create_node(IVY_AST_COND); if (!parse_expr(parser, EXPR_PARSE_NORMAL, &cond->n_body)) { parse_trace(parser, "invalid else body"); return false; } fx_queue_push_back(&cond_group->n_branches, &cond->n_base.n_entry); } *out = generic_node(cond_group); return true; }