基于ANTLR4语法实现语言自动完成

时间:2016-05-06 09:12:59

标签: c# .net parsing antlr4

我想知道是否有任何用于命令行界面(控制台)的TAB自动完成解决方案(google搜索我没有找到),使用ANTLR4语法来预测下一个术语(如在REPL中)模型)。

我为开源数据库编写了PL / SQL语法,现在我想实现一个数据库的命令行界面,为用户提供根据语法完成语句的功能,或者最终发现要使用的正确数据库对象名称(例如,表名,触发器名称,列名等)。

感谢您指出我正确的方向。

3 个答案:

答案 0 :(得分:4)

实际上有可能! (当然,基于语法的复杂性。)自动完成和ANTLR的问题是你没有完整的表达式而你想要解析它。如果你有完整的表达方式,那么知道什么样的元素在什么地方并且知道在这样的地方可以使用什么就不是什么大问题。但是你没有完整的表达,你无法解析不完整的表达式。所以你需要做的是将输入包装到一些包装器/辅助器中,它将完成表达式以创建一个可解析的表达式。请注意,为了完成表达式而添加的任何内容对您来说都很重要 - 您只会要求成员最后写入真正的字符。

所以:

A)创建将改变它的包装器(excel公式)'= If('into'= If()'

B)解析包裹的输入

C)意识到你在第一个参数

的IF函数中

D)返回所有可以进入那个地方的东西。

它确实有效,我已经完成了几种简单语言的intellisense编辑器。有比这更多的基础设施,但基本的想法是我写的。只有小心,如果语法非常复杂,写包装器并不容易,如果不是不可能的话。在那种情况下,看看Papa Carlo项目。 http://lakhin.com/projects/papa-carlo/

答案 1 :(得分:2)

如前所述,自动完成基于给定位置的跟随集,仅仅因为这是我们在语法中定义的有效语言。但这只是这项任务的一小部分。你需要的是上下文(正如Sam Harwell写的那样:它是一个语义过程,而不是语法过程)。此信息独立于解析器。并且由于解析器用于解析有效输入(并且在自动完成期间,您大部分时间都是无效输入),因此它不适合执行此任务。

知道在给定位置可以跟随哪个令牌对于控制整个过程是有用的(例如,如果只出现一个字符串,你不想显示建议),但大部分时间不是你真正想要的建议(关键字除外)。如果在当前位置可以使用ID,则它不会告诉您实际允许的ID(变量名称?命名空间等等)。所以你需要的只是三件事:

  1. 符号表,为您提供按范围排序的所有可能名称。创建这很大程度上取决于解析的语言。但这是一个解析器非常有用的任务。您可能希望缓存此信息,因为运行此分析步骤非常耗时。
  2. 确定调用自动完成时的范围。你也可以在这里使用解析器(可能与步骤1结合使用)。
  3. 确定要显示的符号类型。许多人认为这是解析器可以为您提供所有必要信息的地方(以下集合)。但如上所述,这不是真的(除了关键词)。
  4. 在我的博文Universal Code Completion using ANTLR3中,我特别提到了第3步。在那里我不使用解析器,但是模拟一个解析器,只有当解析器没有时才会停止,但是当达到插入位置时(因此输入必须是有效的语法)那一点)。在到达插入符后,收集过程开始,不仅收集终端节点(用于关键字),还查看规则名称以了解需要收集的内容。使用特定的规则名称是我将语境放入语法的方法,因此当收集代码找到规则 table_ref 时,它知道它不需要在规则链中走得更远(到最终的ID令牌),但可以使用此信息提供表格列表作为建议。

    使用ANTLR4,事情可能变得更加简单。我自己还没有使用它,但解析器解释器在这里可能是一个很大的帮助,因为它实际上是我在我的实现中手动完成的(使用ANTLR3后端)。

答案 2 :(得分:0)

这可能很难做到。

从根本上说,你想使用一些解析器来预测接下来会发生什么?#34;显示为自动完成。这必须至少预测用户输入停止时FIRST令牌是什么。

对于ANTLR,我认为这将非常困难。原因是ANTLR生成基本上是程序性的递归下降解析器。因此,在运行时,当您需要确定哪些FIRST令牌时,您必须检查生成的解析器的过程源代码。那种方式就是疯狂。

blog entry声称通过收集错误报告而不是检查解析器代码来实现自动完成。这是一个有趣的想法,但我不明白他的方法是如何工作的,我无法看到它将如何提供所有可能的第一个令牌;它可能会获得一些。这SO answer证实了我的直觉。

Sam Harwell discusses how he has tackled this;他是ANTLR4实施者之一,如果有人可以做这项工作,他可以​​。如果他到达ANTLR内部以提取他需要的信息,我不会感到惊讶;作为一名ANTLR实施者,他肯定知道在哪里可以利用。你不太可能如此有条理。即便如此,他并没有真正描述他所做的细节。祝你好运复制。你可能会问他到底做了什么。

你想要的是一个解析引擎,其FIRST令牌信息可以直接使用(解析器生成器可以生成它)或基于解析器状态可计算。这实际上可能与自下而上的解析器有关,例如LALR(k);您可以构建一个遍历状态表并计算此信息的算法。 (我们使用我们的DMS软件重新设计工具包为其GLR解析器精确地生成语法错误报告,说明&#34;缺少令牌,可以是这些 [set]&#34;)< / p>