ANTLR4生成的C++词法分析器无法接收输入流问题求助
问题描述
在Ubuntu系统中,通过ANTLR4的-Dlanguage=Cpp参数生成ExprLexer和ExprParser,未修改生成文件,使用官方示例代码:
#include <iostream> #include "antlr4-runtime.h" #include "ExprLexer.h" #include "ExprParser.h" using namespace antlr4; int main(int , const char **) { // make input stream with string, put input stream into ANTLRInputStream ANTLRInputStream input("h"); ExprLexer lexer(&input); return 0; }
编译命令:
g++ -std=c++17 *.cpp -o index -I/usr/local/include/antlr4-runtime -L. -lantlr4-runtime
编译正常,但运行时抛出错误:
terminate called after throwing an instance of 'std::system_error' what(): Unknown error -1 Aborted (core dumped)
尝试用try-catch捕获仅得知是系统调用错误,无法定位具体原因。
解决方法
1. 匹配ANTLR4 Runtime与生成代码的版本
ANTLR4生成代码和runtime库版本必须严格一致,版本不兼容会触发底层调用错误:
- 查看runtime版本:查看
/usr/local/include/antlr4-runtime/antlr4-runtime.h中的版本宏定义,或执行pkg-config --modversion antlr4-runtime - 查看生成代码用的antlr4.jar版本:
java -jar antlr4.jar -version - 版本不一致时,重新安装对应版本的runtime,或用相同版本的antlr4.jar重新生成词法/解析器代码。
2. 确保动态链接库可被加载
编译时指定的-L.仅在编译阶段生效,运行时需确保antlr4-runtime的so文件能被找到:
- 临时指定库路径运行:
LD_LIBRARY_PATH=/usr/local/lib ./index(默认antlr4-runtime安装在/usr/local/lib) - 编译时嵌入库路径:
g++ -std=c++17 *.cpp -o index -I/usr/local/include/antlr4-runtime -L/usr/local/lib -Wl,-rpath=/usr/local/lib -lantlr4-runtime - 永久添加库路径:将
/usr/local/lib写入/etc/ld.so.conf,执行sudo ldconfig更新配置。
3. 修复Locale设置问题
ANTLR4 C++ runtime初始化依赖正确的locale,缺失会导致系统调用错误:
- 运行前设置locale:
export LC_ALL=C.UTF-8 && ./index - 或在代码开头添加locale初始化:
#include <locale> int main(int , const char **) { std::locale::global(std::locale("C.UTF-8")); ANTLRInputStream input("h"); ExprLexer lexer(&input); return 0; }
4. 捕获更详细的错误信息
修改代码打印完整错误细节,帮助定位问题:
#include <iostream> #include <system_error> #include "antlr4-runtime.h" #include "ExprLexer.h" #include "ExprParser.h" using namespace antlr4; int main(int , const char **) { try { ANTLRInputStream input("h"); ExprLexer lexer(&input); } catch (const std::system_error& e) { std::cerr << "System error: " << e.what() << ", error code: " << e.code() << std::endl; std::cerr << "Error category: " << e.code().category().name() << std::endl; } catch (const std::exception& e) { std::cerr << "Exception: " << e.what() << std::endl; } return 0; }
内容的提问来源于stack exchange,提问作者Amukh1
相关产品推荐
相关产品推荐

