// 调用前端解析流程，返回语法树。
#include "frontend/AntlrDriver.h"

#include <fstream>
#include <sstream>
#include <stdexcept>
#include <string>

#include "SysYLexer.h"
#include "SysYParser.h"
#include "antlr4-runtime.h"
#include "utils/Log.h"

namespace {

class ParseErrorListener : public antlr4::BaseErrorListener {
 public:
  void syntaxError(antlr4::Recognizer* /*recognizer*/, antlr4::Token* /*offendingSymbol*/,
                   size_t line, size_t charPositionInLine,
                   const std::string& msg, std::exception_ptr /*e*/) override {
    throw std::runtime_error(FormatErrorAt("parse", line, charPositionInLine,
                                           "暂不支持的语法/词法 - " + msg));
  }
};

}  // namespace

AntlrResult ParseFileWithAntlr(const std::string& path) {
  std::ifstream fin(path);
  if (!fin.is_open()) {
    throw std::runtime_error(FormatError("parse", "无法打开输入文件: " + path));
  }
  std::ostringstream ss;
  ss << fin.rdbuf();

  auto input = std::make_unique<antlr4::ANTLRInputStream>(ss.str());
  auto lexer = std::make_unique<SysYLexer>(input.get());
  auto tokens = std::make_unique<antlr4::CommonTokenStream>(lexer.get());
  auto parser = std::make_unique<SysYParser>(tokens.get());

  ParseErrorListener error_listener;
  lexer->removeErrorListeners();
  lexer->addErrorListener(&error_listener);
  parser->removeErrorListeners();
  parser->addErrorListener(&error_listener);
  parser->setErrorHandler(std::make_shared<antlr4::BailErrorStrategy>());
  antlr4::tree::ParseTree* tree = nullptr;
  try {
    tree = parser->compUnit();
  } catch (const std::exception& ex) {
    const std::string msg = ex.what();
    if (!msg.empty()) {
      if (HasErrorPrefix(msg, "parse")) {
        throw;
      }
      throw std::runtime_error(
          FormatError("parse", "暂不支持的语法/词法 - " + msg));
    }
    if (auto* tok = parser->getCurrentToken()) {
      throw std::runtime_error(
          FormatErrorAt("parse", tok->getLine(), tok->getCharPositionInLine(),
                        "暂不支持的语法/词法 near token '" + tok->getText() + "'"));
    }
    throw std::runtime_error(FormatError("parse", "暂不支持的语法/词法"));
  }

  AntlrResult result;
  result.input = std::move(input);
  result.lexer = std::move(lexer);
  result.tokens = std::move(tokens);
  result.parser = std::move(parser);
  result.tree = tree;
  return result;
}
