edfb3e24a3
bshell: the front-end binary bshell.runtime: contains the parser, compiler, and classes needed to run bshell scripts bshell.core: contains the builtin commandlets and aliases
131 lines
2.9 KiB
C
131 lines
2.9 KiB
C
#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;
|
|
}
|