#include "parse.h" #include #include void parse_init(am_t *am, parse_ctx_t *out) { out->am = am; out->state = PARSE_STATE_INIT; out->sp = out->stack + PARSE_MAX_DEPTH - 1; } static void push_state(parse_ctx_t *ctx, parse_state_t state) { assert(ctx->sp >= ctx->stack); *ctx->sp-- = state; } static parse_state_t pop_state(parse_ctx_t *ctx) { assert(ctx->sp < ctx->stack + PARSE_MAX_DEPTH - 1); return *++ctx->sp; } static void append(parse_ctx_t *ctx, expr_t *expr) { expr_t *list = ctx->am->expr; while (!list->is_atom) list = list->pair.cdr; assert(list->atom.type == ATOM_TYPE_EMPTY_LIST); list->is_atom = false; list->pair.car = expr; list->pair.cdr = expr_empty_list(ctx->am); } parse_state_t parse_proc(parse_ctx_t *ctx, const token_t *token) { switch (ctx->state) { case PARSE_STATE_INIT: switch (token->type) { case TOKEN_TYPE_INTEGER: ctx->am->expr = expr_integer(ctx->am, token->integer); ctx->state = PARSE_STATE_DONE; break; case TOKEN_TYPE_SYMBOL: ctx->am->expr = expr_symbol(ctx->am, &token->symbol); ctx->state = PARSE_STATE_DONE; break; case TOKEN_TYPE_OPEN_PAREN: push_state(ctx, PARSE_STATE_DONE); ctx->am->expr = expr_empty_list(ctx->am); ctx->state = PARSE_STATE_LIST; break; case TOKEN_TYPE_CLOSE_PAREN: ctx->state = PARSE_STATE_ERROR; break; } break; case PARSE_STATE_LIST: switch (token->type) { case TOKEN_TYPE_INTEGER: append(ctx, expr_integer(ctx->am, token->integer)); break; case TOKEN_TYPE_SYMBOL: append(ctx, expr_symbol(ctx->am, &token->symbol)); break; case TOKEN_TYPE_OPEN_PAREN: am_push(ctx->am); push_state(ctx, PARSE_STATE_LIST); ctx->am->expr = expr_empty_list(ctx->am); ctx->state = PARSE_STATE_LIST; break; case TOKEN_TYPE_CLOSE_PAREN: ctx->state = pop_state(ctx); if (ctx->state == PARSE_STATE_LIST) { expr_t *expr = ctx->am->expr; am_pop(ctx->am); append(ctx, expr); } break; } break; case PARSE_STATE_DONE: case PARSE_STATE_ERROR: break; } assert(ctx->state != PARSE_STATE_INIT); return ctx->state; }