#include "../syntax.h" static bool add_branch( struct bshell_if_ast_node *group, struct bshell_ast_node *cond, struct bshell_ast_node *body) { struct bshell_if_branch_ast_node *branch = (struct bshell_if_branch_ast_node *)bshell_ast_node_create( BSHELL_AST_IF_BRANCH); if (!branch) { return false; } branch->n_cond = cond; branch->n_body = body; fx_queue_push_back(&group->n_branches, &branch->n_base.n_entry); return true; } bool parse_if(struct bshell_parse_ctx *ctx, struct bshell_ast_node **out) { if (!parse_keyword(ctx, BSHELL_KW_IF)) { return false; } if (!parse_symbol(ctx, BSHELL_SYM_LEFT_PAREN)) { report_error(ctx, "expected `(` after `if`"); return false; } struct bshell_ast_node *if_cond = NULL, *if_body = NULL; if (!parse_expr(ctx, &if_cond)) { report_error(ctx, "invalid if condition"); return false; } if (!parse_symbol(ctx, BSHELL_SYM_RIGHT_PAREN)) { report_error(ctx, "expected `)` after if-condition"); bshell_ast_node_destroy(if_cond); return false; } if (!parse_block(ctx, &if_body)) { report_error(ctx, "invalid if body"); bshell_ast_node_destroy(if_cond); return false; } struct bshell_if_ast_node *if_group = (struct bshell_if_ast_node *)bshell_ast_node_create( BSHELL_AST_IF); if (!if_group) { ctx->p_status = BSHELL_ERR_NO_MEMORY; bshell_ast_node_destroy(if_cond); bshell_ast_node_destroy(if_body); return false; } if (!add_branch(if_group, if_cond, if_body)) { ctx->p_status = BSHELL_ERR_NO_MEMORY; bshell_ast_node_destroy(if_cond); bshell_ast_node_destroy(if_body); bshell_ast_node_destroy((struct bshell_ast_node *)if_group); return false; } bool done = false; while (!done) { struct bshell_ast_node *cond = NULL, *body = NULL; if (parse_keyword(ctx, BSHELL_KW_ELSE)) { done = true; } else if (parse_keyword(ctx, BSHELL_KW_ELSEIF)) { if (!parse_symbol(ctx, BSHELL_SYM_LEFT_PAREN)) { report_error( ctx, "expected `(` after `elseif`"); return false; } if (!parse_expr(ctx, &cond)) { report_error( ctx, "invalid conditional expression"); bshell_ast_node_destroy( (struct bshell_ast_node *)if_group); return false; } if (!parse_symbol(ctx, BSHELL_SYM_RIGHT_PAREN)) { report_error( ctx, "expected `)` after elseif-condition"); bshell_ast_node_destroy(if_cond); return false; } } else { done = true; break; } if (!parse_block(ctx, &body)) { report_error(ctx, "invalid conditional body"); if (cond) { bshell_ast_node_destroy(cond); } bshell_ast_node_destroy( (struct bshell_ast_node *)if_group); return false; } if (!add_branch(if_group, cond, body)) { report_error(ctx, "failed to add branch to if-group"); if (cond) { bshell_ast_node_destroy(cond); } bshell_ast_node_destroy(body); bshell_ast_node_destroy( (struct bshell_ast_node *)if_group); return false; } } *out = (struct bshell_ast_node *)if_group; return true; }