From b2c252fbc218ec95c449ae7f2263d98a6f87c900 Mon Sep 17 00:00:00 2001 From: Laria Carolin Chabowski Date: Sun, 2 Jan 2022 17:21:16 +0100 Subject: [PATCH] main.c: Add repl mode switching You can now choose, if you want to play around with the tokenizer, parser or evaluator in the repl. --- src/main.c | 164 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 136 insertions(+), 28 deletions(-) diff --git a/src/main.c b/src/main.c index 1efa056..9855d2a 100644 --- a/src/main.c +++ b/src/main.c @@ -5,6 +5,12 @@ #include "apfl.h" +enum repl_mode { + REPL_TOKENIZER, + REPL_PARSER, + REPL_EVAL, +}; + static bool repl_source_reader(void *context, char *buf, size_t *len, bool need) { @@ -28,55 +34,157 @@ repl_source_reader(void *context, char *buf, size_t *len, bool need) return true; } -int -main(int argc, const char **argv) +static int +repl_tokenizer(apfl_tokenizer_ptr tokenizer) { - (void)argc; - (void)argv; - - int rv = 0; - - apfl_tokenizer_ptr tokenizer = NULL; - apfl_parser_ptr parser = NULL; - - if ((tokenizer = apfl_tokenizer_new(repl_source_reader, NULL)) == NULL) { - fprintf(stderr, "Failed initializing tokenizer\n"); - goto exit; - } - - if ((parser = apfl_parser_new(apfl_tokenizer_as_token_source(tokenizer))) == NULL) { - fprintf(stderr, "Failed initializing parser\n"); - goto exit; - } - while (true) { struct apfl_error err; - struct apfl_expr expr; + struct apfl_token token; - switch (apfl_parser_next(parser)) { + switch (apfl_tokenizer_next(tokenizer, false)) { case APFL_PARSE_OK: - expr = apfl_parser_get_expr(parser); - apfl_expr_print(expr, stdout); - apfl_expr_deinit(&expr); + token = apfl_tokenizer_get_token(tokenizer); + apfl_token_print(token, stdout); + apfl_token_deinit(&token); break; case APFL_PARSE_EOF: - goto exit; + return 0; + case APFL_PARSE_ERROR: + err = apfl_tokenizer_get_error(tokenizer); + apfl_error_print(err, stderr); + + if (APFL_ERROR_IS_FATAL(err)) { + return 1; + } + break; + } + } +} + +static bool +repl_parser_generic(apfl_parser_ptr parser, struct apfl_expr *expr, int *rv) +{ + while (true) { + struct apfl_error err; + + switch (apfl_parser_next(parser)) { + case APFL_PARSE_OK: + *expr = apfl_parser_get_expr(parser); + return true; + case APFL_PARSE_EOF: + *rv = 0; + return false; case APFL_PARSE_ERROR: err = apfl_parser_get_error(parser); apfl_error_print(err, stderr); if (APFL_ERROR_IS_FATAL(err)) { - rv = 1; - goto exit; + *rv = 1; + return false; } break; } } +} + +static int +repl_parser(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(&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)) { + struct apfl_result result = apfl_eval(ctx, expr); + switch (result.type) { + case APFL_RESULT_OK: + apfl_value_print(result.value, stdout); + apfl_value_deinit(&result.value); + 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; + } + } + + apfl_tokenizer_ptr tokenizer = NULL; + apfl_parser_ptr parser = NULL; + apfl_ctx ctx = NULL; + + if ((tokenizer = apfl_tokenizer_new(repl_source_reader, NULL)) == NULL) { + fprintf(stderr, "Failed initializing tokenizer\n"); + rv = 1; + goto exit; + } + + if (mode >= REPL_PARSER) { + if ((parser = apfl_parser_new(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()) == NULL) { + fprintf(stderr, "Failed initializing context\n"); + rv = 1; + goto exit; + } + } + + switch (mode) { + case REPL_TOKENIZER: + rv = repl_tokenizer(tokenizer); + break; + case REPL_PARSER: + rv = repl_parser(parser); + break; + case REPL_EVAL: + rv = repl_eval(parser, ctx); + break; + } exit: apfl_tokenizer_destroy(tokenizer); apfl_parser_destroy(parser); + apfl_ctx_destroy(ctx); return rv; }