如何在antlr4中的侦听器类中插入标记或上下文

时间:2014-10-26 18:21:38

标签: antlr antlr4

我有一个解析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启动一个新的解析器,然后以某种方式将标记/上下文插入到我当前的。(/ p>

这样做的正确方法是什么?

2 个答案:

答案 0 :(得分:0)

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

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中,检索新的当前状态,并根据需要验证/检查错误。

由于状态模型封装了你的符号表等,你在穿过森林时保持连续性 - 递归实际上是免费的。

应该提到的是,相对于符号表,处理执行包含与调用子例程基本相同。

相关:Symbol Table

答案 1 :(得分:0)

我有两个解决方案,我拿了最后一个我要提到的。此外,GRosenBerg也有一个好主意。

1)使用TokenStreamRewriter并在enterIncludeStatement中使用重写器insertBefore,insertAfter和/或replace方法。在该特定侦听器对象的遍历结束时,调用重写器getText(),这将为您提供组合字符串。您将不得不重新分析该文本以进入下一个侦听器传递。

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

我使用了选项2,它为我工作到目前为止,但我不确定使用addChild方法是最好的方法,因为我真的插入兄弟姐妹而不是孩子。鉴于这个兄弟姐妹/孩子的问题,那么格罗森伯格的递归思想可能是最好的。