fix(frontend): 补充不支持语法的警告输出
This commit is contained in:
@@ -4,15 +4,30 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "SysYLexer.h"
|
#include "SysYLexer.h"
|
||||||
#include "SysYParser.h"
|
#include "SysYParser.h"
|
||||||
#include "antlr4-runtime.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) {
|
AntlrResult ParseFileWithAntlr(const std::string& path) {
|
||||||
std::ifstream fin(path);
|
std::ifstream fin(path);
|
||||||
if (!fin.is_open()) {
|
if (!fin.is_open()) {
|
||||||
throw std::runtime_error("无法打开输入文件: " + path);
|
throw std::runtime_error("[parse] 无法打开输入文件: " + path);
|
||||||
}
|
}
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
ss << fin.rdbuf();
|
ss << fin.rdbuf();
|
||||||
@@ -21,8 +36,29 @@ AntlrResult ParseFileWithAntlr(const std::string& path) {
|
|||||||
auto lexer = std::make_unique<SysYLexer>(input.get());
|
auto lexer = std::make_unique<SysYLexer>(input.get());
|
||||||
auto tokens = std::make_unique<antlr4::CommonTokenStream>(lexer.get());
|
auto tokens = std::make_unique<antlr4::CommonTokenStream>(lexer.get());
|
||||||
auto parser = std::make_unique<SysYParser>(tokens.get());
|
auto parser = std::make_unique<SysYParser>(tokens.get());
|
||||||
|
|
||||||
|
ParseErrorListener error_listener;
|
||||||
|
lexer->removeErrorListeners();
|
||||||
|
lexer->addErrorListener(&error_listener);
|
||||||
parser->removeErrorListeners();
|
parser->removeErrorListeners();
|
||||||
auto tree = parser->compUnit();
|
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;
|
AntlrResult result;
|
||||||
result.input = std::move(input);
|
result.input = std::move(input);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ void IRGenImpl::GenBlock(const ast::Block& block) {
|
|||||||
void IRGenImpl::GenVarDecl(const ast::VarDecl& decl) {
|
void IRGenImpl::GenVarDecl(const ast::VarDecl& decl) {
|
||||||
auto it = locals_.find(decl.name);
|
auto it = locals_.find(decl.name);
|
||||||
if (it == locals_.end()) {
|
if (it == locals_.end()) {
|
||||||
throw std::runtime_error("变量栈槽未创建: " + decl.name);
|
throw std::runtime_error("[irgen] 变量栈槽未创建: " + decl.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
ir::Value* init = nullptr;
|
ir::Value* init = nullptr;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ ir::Value* IRGenImpl::GenExpr(const ast::Expr& expr) {
|
|||||||
if (auto var = dynamic_cast<const ast::VarExpr*>(&expr)) {
|
if (auto var = dynamic_cast<const ast::VarExpr*>(&expr)) {
|
||||||
auto it = locals_.find(var->name);
|
auto it = locals_.find(var->name);
|
||||||
if (it == locals_.end()) {
|
if (it == locals_.end()) {
|
||||||
throw std::runtime_error("变量未找到: " + var->name);
|
throw std::runtime_error("[irgen] 变量未找到: " + var->name);
|
||||||
}
|
}
|
||||||
std::string name = ir::DefaultContext().NextTemp();
|
std::string name = ir::DefaultContext().NextTemp();
|
||||||
return builder_.CreateLoad(it->second, name);
|
return builder_.CreateLoad(it->second, name);
|
||||||
@@ -33,5 +33,5 @@ ir::Value* IRGenImpl::GenExpr(const ast::Expr& expr) {
|
|||||||
return builder_.CreateBinary(ir::Opcode::Add, lhs, rhs, name);
|
return builder_.CreateBinary(ir::Opcode::Add, lhs, rhs, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw std::runtime_error("不支持的表达式类型");
|
throw std::runtime_error("[irgen] 暂不支持的表达式类型");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ IRGenImpl::IRGenImpl(ir::Module& module)
|
|||||||
|
|
||||||
void IRGenImpl::Gen(const ast::CompUnit& ast) {
|
void IRGenImpl::Gen(const ast::CompUnit& ast) {
|
||||||
if (!ast.func || !ast.func->body) {
|
if (!ast.func || !ast.func->body) {
|
||||||
throw std::runtime_error("AST 不完整:缺少 main 定义");
|
throw std::runtime_error("[irgen] AST 不完整:缺少 main 定义");
|
||||||
}
|
}
|
||||||
GenBlock(*ast.func->body);
|
GenBlock(*ast.func->body);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,5 +15,5 @@ void IRGenImpl::GenStmt(const ast::Stmt& stmt) {
|
|||||||
builder_.CreateRet(v);
|
builder_.CreateRet(v);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw std::runtime_error("不支持的语句类型");
|
throw std::runtime_error("[irgen] 暂不支持的语句类型");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class SemaVisitor {
|
|||||||
void CheckExpr(const ast::Expr& expr) {
|
void CheckExpr(const ast::Expr& expr) {
|
||||||
if (auto var = dynamic_cast<const ast::VarExpr*>(&expr)) {
|
if (auto var = dynamic_cast<const ast::VarExpr*>(&expr)) {
|
||||||
if (!table_.Contains(var->name)) {
|
if (!table_.Contains(var->name)) {
|
||||||
throw std::runtime_error("使用了未定义的变量: " + var->name);
|
throw std::runtime_error("[sema] 使用了未定义的变量: " + var->name);
|
||||||
}
|
}
|
||||||
} else if (auto bin = dynamic_cast<const ast::BinaryExpr*>(&expr)) {
|
} else if (auto bin = dynamic_cast<const ast::BinaryExpr*>(&expr)) {
|
||||||
CheckExpr(*bin->lhs);
|
CheckExpr(*bin->lhs);
|
||||||
|
|||||||
Reference in New Issue
Block a user