From 6aaa58f518120cf5592bb63c2d8db5a52490381a Mon Sep 17 00:00:00 2001 From: lisyarus Date: Thu, 18 Dec 2025 01:37:17 +0300 Subject: [PATCH] Refactor interpreter: parse all files before executing them & improve error reporting --- apps/interpreter/source/main.cpp | 72 +++++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/apps/interpreter/source/main.cpp b/apps/interpreter/source/main.cpp index f9c7668..d559fb2 100644 --- a/apps/interpreter/source/main.cpp +++ b/apps/interpreter/source/main.cpp @@ -5,16 +5,45 @@ #include #include +#include #include +#include -int main(int argc, char ** argv) try +std::string extract_nth_line(std::filesystem::path const & path, std::size_t n) +{ + std::ifstream file(path); + std::string line; + + for (size_t i = 1; i <= n && std::getline(file, line); ++i) { + if (i == n) { + return line; + } + } + + return {}; +} + +void print_error_context(std::filesystem::path const & file, pslang::ast::location const & location) +{ + if (location.begin.line == location.end.line) + { + std::size_t max_line_number_digits = std::floor(std::log10(location.begin.line)) + 1; + + std::cerr << std::endl; + std::cerr << "line " << std::setw(max_line_number_digits) << std::right << location.begin.line << ": "; + std::cerr << extract_nth_line(file, location.begin.line) << std::endl; + std::cerr << std::string(std::max(location.begin.column, 1) - 1 + max_line_number_digits + 7, ' ') << std::string(location.end.column - location.begin.column, '^') << std::endl; + } +} + +int main(int argc, char ** argv) { if (argc == 1) { std::cout << "Usage: psli [ options ] [ ... ]\n"; std::cout << "Available options:\n"; std::cout << " -t, --trace Trace each line of execution\n"; - std::cout << " -d, --dump Dump all variables after processing each file\n"; + std::cout << " -d, --dump Dump all variables after processing all files\n"; std::cout << " -p, --print Print the AST after parsing each file\n"; return 0; } @@ -26,6 +55,9 @@ int main(int argc, char ** argv) try bool dump = false; bool dump_ast = false; + std::vector filenames; + std::vector parsed; + for (int arg = 1; arg < argc; ++arg) { if (std::strcmp(argv[arg], "-d") == 0 || std::strcmp(argv[arg], "--dump") == 0) @@ -46,21 +78,33 @@ int main(int argc, char ** argv) try continue; } - auto ast = parser::parse(argv[arg]); - - if (dump_ast) + try { - ast::print(std::cout, ast); - std::cout << std::flush; + filenames.push_back(argv[arg]); + parsed.push_back(parser::parse(argv[arg])); } + catch (pslang::parser::parse_error const & error) + { + std::cerr << "Parse error at " << error.location() << ":\n " << error.what() << std::endl; + print_error_context(argv[arg], error.location()); + return EXIT_FAILURE; + } + } + if (dump_ast) + { + for (std::size_t i = 0; i < filenames.size(); ++i) + { + std::cout << "Input file " << filenames[i] << " AST dump:\n\n"; + ast::print(std::cout, parsed[i]); + std::cout << "\n"; + } + std::cout << std::flush; + } + + for (auto const & ast : parsed) interpreter::exec(context, ast); - if (dump) - interpreter::dump(std::cout, context); - } -} -catch (pslang::parser::parse_error const & error) -{ - std::cerr << "Parse error at " << error.location() << ":\n " << error.what() << std::endl; + if (dump) + interpreter::dump(std::cout, context); }