Files
mie/mie/parse/parse.c

1281 lines
28 KiB
C
Raw Normal View History

#include <mie/ctx.h>
#include <mie/dialect/arith.h>
#include <mie/dialect/dialect.h>
#include <mie/ir/block.h>
#include <mie/ir/module.h>
#include <mie/ir/op.h>
#include <mie/ir/region.h>
#include <mie/ir/register.h>
#include <mie/parse/lex.h>
#include <mie/parse/parse.h>
#include <mie/parse/token.h>
#include <mie/type/function.h>
#include <mie/type/type-definition.h>
#include <mie/vector.h>
struct mie_parser {
struct mie_ctx *p_ctx;
struct mie_lex *p_lex;
enum mie_status p_status;
b_string *s_tmp;
};
static b_string *get_temp_string(struct mie_parser *parser)
{
b_string_clear(parser->s_tmp);
return parser->s_tmp;
}
struct mie_parser *mie_parser_create(struct mie_ctx *ctx, struct mie_lex *lex)
{
struct mie_parser *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
out->s_tmp = b_string_create();
if (!out->s_tmp) {
free(out);
return NULL;
}
out->p_ctx = ctx;
out->p_lex = lex;
out->p_status = MIE_SUCCESS;
return out;
}
void mie_parser_destroy(struct mie_parser *ctx)
{
if (ctx->s_tmp) {
b_string_unref(ctx->s_tmp);
}
free(ctx);
}
enum mie_status mie_parser_get_status(const struct mie_parser *ctx)
{
return ctx->p_status;
}
struct mie_token *mie_parser_peek(struct mie_parser *ctx)
{
return mie_lex_peek(ctx->p_lex);
}
enum mie_token_type mie_parser_peek_type(struct mie_parser *ctx)
{
return MIE_TOKEN_TYPE(mie_lex_peek(ctx->p_lex));
}
enum mie_token_symbol mie_parser_peek_symbol(struct mie_parser *ctx)
{
struct mie_token *tok = mie_lex_peek(ctx->p_lex);
if (MIE_TOKEN_TYPE(tok) != MIE_TOK_SYMBOL) {
return MIE_SYM_NONE;
}
return tok->tok_sym;
}
bool mie_parser_check_eof(struct mie_parser *ctx)
{
return mie_lex_peek(ctx->p_lex) == NULL;
}
bool mie_parser_check_type(struct mie_parser *ctx, enum mie_token_type type)
{
return MIE_TOKEN_IS(mie_lex_peek(ctx->p_lex), type);
}
bool mie_parser_check_symbol(struct mie_parser *ctx, enum mie_token_symbol sym)
{
return MIE_TOKEN_IS_SYMBOL(mie_lex_peek(ctx->p_lex), sym);
}
bool mie_parser_advance(struct mie_parser *ctx)
{
mie_lex_advance(ctx->p_lex);
return mie_lex_get_status(ctx->p_lex) == MIE_SUCCESS;
}
bool mie_parser_parse_int(
struct mie_parser *ctx, long long *out, struct mie_file_span *loc)
{
if (!mie_parser_check_type(ctx, MIE_TOK_INT)) {
return false;
}
struct mie_token *tok = mie_lex_peek(ctx->p_lex);
if (tok->tok_value_type != MIE_TOK_V_INT) {
return false;
}
if (loc) {
mie_file_span_init(loc, tok);
}
*out = tok->tok_int;
mie_lex_advance(ctx->p_lex);
return true;
}
bool mie_parser_parse_float(
struct mie_parser *ctx, double *out, struct mie_file_span *loc)
{
if (!mie_parser_check_type(ctx, MIE_TOK_FLOAT)) {
return false;
}
struct mie_token *tok = mie_lex_peek(ctx->p_lex);
if (tok->tok_value_type != MIE_TOK_V_FLOAT) {
return false;
}
if (loc) {
mie_file_span_init(loc, tok);
}
*out = tok->tok_float;
mie_lex_advance(ctx->p_lex);
return true;
}
#define TOKEN_PARSER(name, id) \
bool mie_parser_parse_##name( \
struct mie_parser *ctx, b_string *out, struct mie_file_span *loc) \
{ \
if (!mie_parser_check_type(ctx, id)) { \
return false; \
} \
struct mie_token *tok = mie_lex_peek(ctx->p_lex); \
switch (tok->tok_value_type) { \
case MIE_TOK_V_STRING: \
b_string_append_cstr(out, tok->tok_str); \
break; \
case MIE_TOK_V_INT: \
b_string_append_cstrf(out, "%lld", tok->tok_int); \
break; \
default: \
return false; \
} \
if (loc) { \
mie_file_span_init(loc, tok); \
} \
mie_lex_advance(ctx->p_lex); \
return true; \
}
TOKEN_PARSER(word, MIE_TOK_WORD);
TOKEN_PARSER(instname, MIE_TOK_INSTNAME);
TOKEN_PARSER(graphname, MIE_TOK_GRAPHNAME);
TOKEN_PARSER(opname, MIE_TOK_OPNAME);
TOKEN_PARSER(vregname, MIE_TOK_VREGNAME);
TOKEN_PARSER(mregname, MIE_TOK_MREGNAME);
TOKEN_PARSER(blockname, MIE_TOK_BLOCKNAME);
TOKEN_PARSER(typename, MIE_TOK_TYPENAME);
TOKEN_PARSER(symname, MIE_TOK_SYMNAME);
TOKEN_PARSER(string, MIE_TOK_STRING);
bool mie_parser_parse_symbol(struct mie_parser *ctx, enum mie_token_symbol sym)
{
struct mie_token *tok = mie_lex_peek(ctx->p_lex);
if (!MIE_TOKEN_IS_SYMBOL(tok, sym)) {
return false;
}
mie_lex_advance(ctx->p_lex);
return true;
}
bool mie_parser_parse_linefeed(struct mie_parser *ctx)
{
struct mie_token *tok = mie_lex_peek(ctx->p_lex);
if (tok->tok_type != MIE_TOK_LINEFEED) {
return false;
}
mie_lex_advance(ctx->p_lex);
return true;
}
static bool parse_builtin_type_name(
struct mie_parser *ctx, const struct mie_type **out)
{
b_string *name = get_temp_string(ctx);
struct mie_file_span loc;
if (!mie_parser_parse_word(ctx, name, &loc)) {
return false;
}
const struct mie_type_definition *type_info = NULL;
const struct mie_type *type = NULL;
size_t width = 0;
char tmp = 0;
enum {
NONE = 0,
INT,
FLOAT
} base_type = NONE;
const char *name_cstr = b_string_ptr(name);
if (!strcmp(name_cstr, "memref")) {
type_info = mie_ctx_get_type_definition(
ctx->p_ctx, "memref", "memref");
} else if (!strcmp(name_cstr, "index")) {
type_info = mie_ctx_get_type_definition(
ctx->p_ctx, "index", "index");
} else if (!strcmp(name_cstr, "str")) {
type_info = mie_ctx_get_type_definition(
ctx->p_ctx, "builtin", "string");
} else if (sscanf(name_cstr, "i%zu%c", &width, &tmp) == 1) {
type_info = mie_ctx_get_type_definition(
ctx->p_ctx, "arith", "int");
base_type = INT;
} else if (sscanf(name_cstr, "f%zu%c", &width, &tmp) == 1) {
type_info = mie_ctx_get_type_definition(
ctx->p_ctx, "arith", "float");
base_type = FLOAT;
}
if (!type_info) {
return false;
}
switch (base_type) {
case INT:
type = mie_arith_int_get_type(ctx->p_ctx, width);
break;
case FLOAT:
type = mie_arith_float_get_type(ctx->p_ctx, width);
break;
default:
type = mie_ctx_get_type(
ctx->p_ctx, type_info->ty_parent->d_name,
type_info->ty_name);
break;
}
*out = type;
return type != NULL;
}
static bool parse_type_name(struct mie_parser *ctx, const struct mie_type **out)
{
b_string *name = get_temp_string(ctx);
struct mie_file_span loc;
if (!mie_parser_parse_typename(ctx, name, &loc)) {
return false;
}
*out = NULL;
return false;
}
static bool parse_composite_type(struct mie_parser *ctx, const struct mie_type **out)
{
const struct mie_type *temp = NULL;
MIE_VECTOR_DEFINE(const struct mie_type *, type_list_1);
MIE_VECTOR_DEFINE(const struct mie_type *, type_list_2);
if (!mie_parser_parse_type_list(ctx, MIE_VECTOR_REF(type_list_1))) {
return false;
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_HYPHEN_RIGHT_ANGLE)) {
*out = mie_ctx_get_storage_type(
ctx->p_ctx, type_list_1.items, type_list_1.count);
return *out != NULL;
}
bool ok = false;
if (mie_parser_peek_symbol(ctx) == MIE_SYM_LEFT_PAREN) {
ok = mie_parser_parse_type_list(ctx, MIE_VECTOR_REF(type_list_2));
} else {
ok = mie_parser_parse_type(ctx, &temp);
if (temp) {
mie_vector_push_back(type_list_2, &temp);
}
}
if (!ok) {
mie_vector_destroy(type_list_1, NULL);
mie_vector_destroy(type_list_2, NULL);
return false;
}
temp = mie_ctx_get_function_type(
ctx->p_ctx, type_list_1.items, type_list_1.count,
type_list_2.items, type_list_2.count);
mie_vector_destroy(type_list_1, NULL);
mie_vector_destroy(type_list_2, NULL);
*out = temp;
return temp != NULL;
}
bool mie_parser_parse_type(struct mie_parser *ctx, const struct mie_type **out)
{
if (mie_parser_peek_symbol(ctx) == MIE_SYM_LEFT_PAREN) {
return parse_composite_type(ctx, out);
}
switch (mie_parser_peek_type(ctx)) {
case MIE_TOK_WORD:
return parse_builtin_type_name(ctx, out);
case MIE_TOK_TYPENAME:
return parse_type_name(ctx, out);
default:
return false;
}
}
bool mie_parser_parse_type_list(
struct mie_parser *ctx, MIE_VECTOR_REF_PARAM(const struct mie_type *, out))
{
bool ok = false;
const struct mie_type **type_slot = NULL;
if (!mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_PAREN)) {
return false;
}
if (mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_PAREN)) {
/* empty type list */
return true;
}
type_slot = mie_vector_ref_emplace_back(out);
if (!type_slot) {
return false;
}
if (!mie_parser_parse_type(ctx, type_slot)) {
mie_vector_ref_pop_back(out);
return false;
}
while (1) {
if (!mie_parser_parse_symbol(ctx, MIE_SYM_COMMA)) {
break;
}
type_slot = mie_vector_ref_emplace_back(out);
if (!type_slot) {
return false;
}
if (!mie_parser_parse_type(ctx, type_slot)) {
mie_vector_ref_pop_back(out);
return false;
}
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_PAREN)) {
return false;
}
return true;
}
MIE_API bool mie_parser_parse_function_type(
struct mie_parser *ctx, struct mie_type **out)
{
const struct mie_type *type = NULL;
MIE_VECTOR_DEFINE(const struct mie_type *, in_parts);
MIE_VECTOR_DEFINE(const struct mie_type *, out_parts);
if (!mie_parser_parse_type_list(ctx, MIE_VECTOR_REF(in_parts))) {
return false;
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_HYPHEN_RIGHT_ANGLE)) {
mie_vector_destroy(in_parts, NULL);
mie_vector_destroy(out_parts, NULL);
return false;
}
bool ok = false;
if (mie_parser_peek_symbol(ctx) == MIE_SYM_LEFT_PAREN) {
ok = mie_parser_parse_type_list(ctx, MIE_VECTOR_REF(out_parts));
} else {
ok = mie_parser_parse_type(ctx, &type);
if (type) {
mie_vector_push_back(out_parts, &type);
}
}
if (!ok) {
mie_vector_destroy(in_parts, NULL);
mie_vector_destroy(out_parts, NULL);
return false;
}
type = mie_ctx_get_function_type(
ctx->p_ctx, in_parts.items, in_parts.count, out_parts.items,
out_parts.count);
mie_vector_destroy(in_parts, NULL);
mie_vector_destroy(out_parts, NULL);
*out = (struct mie_type *)type;
return type != NULL;
}
bool mie_parser_parse_operand(struct mie_parser *ctx, struct mie_op_arg *out)
{
memset(out, 0x0, sizeof *out);
b_string *str = get_temp_string(ctx);
bool result = false;
struct mie_file_span loc;
if (mie_parser_parse_vregname(ctx, str, &loc)) {
out->arg_unresolved.reg_name = b_string_steal(str);
out->arg_unresolved.reg_flags = MIE_REGISTER_F_VIRTUAL;
result = true;
} else if (mie_parser_parse_mregname(ctx, str, &loc)) {
out->arg_unresolved.reg_name = b_string_steal(str);
out->arg_unresolved.reg_flags = MIE_REGISTER_F_MACHINE;
result = true;
}
return result;
}
bool mie_parser_parse_operand_list(
struct mie_parser *ctx, MIE_VECTOR_REF_PARAM(struct mie_op_arg, out))
{
bool ok = false;
struct mie_op_arg *operand = NULL;
struct mie_token *tok = mie_parser_peek(ctx);
enum mie_token_type type = MIE_TOKEN_TYPE(tok);
if (type != MIE_TOK_VREGNAME && type != MIE_TOK_MREGNAME) {
return false;
}
operand = mie_vector_ref_emplace_back(out);
if (!operand) {
return false;
}
if (!mie_parser_parse_operand(ctx, operand)) {
return false;
}
while (1) {
tok = mie_parser_peek(ctx);
if (!MIE_TOKEN_IS_SYMBOL(tok, MIE_SYM_COMMA)) {
break;
}
mie_parser_advance(ctx);
tok = mie_parser_peek(ctx);
type = MIE_TOKEN_TYPE(tok);
if (type != MIE_TOK_VREGNAME && type != MIE_TOK_MREGNAME) {
return false;
}
operand = mie_vector_ref_emplace_back(out);
if (!operand) {
return false;
}
if (!mie_parser_parse_operand(ctx, operand)) {
return false;
}
}
return true;
}
bool mie_parser_parse_parameter(struct mie_parser *ctx, struct mie_op_arg *out)
{
memset(out, 0x0, sizeof *out);
b_string *str = get_temp_string(ctx);
struct mie_file_span loc;
if (mie_parser_parse_vregname(ctx, str, &loc)) {
out->arg_unresolved.reg_name = b_string_steal(str);
out->arg_unresolved.reg_flags = MIE_REGISTER_F_VIRTUAL;
} else if (mie_parser_parse_mregname(ctx, str, &loc)) {
out->arg_unresolved.reg_name = b_string_steal(str);
out->arg_unresolved.reg_flags = MIE_REGISTER_F_MACHINE;
} else {
return false;
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_COLON)) {
return false;
}
if (!mie_parser_parse_type(ctx, &out->arg_unresolved.reg_type)) {
return false;
}
return true;
}
bool mie_parser_parse_parameter_list(
struct mie_parser *ctx, MIE_VECTOR_REF_PARAM(struct mie_op_arg, out))
{
bool ok = false;
struct mie_op_arg *operand = NULL;
struct mie_token *tok = mie_parser_peek(ctx);
enum mie_token_type type = MIE_TOKEN_TYPE(tok);
if (type != MIE_TOK_VREGNAME && type != MIE_TOK_MREGNAME) {
return false;
}
operand = mie_vector_ref_emplace_back(out);
if (!operand) {
return false;
}
if (!mie_parser_parse_parameter(ctx, operand)) {
return false;
}
while (1) {
tok = mie_parser_peek(ctx);
if (!MIE_TOKEN_IS_SYMBOL(tok, MIE_SYM_COMMA)) {
break;
}
mie_parser_advance(ctx);
tok = mie_parser_peek(ctx);
type = MIE_TOKEN_TYPE(tok);
if (type != MIE_TOK_VREGNAME && type != MIE_TOK_MREGNAME) {
return false;
}
operand = mie_vector_ref_emplace_back(out);
if (!operand) {
return false;
}
if (!mie_parser_parse_parameter(ctx, operand)) {
return false;
}
}
return true;
}
bool mie_parser_parse_register(
struct mie_parser *ctx, struct mie_name_map *names, struct mie_register *out)
{
memset(out, 0x0, sizeof *out);
struct mie_token *tok = mie_parser_peek(ctx);
enum mie_token_type type = MIE_TOKEN_TYPE(tok);
switch (type) {
case MIE_TOK_VREGNAME:
out->reg_flags |= MIE_REGISTER_F_VIRTUAL;
break;
case MIE_TOK_MREGNAME:
out->reg_flags |= MIE_REGISTER_F_MACHINE;
break;
default:
return false;
}
struct mie_name *name = NULL;
b_string *tmp = get_temp_string(ctx);
switch (tok->tok_value_type) {
case MIE_TOK_V_STRING:
name = mie_name_map_put(
names, &out->reg_name, tok->tok_str, MIE_NAME_MAP_F_STRICT);
break;
case MIE_TOK_V_INT:
b_string_append_cstrf(tmp, "%lld", tok->tok_int);
name = mie_name_map_put(
names, &out->reg_name, b_string_ptr(tmp),
MIE_NAME_MAP_F_STRICT);
break;
default:
break;
}
mie_parser_advance(ctx);
return name != NULL;
}
bool mie_parser_parse_register_list(
struct mie_parser *ctx, struct mie_name_map *names,
MIE_VECTOR_REF_PARAM(struct mie_register, out))
{
bool ok = false;
struct mie_register *reg = NULL;
struct mie_token *tok = mie_parser_peek(ctx);
enum mie_token_type type = MIE_TOKEN_TYPE(tok);
if (type != MIE_TOK_VREGNAME && type != MIE_TOK_MREGNAME) {
return false;
}
reg = mie_vector_ref_emplace_back(out);
if (!reg) {
return false;
}
if (!mie_parser_parse_register(ctx, names, reg)) {
return false;
}
while (1) {
tok = mie_parser_peek(ctx);
if (!MIE_TOKEN_IS_SYMBOL(tok, MIE_SYM_COMMA)) {
break;
}
mie_parser_advance(ctx);
tok = mie_parser_peek(ctx);
type = MIE_TOKEN_TYPE(tok);
if (type != MIE_TOK_VREGNAME && type != MIE_TOK_MREGNAME) {
return false;
}
reg = mie_vector_ref_emplace_back(out);
if (!reg) {
return false;
}
if (!mie_parser_parse_register(ctx, names, reg)) {
return false;
}
}
return true;
}
bool mie_parser_parse_module(struct mie_parser *ctx, struct mie_module *mod)
{
#define OP_TOKEN_TYPES \
(MIE_TOK_NAME | MIE_TOK_OPNAME | MIE_TOK_VREGNAME | MIE_TOK_MREGNAME \
| MIE_TOK_GRAPHNAME | MIE_TOK_INSTNAME)
while (1) {
enum mie_token_type type = mie_parser_peek_type(ctx);
bool is_op = (type & OP_TOKEN_TYPES);
if (!is_op) {
break;
}
struct mie_op *op = mie_vector_emplace_back(mod->m_ops);
if (!op) {
return false;
}
if (!mie_parser_parse_op(ctx, mod->m_names, op)) {
return false;
}
}
return true;
}
bool mie_parser_parse_region(struct mie_parser *ctx, struct mie_region *region)
{
region->r_names = mie_name_map_create(NULL);
if (!mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_BRACE)) {
return false;
}
mie_parser_parse_linefeed(ctx);
struct mie_block *block = NULL;
if (mie_parser_peek_type(ctx) != MIE_TOK_BLOCKNAME) {
block = mie_vector_emplace_back(region->r_blocks);
if (!mie_parser_parse_anonymous_block(ctx, region->r_names, block)) {
return false;
}
}
while (1) {
if (mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_BRACE)) {
break;
}
block = mie_vector_emplace_back(region->r_blocks);
if (!mie_parser_parse_block(ctx, region->r_names, block)) {
return false;
}
}
return true;
}
bool mie_parser_parse_region_list(
struct mie_parser *ctx, MIE_VECTOR_REF_PARAM(struct mie_region, out))
{
if (!mie_parser_check_symbol(ctx, MIE_SYM_LEFT_BRACE)) {
return false;
}
struct mie_region *region = mie_vector_ref_emplace_back(out);
if (!mie_parser_parse_region(ctx, region)) {
return false;
}
while (1) {
if (!mie_parser_parse_symbol(ctx, MIE_SYM_COMMA)) {
break;
}
if (!mie_parser_check_symbol(ctx, MIE_SYM_LEFT_BRACE)) {
break;
}
struct mie_region *region = mie_vector_ref_emplace_back(out);
if (!mie_parser_parse_region(ctx, region)) {
return false;
}
}
return true;
}
bool mie_parser_parse_anonymous_block(
struct mie_parser *ctx, struct mie_name_map *names, struct mie_block *block)
{
mie_parser_parse_linefeed(ctx);
struct mie_op *op = mie_vector_emplace_back(block->b_ops);
if (!mie_parser_parse_op(ctx, names, op)) {
return false;
}
mie_parser_parse_linefeed(ctx);
while (1) {
if (mie_parser_peek_type(ctx) == MIE_TOK_BLOCKNAME) {
break;
}
if (mie_parser_peek_symbol(ctx) == MIE_SYM_RIGHT_BRACE) {
break;
}
struct mie_op *op = mie_vector_emplace_back(block->b_ops);
if (!mie_parser_parse_op(ctx, names, op)) {
return false;
}
if (!mie_parser_parse_linefeed(ctx)) {
return false;
}
}
return true;
}
static bool parse_block_parameters(
struct mie_parser *ctx, struct mie_name_map *names, struct mie_block *block)
{
if (!mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_PAREN)) {
return false;
}
MIE_VECTOR_DEFINE(struct mie_op_arg, block_params);
if (!mie_parser_parse_parameter_list(ctx, MIE_VECTOR_REF(block_params))) {
return false;
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_PAREN)
|| !mie_parser_parse_symbol(ctx, MIE_SYM_COLON)
|| !mie_parser_parse_linefeed(ctx)) {
mie_vector_destroy(block_params, NULL);
return false;
}
for (size_t i = 0; i < MIE_VECTOR_COUNT(block_params); i++) {
struct mie_register *param_reg
= mie_vector_emplace_back(block->b_params);
param_reg->reg_flags = block_params.items[i].arg_unresolved.reg_flags
| MIE_REGISTER_F_BLOCK_PARAM;
param_reg->reg_type = block_params.items[i].arg_unresolved.reg_type;
param_reg->reg_block = block;
if (!mie_name_map_put(
names, &param_reg->reg_name,
block_params.items[i].arg_unresolved.reg_name,
MIE_NAME_MAP_F_STRICT)) {
return false;
}
}
return true;
}
bool mie_parser_parse_block(
struct mie_parser *ctx, struct mie_name_map *names, struct mie_block *block)
{
b_string *str = get_temp_string(ctx);
struct mie_file_span span;
if (!mie_parser_parse_blockname(ctx, str, &span)) {
return false;
}
if (!mie_name_map_put(
names, &block->b_name, b_string_ptr(str),
MIE_NAME_MAP_F_STRICT)) {
return false;
}
if (mie_parser_peek_symbol(ctx) == MIE_SYM_LEFT_PAREN
&& !parse_block_parameters(ctx, names, block)) {
return false;
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_COLON)
|| !mie_parser_parse_linefeed(ctx)) {
return false;
}
while (1) {
if (mie_parser_peek_type(ctx) == MIE_TOK_BLOCKNAME) {
break;
}
if (mie_parser_peek_symbol(ctx) == MIE_SYM_RIGHT_BRACE) {
break;
}
struct mie_op *op = mie_vector_emplace_back(block->b_ops);
if (!mie_parser_parse_op(ctx, names, op)) {
return false;
}
if (!mie_parser_parse_linefeed(ctx)) {
return false;
}
}
return true;
}
bool mie_parser_parse_attribute(
struct mie_parser *ctx, struct mie_op_attribute *attrib)
{
b_string *str = get_temp_string(ctx);
struct mie_file_span span;
if (!mie_parser_parse_word(ctx, str, &span)) {
return false;
}
attrib->attrib_name = b_string_steal(str);
if (!mie_parser_parse_symbol(ctx, MIE_SYM_EQUAL)) {
return false;
}
struct mie_value *value = NULL;
if (!mie_parser_parse_value(ctx, &value)) {
return false;
}
attrib->attrib_value = value;
return true;
}
bool mie_parser_parse_attribute_list(
struct mie_parser *ctx, MIE_VECTOR_REF_PARAM(struct mie_op_attribute, out))
{
bool ok = false;
struct mie_op_attribute *attrib = NULL;
attrib = mie_vector_ref_emplace_back(out);
if (!attrib) {
return false;
}
if (!mie_parser_parse_attribute(ctx, attrib)) {
return false;
}
while (1) {
const struct mie_token *tok = mie_parser_peek(ctx);
if (!MIE_TOKEN_IS_SYMBOL(tok, MIE_SYM_COMMA)) {
break;
}
mie_parser_advance(ctx);
mie_parser_parse_linefeed(ctx);
attrib = mie_vector_ref_emplace_back(out);
if (!attrib) {
return false;
}
if (!mie_parser_parse_attribute(ctx, attrib)) {
return false;
}
}
return true;
}
bool mie_parser_parse_successor(struct mie_parser *ctx, struct mie_op_successor *out)
{
memset(out, 0x0, sizeof *out);
b_string *str = get_temp_string(ctx);
bool result = false;
struct mie_file_span span;
if (!mie_parser_parse_blockname(ctx, str, &span)) {
return false;
}
out->s_block_name = b_string_steal(str);
if (!mie_parser_parse_symbol(ctx, MIE_SYM_COLON)) {
return true;
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_PAREN)) {
goto fail;
}
if (!mie_parser_parse_parameter_list(ctx, MIE_VECTOR_REF(out->s_args))) {
goto fail;
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_PAREN)) {
goto fail;
}
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;
}
bool mie_parser_parse_successor_list(
struct mie_parser *ctx, MIE_VECTOR_REF_PARAM(struct mie_op_successor, out))
{
bool ok = false;
struct mie_op_successor *successor = NULL;
successor = mie_vector_ref_emplace_back(out);
if (!successor) {
return false;
}
if (!mie_parser_parse_successor(ctx, successor)) {
return false;
}
while (1) {
const struct mie_token *tok = mie_parser_peek(ctx);
if (!MIE_TOKEN_IS_SYMBOL(tok, MIE_SYM_COMMA)) {
break;
}
mie_parser_advance(ctx);
mie_parser_parse_linefeed(ctx);
successor = mie_vector_ref_emplace_back(out);
if (!successor) {
return false;
}
if (!mie_parser_parse_successor(ctx, successor)) {
return false;
}
}
return true;
}
static bool parse_custom_op(
struct mie_parser *ctx, struct mie_name_map *names, struct mie_op *dest)
{
return false;
}
static bool parse_generic_op(
struct mie_parser *ctx, struct mie_name_map *names, struct mie_op *dest)
{
b_string *str = get_temp_string(ctx);
struct mie_file_span loc;
if (!mie_parser_parse_opname(ctx, str, &loc)) {
return false;
}
dest->op_name = b_string_steal(str);
if (!mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_PAREN)) {
return false;
}
if (mie_parser_peek_symbol(ctx) != MIE_SYM_RIGHT_PAREN
&& !mie_parser_parse_operand_list(ctx, MIE_VECTOR_REF(dest->op_args))) {
return false;
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_PAREN)) {
return false;
}
if (mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_BRACKET)) {
mie_parser_parse_linefeed(ctx);
if (!mie_parser_parse_successor_list(
ctx, MIE_VECTOR_REF(dest->op_successors))) {
return false;
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_BRACKET)) {
return false;
}
}
if (mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_PAREN)) {
mie_parser_parse_linefeed(ctx);
if (!mie_parser_parse_region_list(
ctx, MIE_VECTOR_REF(dest->op_regions))) {
return false;
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_PAREN)) {
return false;
}
}
if (mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_BRACKET)) {
if (!mie_parser_parse_successor_list(
ctx, MIE_VECTOR_REF(dest->op_successors))) {
return false;
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_BRACKET)) {
return false;
}
}
if (mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_PAREN)) {
if (!mie_parser_parse_region_list(
ctx, MIE_VECTOR_REF(dest->op_regions))) {
return false;
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_PAREN)) {
return false;
}
}
if (mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_BRACE)) {
if (!mie_parser_parse_attribute_list(
ctx, MIE_VECTOR_REF(dest->op_attrib))) {
return false;
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_BRACE)) {
return false;
}
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_COLON)) {
return false;
}
struct mie_function_type *func_type = NULL;
if (!mie_parser_parse_function_type(ctx, (struct mie_type **)&func_type)) {
return false;
}
if (MIE_VECTOR_COUNT(func_type->func_in)
!= MIE_VECTOR_COUNT(dest->op_args)) {
return false;
}
if (MIE_VECTOR_COUNT(func_type->func_out)
!= MIE_VECTOR_COUNT(dest->op_result)) {
return false;
}
for (size_t i = 0; i < MIE_VECTOR_COUNT(func_type->func_in); i++) {
dest->op_args.items[i].arg_unresolved.reg_type
= func_type->func_in.items[i];
}
for (size_t i = 0; i < MIE_VECTOR_COUNT(func_type->func_out); i++) {
dest->op_result.items[i].reg_type = func_type->func_out.items[i];
}
return true;
}
static bool parse_graph_op(
struct mie_parser *ctx, struct mie_name_map *names, struct mie_op *dest)
{
return false;
}
bool mie_parser_parse_op(
struct mie_parser *ctx, struct mie_name_map *names, struct mie_op *dest)
{
memset(dest, 0x0, sizeof *dest);
if (mie_parser_check_eof(ctx)) {
return false;
}
if (mie_parser_check_type(ctx, MIE_TOK_MREGNAME | MIE_TOK_VREGNAME)) {
if (!mie_parser_parse_register_list(
ctx, names, MIE_VECTOR_REF(dest->op_result))) {
return false;
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_EQUAL)) {
return false;
}
}
if (mie_parser_check_type(ctx, MIE_TOK_NAME)) {
/* custom-format operation */
return parse_custom_op(ctx, names, dest);
} else if (mie_parser_check_type(ctx, MIE_TOK_OPNAME)) {
/* generic-format operation */
return parse_generic_op(ctx, names, dest);
} else if (mie_parser_check_type(ctx, MIE_TOK_GRAPHNAME)) {
/* graph-node operation */
return parse_graph_op(ctx, names, dest);
} else {
/* not sure what this is */
return false;
}
}
static bool parse_string(struct mie_parser *ctx, struct mie_value **dest)
{
b_string *str = get_temp_string(ctx);
struct mie_file_span span;
if (!mie_parser_parse_string(ctx, str, &span)) {
return false;
}
struct mie_value *v = mie_ctx_get_string(ctx->p_ctx, b_string_ptr(str));
if (!v) {
return false;
}
*dest = v;
return true;
}
static bool parse_int(struct mie_parser *ctx, struct mie_value **dest)
{
long long value = 0;
struct mie_file_span span;
if (!mie_parser_parse_int(ctx, &value, &span)) {
return false;
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_COLON)) {
return false;
}
const struct mie_type *type = NULL;
if (!mie_parser_parse_type(ctx, &type)) {
return false;
}
size_t width = mie_arith_int_type_get_width(type);
if (width == (size_t)-1) {
return false;
}
struct mie_value *v = mie_ctx_get_int(ctx->p_ctx, value, width);
if (!v) {
return false;
}
*dest = v;
return true;
}
static bool parse_float(struct mie_parser *ctx, struct mie_value **dest)
{
double value = 0;
struct mie_file_span span;
if (!mie_parser_parse_float(ctx, &value, &span)) {
return false;
}
if (!mie_parser_parse_symbol(ctx, MIE_SYM_COLON)) {
return false;
}
const struct mie_type *type = NULL;
if (!mie_parser_parse_type(ctx, &type)) {
return false;
}
size_t width = mie_arith_float_type_get_width(type);
if (width == (size_t)-1) {
return false;
}
struct mie_value *v = mie_ctx_get_float(ctx->p_ctx, value, width);
if (!v) {
return false;
}
*dest = v;
return true;
}
bool mie_parser_parse_value(struct mie_parser *ctx, struct mie_value **dest)
{
enum mie_token_type type = mie_parser_peek_type(ctx);
switch (type) {
case MIE_TOK_STRING:
return parse_string(ctx, dest);
case MIE_TOK_INT:
return parse_int(ctx, dest);
case MIE_TOK_FLOAT:
return parse_float(ctx, dest);
default:
return false;
}
}