diff --git a/mie/dialect/cf/op/br-cond.c b/mie/dialect/cf/op/br-cond.c index 960a335..98a7b48 100644 --- a/mie/dialect/cf/op/br-cond.c +++ b/mie/dialect/cf/op/br-cond.c @@ -1,8 +1,10 @@ +#include #include #include #include #include #include +#include #include static enum mie_status print(struct mie_printer *printer, const struct mie_op *op) @@ -29,8 +31,104 @@ static enum mie_status print(struct mie_printer *printer, const struct mie_op *o return MIE_SUCCESS; } -static enum mie_status parse(struct mie_parser *parser, struct mie_op *out) +static bool parse_successor(struct mie_parser *ctx, struct mie_op_successor *out) { + memset(out, 0x0, sizeof *out); + b_string *str = mie_parser_get_tempstr(ctx); + bool result = false; + + if (!mie_parser_parse_blockname(ctx, str, &out->s_name_span)) { + mie_parser_report_unexpected_token( + ctx, MIE_TOK_BLOCKNAME, "branch destination"); + return false; + } + + out->s_block_name = b_string_steal(str); + + if (mie_parser_peek_type(ctx) == MIE_TOK_LINEFEED + || mie_parser_peek_symbol(ctx) == MIE_SYM_COMMA) { + goto ok; + } + + if (!mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_PAREN)) { + struct mie_parser_item expected[] = { + MIE_PARSE_ITEM_TOKEN(MIE_SYM_COMMA), + MIE_PARSE_ITEM_TOKEN(MIE_SYM_LEFT_PAREN), + MIE_PARSE_ITEM_TOKEN(MIE_TOK_LINEFEED), + MIE_PARSE_ITEM_NONE, + }; + + mie_parser_report_unexpected_token_v( + ctx, expected, "branch destination/arguments"); + goto fail; + } + + if (!mie_parser_parse_parameter_list( + ctx, true, MIE_VECTOR_REF(out->s_args), + "branch successor arguments")) { + goto fail; + } + + if (!mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_PAREN)) { + mie_parser_report_unexpected_token( + ctx, MIE_SYM_RIGHT_PAREN, "branch arguments"); + goto fail; + } + +ok: + return true; + +fail: + if (out->s_block_name) { + free(out->s_block_name); + out->s_block_name = NULL; + } + + if (MIE_VECTOR_MAX(out->s_args) > 0) { + mie_vector_destroy(out->s_args, NULL); + } + + return false; +} + +static enum mie_status parse( + struct mie_parser *parser, struct mie_parser_scope *scope, + struct mie_op *out) +{ + struct mie_op_arg *cond = mie_op_add_arg(out); + struct mie_file_span span; + if (!mie_parser_parse_parameter( + parser, false, cond, "branch condition")) { + return MIE_ERR_BAD_SYNTAX; + } + + if (!mie_parser_parse_symbol(parser, MIE_SYM_COMMA)) { + mie_parser_report_unexpected_token( + parser, MIE_SYM_COMMA, "branch destination list"); + return MIE_ERR_BAD_SYNTAX; + } + + struct mie_op_successor *true_branch + = mie_vector_emplace_back(out->op_successors, NULL); + if (!parse_successor(parser, true_branch)) { + return MIE_ERR_BAD_SYNTAX; + } + + if (!mie_parser_parse_symbol(parser, MIE_SYM_COMMA)) { + mie_parser_report_unexpected_token( + parser, MIE_SYM_COMMA, "branch destination list"); + return MIE_ERR_BAD_SYNTAX; + } + + struct mie_op_successor *false_branch + = mie_vector_emplace_back(out->op_successors, NULL); + if (!parse_successor(parser, false_branch)) { + return MIE_ERR_BAD_SYNTAX; + } + + cond->arg_unresolved.reg_type + = mie_ctx_get_int_type(mie_parser_get_mie_ctx(parser), 1); + return MIE_SUCCESS; } diff --git a/mie/dialect/cf/op/br.c b/mie/dialect/cf/op/br.c index a61f23d..2101e81 100644 --- a/mie/dialect/cf/op/br.c +++ b/mie/dialect/cf/op/br.c @@ -4,6 +4,7 @@ #include #include #include +#include #include static enum mie_status print(struct mie_printer *printer, const struct mie_op *op) @@ -16,8 +17,78 @@ static enum mie_status print(struct mie_printer *printer, const struct mie_op *o return MIE_SUCCESS; } -static enum mie_status parse(struct mie_parser *parser, struct mie_op *out) +static bool parse_successor(struct mie_parser *ctx, struct mie_op_successor *out) { + memset(out, 0x0, sizeof *out); + b_string *str = mie_parser_get_tempstr(ctx); + bool result = false; + + if (!mie_parser_parse_blockname(ctx, str, &out->s_name_span)) { + mie_parser_report_unexpected_token( + ctx, MIE_TOK_BLOCKNAME, "branch destination"); + return false; + } + + out->s_block_name = b_string_steal(str); + + if (mie_parser_peek_type(ctx) == MIE_TOK_LINEFEED) { + goto ok; + } + + if (!mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_PAREN)) { + struct mie_parser_item expected[] = { + MIE_PARSE_ITEM_TOKEN(MIE_TOK_LINEFEED), + MIE_PARSE_ITEM_TOKEN(MIE_SYM_LEFT_PAREN), + MIE_PARSE_ITEM_NONE, + }; + + mie_parser_report_unexpected_token_v( + ctx, expected, "branch destination/arguments"); + goto fail; + } + + if (!mie_parser_parse_parameter_list( + ctx, true, MIE_VECTOR_REF(out->s_args), + "branch successor arguments")) { + goto fail; + } + + if (!mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_PAREN)) { + mie_parser_report_unexpected_token( + ctx, MIE_SYM_RIGHT_PAREN, "branch arguments"); + goto fail; + } + +ok: + return true; + +fail: + if (out->s_block_name) { + free(out->s_block_name); + out->s_block_name = NULL; + } + + if (MIE_VECTOR_MAX(out->s_args) > 0) { + mie_vector_destroy(out->s_args, NULL); + } + + return false; +} + +static enum mie_status parse( + struct mie_parser *parser, struct mie_parser_scope *scope, + struct mie_op *out) +{ + struct mie_op_successor *s + = mie_vector_emplace_back(out->op_successors, NULL); + if (!s) { + return MIE_ERR_NO_MEMORY; + } + + if (!parse_successor(parser, s)) { + return MIE_ERR_BAD_SYNTAX; + } + return MIE_SUCCESS; }