You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 11:47:31