如何使用 antlr4 恢复特定行和字符位置的 ParserRuleContext?
How to recover the ParserRuleContext for a specific line and character position with antlr4?
一旦我初始化了解析器、词法分析器并获得了 translationUnit 上下文,我如何才能直接跳转到包含 antlr4(CPP 运行时)中特定行和字符位置的(最近的)ParserRuleContext?
通常我使用 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();
我想执行相反的操作:从特定行和字符位置获取标记,然后获取(第一个)父上下文。可能吗?
我想我可以通过检查函数 enterEveryRule(antlr4::ParserRuleContext* context)
中 context
的每一行和字符位置来实现我想要的(即根据行和字符位置找到上下文),但看起来过于复杂。那么有没有更简单的方法来恢复特定 line/character 位置的 ParserRuleContext?
方法很简单。 ParserRuleContext
包含带有定位信息的开始和停止令牌。因此很容易判断规则上下文是否包含特定位置。从解析树根开始并遍历它的子节点。找到包含此位置的那个(不可能重叠)。继续该节点及其子节点,直到找到一个终端节点,这就是您正在寻找的节点。如果对于给定节点,没有子节点包含给定位置,则改用该节点。
在MySQL Workbench Sources there's a C++ implementation for terminalFromPosition
and contextFromPosition
。第一个函数采用 line/column 对并努力始终 return 一个终端(即使在给定位置直接存在 none ),而后者使用字符索引并准确地实现该方法正如我在上一段中提到的。
一旦我初始化了解析器、词法分析器并获得了 translationUnit 上下文,我如何才能直接跳转到包含 antlr4(CPP 运行时)中特定行和字符位置的(最近的)ParserRuleContext?
通常我使用 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();
我想执行相反的操作:从特定行和字符位置获取标记,然后获取(第一个)父上下文。可能吗?
我想我可以通过检查函数 enterEveryRule(antlr4::ParserRuleContext* context)
中 context
的每一行和字符位置来实现我想要的(即根据行和字符位置找到上下文),但看起来过于复杂。那么有没有更简单的方法来恢复特定 line/character 位置的 ParserRuleContext?
方法很简单。 ParserRuleContext
包含带有定位信息的开始和停止令牌。因此很容易判断规则上下文是否包含特定位置。从解析树根开始并遍历它的子节点。找到包含此位置的那个(不可能重叠)。继续该节点及其子节点,直到找到一个终端节点,这就是您正在寻找的节点。如果对于给定节点,没有子节点包含给定位置,则改用该节点。
在MySQL Workbench Sources there's a C++ implementation for terminalFromPosition
and contextFromPosition
。第一个函数采用 line/column 对并努力始终 return 一个终端(即使在给定位置直接存在 none ),而后者使用字符索引并准确地实现该方法正如我在上一段中提到的。