apfl/src/main.c

199 lines
4.6 KiB
C
Raw Normal View History

2021-12-10 20:22:16 +00:00
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "apfl.h"
enum repl_mode {
REPL_TOKENIZER,
REPL_PARSER,
REPL_EVAL,
};
2021-12-10 20:22:16 +00:00
static bool
repl_source_reader_cb(void *context, char *buf, size_t *len, bool need)
2021-12-10 20:22:16 +00:00
{
(void)context;
printf(need ? "... " : "> ");
fflush(stdout);
size_t maxlen = *len;
if (fgets(buf, maxlen, stdin) == NULL) {
if (feof(stdin)) {
*len = 0;
return true;
} else {
return false;
}
}
*len = strlen(buf);
return true;
}
static struct apfl_source_reader
repl_source_reader()
{
return (struct apfl_source_reader) {
.callback = repl_source_reader_cb,
.opaque = NULL,
};
}
static int
repl_tokenizer(struct apfl_allocator allocator, apfl_tokenizer_ptr tokenizer)
2021-12-10 20:22:16 +00:00
{
while (true) {
struct apfl_error err;
struct apfl_token token;
2021-12-10 20:22:16 +00:00
switch (apfl_tokenizer_next(tokenizer, false)) {
case APFL_PARSE_OK:
token = apfl_tokenizer_get_token(tokenizer);
apfl_token_print(token, stdout);
apfl_token_deinit(allocator, &token);
break;
case APFL_PARSE_EOF:
return 0;
case APFL_PARSE_ERROR:
err = apfl_tokenizer_get_error(tokenizer);
apfl_error_print(err, stderr);
2021-12-10 20:22:16 +00:00
if (APFL_ERROR_IS_FATAL(err)) {
return 1;
}
break;
}
}
}
static bool
repl_parser_generic(apfl_parser_ptr parser, struct apfl_expr *expr, int *rv)
{
2021-12-10 20:22:16 +00:00
while (true) {
struct apfl_error err;
switch (apfl_parser_next(parser)) {
2021-12-10 20:22:16 +00:00
case APFL_PARSE_OK:
*expr = apfl_parser_get_expr(parser);
return true;
2021-12-10 20:22:16 +00:00
case APFL_PARSE_EOF:
*rv = 0;
return false;
2021-12-10 20:22:16 +00:00
case APFL_PARSE_ERROR:
err = apfl_parser_get_error(parser);
2021-12-10 20:22:16 +00:00
apfl_error_print(err, stderr);
if (APFL_ERROR_IS_FATAL(err)) {
*rv = 1;
return false;
2021-12-10 20:22:16 +00:00
}
break;
}
}
}
static int
repl_parser(struct apfl_allocator allocator, apfl_parser_ptr parser)
{
struct apfl_expr expr;
int rv;
while (repl_parser_generic(parser, &expr, &rv)) {
apfl_expr_print(expr, stdout);
apfl_expr_deinit(allocator, &expr);
}
return rv;
}
static int
repl_eval(apfl_parser_ptr parser, apfl_ctx ctx)
{
struct apfl_expr expr;
int rv;
while (repl_parser_generic(parser, &expr, &rv)) {
switch (apfl_eval(ctx, expr)) {
case APFL_RESULT_OK:
apfl_debug_print_val(ctx, -1, stdout);
break;
case APFL_RESULT_ERR:
fprintf(stderr, "Error occurred during evaluation.\n");
break;
case APFL_RESULT_ERR_FATAL:
fprintf(stderr, "Fatal error occurred during evaluation.\n");
return 1;
}
}
return rv;
}
int
main(int argc, const char **argv)
{
int rv = 0;
enum repl_mode mode = REPL_PARSER;
if (argc > 1) {
if (apfl_string_eq(argv[1], "tokenizer")) {
mode = REPL_TOKENIZER;
} else if (apfl_string_eq(argv[1], "parser")) {
mode = REPL_PARSER;
} else if (apfl_string_eq(argv[1], "eval")) {
mode = REPL_EVAL;
} else {
fprintf(stderr, "Unknown mode: %s\n", argv[1]);
return 1;
}
}
struct apfl_allocator allocator = apfl_allocator_default();
apfl_tokenizer_ptr tokenizer = NULL;
apfl_parser_ptr parser = NULL;
apfl_ctx ctx = NULL;
if ((tokenizer = apfl_tokenizer_new(allocator, repl_source_reader())) == NULL) {
fprintf(stderr, "Failed initializing tokenizer\n");
rv = 1;
goto exit;
}
if (mode >= REPL_PARSER) {
if ((parser = apfl_parser_new(allocator, apfl_tokenizer_as_token_source(tokenizer))) == NULL) {
fprintf(stderr, "Failed initializing parser\n");
rv = 1;
goto exit;
}
}
if (mode >= REPL_EVAL) {
if ((ctx = apfl_ctx_new(allocator)) == NULL) {
fprintf(stderr, "Failed initializing context\n");
rv = 1;
goto exit;
}
}
switch (mode) {
case REPL_TOKENIZER:
rv = repl_tokenizer(allocator, tokenizer);
break;
case REPL_PARSER:
rv = repl_parser(allocator, parser);
break;
case REPL_EVAL:
rv = repl_eval(parser, ctx);
break;
}
2021-12-10 20:22:16 +00:00
exit:
apfl_tokenizer_destroy(tokenizer);
apfl_parser_destroy(parser);
apfl_ctx_destroy(ctx);
2021-12-10 20:22:16 +00:00
return rv;
}