C++目标下ANTLR中通过#line指令设置源文件名的问题求助
解决ANTLR4 C++ Lexer中动态设置源文件名的问题
看起来你遇到的问题是ANTLR4的C++实现里,ANTLRInputStream没有提供公开的方法修改源文件名,直接访问其name成员不仅不符合API规范,还无法让ErrorListener正确获取更新后的文件名。下面是一个可靠的解决方案:
核心思路
既然无法直接修改输入流的源名称,我们可以让自定义Lexer自己维护当前的文件名,并通过重写ANTLR的getSourceName()方法,让ErrorListener能拿到动态更新的文件名。
具体步骤
在自定义Lexer中添加文件名成员变量
修改你的myLexer类,添加一个私有成员来存储当前的文件名:class myLexer : public antlr4::Lexer { private: std::string currentFilename; // 维护当前的源文件名 // 其他成员... public: // 构造函数等... };初始化文件名
在myLexer的构造函数里,用输入流的初始文件名初始化我们的成员变量:myLexer::myLexer(antlr4::ANTLRInputStream* input) : antlr4::Lexer(input), currentFilename(input->getSourceName()) {}重写getSourceName()方法
覆盖ANTLR Lexer类的getSourceName(),让它返回我们维护的currentFilename:const std::string& myLexer::getSourceName() const override { return currentFilename; }修改newFile函数
现在不需要再修改输入流的name了,直接更新我们自己的文件名成员:void myLexer::newFile (std::string newFilename, int newLine, int newPos) { this->currentFilename = std::move(newFilename); // 更新当前文件名 setLine(newLine); setCharPositionInLine(newPos); }更新ErrorListener的文件名获取方式
确保你的ErrorListener通过recognizer->getSourceName()获取文件名,而不是直接访问输入流:// 在ErrorListener的实现中 void syntaxError(antlr4::Recognizer* recognizer, ...) override { std::string filename = recognizer->getSourceName(); // 这里会拿到更新后的文件名 // 其他错误处理逻辑... }
为什么原来的方法没用?
- 多数ANTLR4 C++版本中,
ANTLRInputStream的name是私有/受保护成员,直接通过static_cast访问并赋值属于未定义行为,可能不会生效甚至引发崩溃。 - 即使
name可访问,Lexer可能在初始化时缓存了源文件名,后续修改输入流的name不会被ErrorListener感知到。
通过让Lexer自己维护文件名并覆盖标准方法,我们遵循了ANTLR的扩展机制,确保文件名的动态更新能被整个识别链正确获取。
内容的提问来源于stack exchange,提问作者TRock
相关产品推荐
相关产品推荐

