代码之家  ›  专栏  ›  技术社区  ›  Malick

如何用antlr4恢复特定行和字符位置的parserRuleContext?

  •  0
  • Malick  · 技术社区  · 7 年前

    一旦初始化了解析器、lexer并获得了translationUnit上下文,如何直接跳转到(最近的)parserRuleContext,该上下文在antl4(cpp运行时)中包含特定的行和字符位置?

    通常我用 Listener 用于遍历TranslationUnit上下文的模式。在每个访问的上下文中,我可以使用以下代码获取上下文的相应行和字符位置:

    antlr4::Token* tokenclass = _tokenstream->get(myContext->getSourceInterval().a); // use ".b" if end of interval is needed 
    size_t CharPositionStartInLine = tokenclass->getCharPositionInLine();       
    size_t LineStart = tokenclass->getLine();
    

    我想执行相反的操作:从特定的行和字符位置获取一个令牌,然后获取(第一个)父上下文。有可能吗?

    我想我可以通过检查每个行和字符的位置来实现我想要的(即根据行和字符的位置找到一个上下文)。 context 在函数内部 enterEveryRule(antlr4::ParserRuleContext* context) 但这似乎过于复杂了。那么,是否有一种更简单的方法来恢复特定行/字符位置的ParserRuleContext?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Mike Lischke    7 年前

    方法非常简单。一 ParserRuleContext 包含带有定位信息的开始和停止标记。因此,很容易判断规则上下文是否包含特定位置。从解析树根开始,并遍历其子级。找到包含此位置的位置(不可能重叠)。继续使用该节点及其子节点,直到找到要查找的终端节点。如果对于给定节点,没有子节点包含给定位置,则使用该节点。

    在 MySQL Workbench Sources 有一个C++实现 terminalFromPosition 和 contextFromPosition . 第一个函数接受一个行/列对,并努力始终返回一个终端(即使在给定位置没有直接返回终端),而后者使用一个字符索引,并完全实现前面提到的方法。