lang: replace stack-based parser with a recursive parser
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
#include "ctx.h"
|
||||
|
||||
#include <ivy/lang/parse.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
enum ivy_status ivy_parser_create(struct ivy_parser **parser)
|
||||
{
|
||||
struct ivy_parser *out = malloc(sizeof *out);
|
||||
if (!out) {
|
||||
return IVY_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
memset(out, 0x0, sizeof *out);
|
||||
|
||||
*parser = out;
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
void ivy_parser_destroy(struct ivy_parser *parser)
|
||||
{
|
||||
free(parser);
|
||||
}
|
||||
|
||||
enum ivy_status ivy_parser_set_diag_ctx(
|
||||
struct ivy_parser *parser, struct ivy_diag_ctx *ctx)
|
||||
{
|
||||
parser->p_diag = ctx;
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
enum ivy_status ivy_parser_get_status(struct ivy_parser *parser)
|
||||
{
|
||||
return parser->p_status;
|
||||
}
|
||||
|
||||
enum ivy_status ivy_parser_parse(
|
||||
struct ivy_parser *parser, struct ivy_lexer *src, struct ivy_ast_node **out)
|
||||
{
|
||||
parser->p_src = src;
|
||||
enum ivy_status status = parse_unit(parser, out);
|
||||
if (status == IVY_ERR_EOF && *out != NULL) {
|
||||
status = IVY_OK;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
struct ivy_token *peek_token(struct ivy_parser *parser)
|
||||
{
|
||||
fx_queue_entry *entry = fx_queue_first(&parser->p_tokens);
|
||||
if (!entry) {
|
||||
return ivy_lexer_peek(parser->p_src);
|
||||
}
|
||||
|
||||
return fx_unbox(struct ivy_token, entry, t_entry);
|
||||
}
|
||||
|
||||
struct ivy_token *peek_next_token(struct ivy_parser *parser)
|
||||
{
|
||||
if (fx_queue_empty(&parser->p_tokens)) {
|
||||
struct ivy_token *tok = parse_token(parser);
|
||||
fx_queue_push_back(&parser->p_tokens, &tok->t_entry);
|
||||
return ivy_lexer_peek(parser->p_src);
|
||||
}
|
||||
|
||||
fx_queue_entry *buf = fx_queue_first(&parser->p_tokens);
|
||||
if (buf) {
|
||||
buf = fx_queue_next(buf);
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
return fx_unbox(struct ivy_token, buf, t_entry);
|
||||
}
|
||||
|
||||
return ivy_lexer_peek(parser->p_src);
|
||||
}
|
||||
|
||||
struct ivy_token *parse_token(struct ivy_parser *parser)
|
||||
{
|
||||
fx_queue_entry *entry = fx_queue_pop_front(&parser->p_tokens);
|
||||
if (!entry) {
|
||||
return ivy_lexer_read(parser->p_src);
|
||||
}
|
||||
|
||||
return fx_unbox(struct ivy_token, entry, t_entry);
|
||||
}
|
||||
|
||||
void discard_token(struct ivy_parser *parser)
|
||||
{
|
||||
struct ivy_token *tok = parse_token(parser);
|
||||
if (tok) {
|
||||
ivy_token_destroy(tok);
|
||||
}
|
||||
}
|
||||
|
||||
void __parse_trace(
|
||||
struct ivy_parser *parser, const char *func, int line,
|
||||
const char *format, ...)
|
||||
{
|
||||
struct ivy_token *tok = NULL;
|
||||
if (parser) {
|
||||
tok = peek_token(parser);
|
||||
if (tok) {
|
||||
fprintf(stderr, "[%zu:%zu] ", tok->t_start.c_row,
|
||||
tok->t_start.c_col);
|
||||
} else {
|
||||
fprintf(stderr, "[EOF] ");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "[UNK] ");
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s:%d: ", func, line);
|
||||
|
||||
if (tok) {
|
||||
fprintf(stderr, "(%s) ", ivy_token_to_string(tok));
|
||||
}
|
||||
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
vfprintf(stderr, format, va);
|
||||
va_end(va);
|
||||
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
Reference in New Issue
Block a user