173 lines
4.2 KiB
C
173 lines
4.2 KiB
C
|
|
#include <ivy/asm/parse.h>
|
||
|
|
#include <ivy/asm/lex.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
#include "parse.h"
|
||
|
|
|
||
|
|
extern struct parser_state_type unit_parser_state_type;
|
||
|
|
extern struct parser_state_type constpool_parser_state_type;
|
||
|
|
extern struct parser_state_type ident_parser_state_type;
|
||
|
|
extern struct parser_state_type selector_parser_state_type;
|
||
|
|
extern struct parser_state_type atom_parser_state_type;
|
||
|
|
|
||
|
|
static const struct parser_state_type *parser_state_types[] = {
|
||
|
|
[ASM_PARSER_UNIT] = &unit_parser_state_type,
|
||
|
|
[ASM_PARSER_CONSTPOOL] = &constpool_parser_state_type,
|
||
|
|
[ASM_PARSER_IDENT] = &ident_parser_state_type,
|
||
|
|
[ASM_PARSER_SELECTOR] = &selector_parser_state_type,
|
||
|
|
[ASM_PARSER_ATOM] = &atom_parser_state_type,
|
||
|
|
};
|
||
|
|
static const size_t nr_parser_state_types = sizeof parser_state_types / sizeof parser_state_types[0];
|
||
|
|
|
||
|
|
enum ivy_status ivy_asm_parser_create(struct ivy_asm_parser **out)
|
||
|
|
{
|
||
|
|
struct ivy_asm_parser *parser = malloc(sizeof *parser);
|
||
|
|
|
||
|
|
if (!parser) {
|
||
|
|
return IVY_ERR_NO_MEMORY;
|
||
|
|
}
|
||
|
|
|
||
|
|
memset(parser, 0x0, sizeof *parser);
|
||
|
|
|
||
|
|
asm_parser_push_state(parser, ASM_PARSER_UNIT);
|
||
|
|
|
||
|
|
*out = parser;
|
||
|
|
return IVY_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
void ivy_asm_parser_destroy(struct ivy_asm_parser *p)
|
||
|
|
{
|
||
|
|
free(p);
|
||
|
|
}
|
||
|
|
|
||
|
|
void ivy_asm_parser_set_assembler(
|
||
|
|
struct ivy_asm_parser *p, struct ivy_assembler *as)
|
||
|
|
{
|
||
|
|
p->p_assembler = as;
|
||
|
|
}
|
||
|
|
|
||
|
|
static token_parse_function get_token_parser(struct parser_state *state, struct ivy_asm_token *tok)
|
||
|
|
{
|
||
|
|
struct parser_state_type *type = state->s_type;
|
||
|
|
if (!type) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
token_parse_function specific_parser = NULL;
|
||
|
|
token_parse_function specific_fallback_parser = NULL;
|
||
|
|
token_parse_function token_parser = type->n_token_parsers[__TOK_PARSER_INDEX(tok->t_type)];
|
||
|
|
token_parse_function token_fallback_parser = type->n_token_parsers[__TOK_PARSER_FALLBACK_INDEX];
|
||
|
|
|
||
|
|
switch (tok->t_type) {
|
||
|
|
case IVY_ASM_TOK_SYMBOL:
|
||
|
|
specific_parser = type->n_symbol_parsers[__SYM_PARSER_INDEX(tok->t_symbol)];
|
||
|
|
specific_fallback_parser = type->n_symbol_parsers[__SYM_PARSER_FALLBACK_INDEX];
|
||
|
|
break;
|
||
|
|
case IVY_ASM_TOK_KEYWORD:
|
||
|
|
specific_parser = type->n_keyword_parsers[__KW_PARSER_INDEX(tok->t_keyword)];
|
||
|
|
specific_fallback_parser = type->n_keyword_parsers[__KW_PARSER_FALLBACK_INDEX];
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (specific_parser)
|
||
|
|
return specific_parser;
|
||
|
|
if (specific_fallback_parser)
|
||
|
|
return specific_fallback_parser;
|
||
|
|
if (token_parser)
|
||
|
|
return token_parser;
|
||
|
|
if (token_fallback_parser)
|
||
|
|
return token_fallback_parser;
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
enum ivy_status ivy_asm_parser_push_token(
|
||
|
|
struct ivy_asm_parser *p, struct ivy_asm_token *tok)
|
||
|
|
{
|
||
|
|
struct parser_state *state = asm_parser_get_state(p);
|
||
|
|
if (!state) {
|
||
|
|
return IVY_ERR_NOT_SUPPORTED;
|
||
|
|
}
|
||
|
|
|
||
|
|
token_parse_function f = get_token_parser(state, tok);
|
||
|
|
if (!f) {
|
||
|
|
if (tok->t_type == IVY_ASM_TOK_LINEFEED) {
|
||
|
|
ivy_asm_token_destroy(tok);
|
||
|
|
return IVY_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
return IVY_ERR_BAD_SYNTAX;
|
||
|
|
}
|
||
|
|
|
||
|
|
return f(p, tok);
|
||
|
|
}
|
||
|
|
|
||
|
|
static struct parser_state_type *get_parser_state_type(enum parser_state_type_id type)
|
||
|
|
{
|
||
|
|
if (type < 0 || type >= nr_parser_state_types) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
return parser_state_types[type];
|
||
|
|
}
|
||
|
|
|
||
|
|
struct parser_state *asm_parser_push_state(struct ivy_asm_parser *parser, enum parser_state_type_id type)
|
||
|
|
{
|
||
|
|
struct parser_state_type *type_info = get_parser_state_type(type);
|
||
|
|
|
||
|
|
if (!type_info) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct parser_state *state = malloc(type_info->n_state_size);
|
||
|
|
|
||
|
|
if (!state) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
memset(state, 0x0, type_info->n_state_size);
|
||
|
|
|
||
|
|
state->s_type = type_info;
|
||
|
|
|
||
|
|
if (type_info->n_init_state) {
|
||
|
|
type_info->n_init_state(parser, state);
|
||
|
|
}
|
||
|
|
|
||
|
|
b_queue_push_back(&parser->p_state, &state->s_entry);
|
||
|
|
|
||
|
|
return state;
|
||
|
|
}
|
||
|
|
|
||
|
|
void asm_parser_pop_state(struct ivy_asm_parser *parser, void *ret)
|
||
|
|
{
|
||
|
|
b_queue_entry *last = b_queue_pop_back(&parser->p_state);
|
||
|
|
if (!last) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct parser_state *state = b_unbox(struct parser_state, last, s_entry);
|
||
|
|
|
||
|
|
if (state->s_type->n_finish_state) {
|
||
|
|
state->s_type->n_finish_state(parser, state);
|
||
|
|
}
|
||
|
|
|
||
|
|
free(state);
|
||
|
|
|
||
|
|
state = asm_parser_get_state(parser);
|
||
|
|
if (state) {
|
||
|
|
state->s_previous_value = ret;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
struct parser_state *asm_parser_get_state(struct ivy_asm_parser *parser)
|
||
|
|
{
|
||
|
|
b_queue_entry *last = b_queue_last(&parser->p_state);
|
||
|
|
|
||
|
|
if (!last) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
return b_unbox(struct parser_state, last, s_entry);
|
||
|
|
}
|