Files
ivy/lang/parse/if-else.c
T

100 lines
2.4 KiB
C

#include "ctx.h"
#include <ivy/lang/ast.h>
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;
}