pslang/apps/interpreter/source/main.cpp

110 lines
2.8 KiB
C++

#include <pslang/parser/parser.hpp>
#include <pslang/parser/error.hpp>
#include <pslang/interpreter/exec.hpp>
#include <pslang/ast/statement.hpp>
#include <pslang/ast/print.hpp>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cmath>
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<std::size_t>(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 ] <file1> [ <file2> ... ]\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 all files\n";
std::cout << " -p, --print Print the AST after parsing each file\n";
return 0;
}
using namespace pslang;
auto context = interpreter::empty_context();
bool dump = false;
bool dump_ast = false;
std::vector<std::string> filenames;
std::vector<ast::statement_list_ptr> parsed;
for (int arg = 1; arg < argc; ++arg)
{
if (std::strcmp(argv[arg], "-d") == 0 || std::strcmp(argv[arg], "--dump") == 0)
{
dump = true;
continue;
}
if (std::strcmp(argv[arg], "-t") == 0 || std::strcmp(argv[arg], "--trace") == 0)
{
context.trace = true;
continue;
}
if (std::strcmp(argv[arg], "-p") == 0 || std::strcmp(argv[arg], "--print") == 0)
{
dump_ast = true;
continue;
}
try
{
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);
}