如何在antlr4中的listener类中插入标记或上下文



我有一个解析BASIC语言的antlr4语法文件。有没有办法在我的扩展baseListener类中插入更多的代码?

例如,如果我正在解析以下代码:

10 print "hello world"
   %include "moreCode.bas"
   print "after include"

moreCode.bas可能类似于:

for t% = 1% to 10%
   print t%
next t%

我需要检测include命令,并将内容包含到正在遍历的文件中,然后作为一个整体继续遍历它。

所以我想,在侦听器类的enterIncludeCommand方法中,我会为moreCode.bas启动一个新的解析器,然后以某种方式将令牌/上下文插入到我当前的解析器中。

正确的方法是什么?

没有一个正确的模式。也就是说,一种有效的方法是让您的main启动解析器,方法是始终通过构造函数调用,该构造函数将状态对象和源路径作为参数

public class BasicParser {
    public static void main(String[] args) {
        ...
        StateModel state = new StateModel()
        RecurseParser rp = new RecurseParser(state, pathname);
        ...
    }
}
public class RecurseParser {
    public RecurseParser(StateModel state, String pathname) {
        this.state = state;
        this.pathname = pathname;  // source text to parse
        ...
    }
    public StateModel getResults() {
        return this.state
}

enterIncludeStatement方法中,直接创建并运行一个新的RecurseParser实例。在exitIncludeStatement中,检索新的当前状态,并根据需要验证/检查错误。

由于状态模型封装了符号表等,所以在森林中行走时可以保持连续性——递归实际上是免费的。

应该提到的是,相对于符号表,执行include本质上与调用子例程相同。

相关:符号表

我有两个解决方案,我选择了最后一个。格罗森伯格也有一个好主意。

1) 使用TokenStreamRewriter,并在enterIncludeStatement中使用重写器insertBefore、insertAfter和/或replace方法。在该特定侦听器对象的遍历结束时,调用重写器getText(),它将为您提供组合字符串。你必须重新分析该文本才能进入下一个监听器通道

2) 在侦听器类的enterIncludeStatement方法中,获取include文件名,在其上运行lexer/parser,然后获取第一个StatementContext(在我的情况下),并使用IncludeContext.AddChile(myStatement)将其注入当前树中。对include文件中的每个语句行进行循环。棘手的部分是将语句包含在正确的位置,但最终会得到一个完整的树,您可以在下一个监听器类阶段中使用它。

我使用了选项2,到目前为止它对我有效,但我不确定使用addChild方法是最好的方法,因为我真的插入了兄弟姐妹而不是孩子。考虑到这个兄弟姐妹/孩子的问题,也许grosenberg的递归想法是最好的。

相关内容

  • 没有找到相关文章

最新更新