ANTLR4:从语言中提取表达式

ANTRL4: Extracting expressions from languages

我有一种编程语言,其中包含许多结构,但我只对从该语言中提取表达式感兴趣。

是否可以在不必编写整个语法的情况下做到这一点?

是的,有可能。你想要所谓的“岛解析器”。 https://en.wikipedia.org/wiki/Island_grammar。你可能实际上没有 决定这样做,详情见下文。

基本思想是为您关心的语言部分(“岛屿”)提供详细的语法规则,为其余部分(“水”)提供草率的规则。

详细的语法规则......你写的就像平常写的一样。这包括构建词法分析器和解析器来解析您想要的部分。

“水”部分是通过定义草率的词素来尽可能多地实现的。您可能需要不止一个,并且您可能必须处理嵌套结构,例如,涉及“(”...)”、“[”...”] 和“{”...“}”的事情,您将最终使用这些结构边界的显式标记,以及跟踪嵌套的递归语法规则(因为作为 FSA 的词法分析器通常无法跟踪它)。

开始时不明显,但在你深入到这个混乱中后会痛苦地明显地跳过长注释体,尤其是带有语言允许的各种引号的字符串文字(考虑 Python顶部集合)和里面的转义序列。当您发现您的 lex 是与内插表达式分开的原始字符串内容时,您会被允许内插字符串的语言所困扰,因为这些通常也是嵌套结构。 PHP 和 C# 允许在其内插字符串中使用任意表达式....包括本身可以包含的表达式...更多内插字符串!

好的一面是,如果您忽略为梦想和处理所有有趣案件而付出的汗水劳动,那么所有这一切在技术上并不难。

...但是...考虑到典型的解析目标,孤岛语法在用于此目的时往往会分崩离析。

要处理表达式,您通常需要为标识符提供类型的语言声明。如果你把它们留在“海洋”部分......你不会得到类型声明,现在很难对你的表达式进行推理。如果你在处理java,遇到了(a+b),那是加法还是字符串拼接?没有类型信息你根本不知道。

如果您决定需要类型信息,那么现在您需要变量和类型声明的详细语法。突然之间,您离完整的解析器更近了。在某些时候,您可以保释并构建一个完整的解析器;那你就不用考虑自己是否作弊了

你没有提到你的语言,但很有可能这里有它的 ANTLR 语法 ANTLR Grammars

这些语法将解析源的全部内容(通过这样做,您可以避免一些“混乱”,这些“混乱”可能伴随着尝试决定何时进入和退出孤岛语法,这可能特别混乱用于表达式,因为它们可以出现在典型源文件中的许多地方。)

一旦你有了生成的 ParseTree,ANTLR 提供了一个监听器功能,允许你调用一个方法来遍历树并只为你感兴趣的那些部分回调你。在你的情况下,这将是表达式。

快速搜索 ANTLR Listeners 应该会找到一些关于如何编写满足您需要的 Listener 的资源。 (This 是一篇很短的文章,涵盖了基础知识(在这种情况下,当你只对方法感兴趣时,但表达式会相似。当然还有其他)。