如何使用 ANTLR 构建交互式解析器?

How can I build an interactive parser with ANTLR?

我一直在研究 Java 和 ANTRL4,它们是构建解析器的非常好的组合。但是,当我测试它们时,我注意到直到我向输入发送 EOF(例如 Mac 上的 CMD-D)后,解析才会开始。这对于解析文件来说很好,但我可以很容易地想象使用 ANTLR 可以非常快速地构建诸如命令行 shells/processors 之类的工具。但它是不可行的,除非我可以让它在输入字符时进行解析(这样事情就会在 RETURN 之后发生,或者如果有人想完成命令,甚至在 TAB 之后发生)。

有人知道怎么做吗?

使用 Antlr4 的最简单方法 'interactively' 是认识到解析操作非常快,并且在温暖的 VM 中,重新实例化解析器也非常快。事实上,速度足以在每次击键之间重新解析整个输入文本。

基本策略是,从一个按键事件中,抓取整个当前输入文本并在非显示线程中处理它。如果在下一个键事件之前处理没有完成,则丢弃处理线程并启动一个新线程。当处理迭代完成时,将下一个键事件设置为缓冲(根据需要)并将结果应用于输入文本。

持续的击键流不太可能超过每次按键事件 100 毫秒(约 80 wpm)。在我的系统上,使用 Java.g4 语法重复简单解析编辑器的 'page' 代码平均耗时 5 毫秒左右。即使处理相当重要,后台线程也很少需要超过 25 毫秒才能完成。当然是YMWV.

更新

如果需要连续流处理——而不是 'interactive'——那么 Antlr 可以适应该目的。这将需要满足 Lexer & TokenStream 接口但等待实际输入数据以响应解析器的 getCurrentToken() 的最小自定义词法分析器——解析器的主要功能是从词法分析器中获取下一个标记。

    StreamLexer tokens = new StreamLexer(yourInputStream); // custom lexer
    YourParser parser = new YourParser(tokens);
    parser.removeErrorListeners(); // remove ConsoleErrorListener
    parser.addErrorListener(new YourErrorListener());
    parser.setErrorHandler(new YourParserErrorStrategy());
    parser.start();

没有实际的词法分析器语法——自定义词法分析器只是将每个输入字符包装为一个单独的标记,并相应地编写解析器规则。

实际上,这将标准的 Antlr 解析器变成了语法定义的 'Push-Parser'。速度将受限于解析器匹配函数的 运行 时间或输入流的数据速率,以较慢者为准。

要实现任何明显更快的解析速度,可能需要专门构建的状态机。