存在哪些算法来解析运算符优先级定义为范围的语言?

What algorithms exist for parsing a language where operator precedence is defined as a range?

TLA+ 语言为其运算符优先级使用范围(请参阅 Specifying Systems [PDF] 一书第 271 页的 table。引用:

The relative precedence of two operators is unspecified if their ranges overlap.

因此,例如 $ 运算符(优先级 9-13)与 + 运算符(优先级 10-10)冲突,但 < 运算符(优先级 5-5)不冲突).

运算符优先级范围是形式语言中常用的甚至是预先存在的概念吗?我无法通过一些搜索在网上找到任何关于此的信息。是否有解析此类优先方案或将此方案转换为标准单值优先方案的算法?是否有解析器生成器处理运算符优先级范围?与单值优先级别相比,通过这种方法获得了什么?

我想你可能已经“埋下了线索”。

在那一节之后,它说“如果两个运算符的应用顺序不确定,则表达式是非法的(语法结构不正确),因为它们的优先级范围重叠并且它们不是关联中缀运算符的两个实例."

我读到“未指定为“随心所欲”,这表示它无效

A​​NTLR 是我选择的解析器,我不知道如何让解析器在语法上拒绝这个(在解析阶段)。我可以看到你在哪里应用设置的优先级,然后,一旦你有了一个 ParseTree,你就可以使用在解析树中查找重叠优先级规则的代码来处理它,并在上面抛出错误。我不知道这有什么不好的地方。您仍然会将其标记为错误。只是 ANTLR 会根据您指定的优先级向您提供它对树的解释。

我可能会用一点 ANTLR 侦听器代码示例来扩展这个想法(在 Java 中)。

老实说,我很难理解这种优先方案的打包版本。这很奇怪。

Are operator precedence ranges a commonly-used or even pre-existing concept in formal languages?

没有

事实上,运算符优先级(没有范围)在形式语言中是一个被严重误解的概念。 (当我写完这篇论文时,您将能够在下面看到该声明的更长版本。)

Are there algorithms for parsing such a precedence scheme, or translating this scheme into a standard single-value precedence scheme?

您可以很容易地调整标准调车场算法,只需使用更复杂的优先级比较。在标准算法中,比较可以有三种可能的结果:小于(压入传入符号)、大于(减少左边的表达式)和等于(组合括号或其他括号标记)。 (最后一个结果在大多数在线资源中没有得到很好的描述,并且经常通过添加额外的关联性测试而变得模糊不清。同样,请参见下文。)

通过范围比较,您将有四种可能的结果。您可以将左侧范围的末尾与右侧范围的起点进行比较以表示小于,将左侧范围的起点与右侧范围的末尾进行比较以表示大于。如果这些都不适用,您将有重叠的范围,并且您将不得不以某种方式将括号标记与错误情况区分开来。

Do any parser generators handle operator precedence ranges?

如今只有少数解析器生成器使用运算符优先级 table,尽管调车场算法(或其等效算法)的手写实现非常普遍。 yacc/bison 等解析器生成器在解析器构造时使用优先级声明,通过消除一些可能的解析操作来解决冲突;解析器本身不知道优先级,并严格根据状态转换 table.

进行操作

ANTLR 是最接近在解析过程中使用优先级的解析器生成器。它根据语法描述中的产生式顺序计算自己的优先级数(分别针对每个非终结符)。这些计算出的优先级被翻译成语义谓词,这些语义谓词在解析时执行,以便 select 在不同的解析预测之间。由于没有显式的优先级声明,你没有任何地方可以声明范围,但你可以自己编写语义谓词而不是让 ANTLR 为你生成它们(如果你有显式谓词,它不会尝试插入冲突分辨率代码)。这将允许您使用我上面概述的相同策略,但我认为它不会完全令人满意。

What is gained through this approach compared to single-value precedence levels?

在我看来,没什么。就像其他大多数优先级解析一样,这是一种 hack。如果它适用于特定的语法,那很好,但它会遇到与通用运算符优先级解析相同的问题:你真的不知道你在解析什么语言,因为整个装置更像是一种启发式而不是正式的框架。作为证明,很难找到一个手写的基于优先级的解析器,它在某些时候没有一些(希望有注释的)代码来处理优先级比较没有正确处理的异常,就像很难找到一个现实生活中使用优先级声明的语法,除了最普通的样式之外,在某些地方没有使用优先声明的长注释来解释一个神秘的声明。