#include "Evalvisitor.h"
#include "Python3Lexer.h"
#include "Python3Parser.h"
#include "antlr4-runtime.h"
#include <iostream>
#include "clipp/clipp.h"
using namespace antlr4;
// TODO: regenerating files in directory named "generated" is dangerous.
//       if you really need to regenerate,please ask TA for help.
int main(int argc, char *argv[])
{
  // TODO: please don't modify the code below the construction of ifs if you want to use visitor mode
  std::string input_file;
  bool need_help = false;
  auto cli = (clipp::option("-h", "--help").set(need_help).doc("show help") |
              clipp::opt_value("input file", input_file));
  if (!clipp::parse(argc, argv, cli))
  {
    std::cout << clipp::make_man_page(cli, argv[0]);
    return 0;
  }
  if (need_help)
  {
    std::cout << clipp::make_man_page(cli, argv[0]);
    return 0;
  }
  ANTLRInputStream *input_p;
  if (input_file.length() == 0)
    input_p = new ANTLRInputStream(std::cin);
  else
  {
    std::ifstream ifs(input_file);
    input_p = new ANTLRInputStream(ifs);
  }
  Python3Lexer lexer(input_p);
  CommonTokenStream tokens(&lexer);
  tokens.fill();
  Python3Parser parser(&tokens);
  tree::ParseTree *tree = parser.file_input();
  EvalVisitor visitor;
  try
  {
    visitor.visit(tree);
  }
  catch (const InterpretException &e)
  {
    std::cerr << "[Interpret Error] " << e.what() << std::endl;
  }
  catch (const FatalError &e)
  {
    std::cerr << "\e[7m\e[31m[Fatal Error] " << e.what() << "\e[0m" << std::endl;
  }
  catch (const std::exception &e)
  {
    std::cerr << "\e[7m\e[31m[other std::exception] " << e.what() << "\e[0m" << std::endl;
  }
  catch (...)
  {
    std::cerr << "\e[7m\e[31m[Unknown Exception]\e[0m" << std::endl;
  }
  delete input_p;
  return 0;
}