You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
71 lines
2.4 KiB
71 lines
2.4 KiB
// 调用前端解析流程,返回语法树。
|
|
#include "frontend/AntlrDriver.h"
|
|
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
#include "SysYLexer.h"
|
|
#include "SysYParser.h"
|
|
#include "antlr4-runtime.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("[parse] 暂不支持的语法/词法 @" + std::to_string(line) + ":" +
|
|
std::to_string(charPositionInLine) + " - " + msg);
|
|
}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
AntlrResult ParseFileWithAntlr(const std::string& path) {
|
|
std::ifstream fin(path);
|
|
if (!fin.is_open()) {
|
|
throw std::runtime_error("[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()) {
|
|
throw std::runtime_error("[parse] 暂不支持的语法/词法 - " + msg);
|
|
}
|
|
if (auto* tok = parser->getCurrentToken()) {
|
|
throw std::runtime_error("[parse] 暂不支持的语法/词法 @" +
|
|
std::to_string(tok->getLine()) + ":" +
|
|
std::to_string(tok->getCharPositionInLine()) +
|
|
" near token '" + tok->getText() + "'");
|
|
}
|
|
throw std::runtime_error("[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;
|
|
}
|