首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在表达式分析中处理含糊不清但又中断的语法

在表达式分析中处理含糊不清但又中断的语法
EN

Stack Overflow用户
提问于 2018-04-28 14:27:44
回答 1查看 130关注 0票数 1

上下文

最近,我提出了一个问题,我无法在我正在编写的解析器中自己解决。

这个解析器是我正在构建的编译器中的一个组件,问题是编程语言解析所必需的表达式解析。

我的解析器使用递归下降来解析表达式。

问题所在

我使用普通的正则语言解析规则解析表达式,消除了所有规则中的左递归,但是有一个语法“歧义”是我的解析器无法处理的,它涉及泛型。

代码语言:javascript
运行
复制
comparison → addition ( ( ">" | ">=" | "<" | "<=" ) addition )* ;

是用于解析表达式中的比较节点的规则。

另一方面,我决定以这种方式解析泛型表达式:

代码语言:javascript
运行
复制
generic → primary ( "<" arguments ">" ) ;

哪里

代码语言:javascript
运行
复制
arguments → expression ( "," expression )* ;

现在,由于泛型表达式具有更高的优先级,因为它们是语言结构而不是数学表达式,这会导致泛型解析器在不应该解析表达式的情况下尝试解析表达式。

例如,在a<2中,它将"a“解析为标识符类型的主要元素,然后立即找到泛型类型的语法,然后解析该语法,然后失败,因为它找不到结束标记。

这种情况的解决办法是什么?特别是在像C++这样的语言中,泛型也可以有表达式,如果我没有弄错的话,arr<1<2>可能是合法的语法。

这是一种特殊的边缘情况,还是需要修改我不知道的语法定义?

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-04-28 15:39:03

例如,在a<2中,它会将"a“解析为标识符类型的一个主要元素,然后自动找到泛型类型的语法,然后解析它,然后失败,因为它找不到结束标记。

这个特殊的情况可以通过回溯或无限制的前瞻来解决。正如您所说的,解析器在将其解释为泛型时最终会失败,因此,当这种情况发生时,您可以返回并将其解析为关系运算符。展望变体是在看到<时向前看,以检查<后面是否有逗号分隔的类型名称和>,并且只有在这种情况下才进入泛型规则。

然而,如果这两种解释在语法上都是有效的(这意味着语法实际上是模棱两可的),那么这种方法就不再有效。这方面的一个例子是x<y>z,它既可以是类型为x<y>的变量z的声明,也可以是两个比较。这个例子有点不成问题,因为后者的意思几乎不是预期的意思,所以总是将其解释为前者是可以的(例如,在C#中就是这样)。

现在,如果我们允许表达,它会变得更复杂。对于x<y>z来说,可以很容易地说,这永远不应该被解释为两个比较,因为将比较的结果与其他东西进行比较是没有意义的(在许多语言中,在Booleans上使用关系运算符都是一个类型错误)。但是,对于像a<b<c>()这样的函数,有两种解释可能都是有效的:要么a是用泛型参数b<c调用的泛型函数,要么是带有泛型参数c的泛型函数( a与调用该函数的结果相比较)。在这一点上,仅靠句法规则就不可能解决这种模糊性:

为了支持这一点,您需要检查给定的primary是否引用泛型函数,并在此基础上做出不同的解析决策,或者让解析器在出现歧义的情况下生成多棵树,然后在稍后阶段选择正确的树。前一个选项意味着解析器需要跟踪当前定义的泛型函数(以及作用域中的泛型函数),然后只有当给定的primary是其中一个函数的名称时,才进入泛型规则。请注意,如果允许在使用函数后定义函数,则这将变得更加复杂。

因此,总之,将表达式支持为泛型参数需要在解析时跟踪哪些函数的作用域,并使用这些信息来做出解析决策(意味着解析器对上下文敏感)或生成多个可能的AST。没有表达式,您可以保持上下文的自由和明确,但需要回溯或任意向前看(这意味着它是LL(*))。

由于这两种语言都不理想,一些语言改变了使用显式类型参数调用泛型函数的语法,使其成为LL(1)。例如:

  • Java将方法的泛型参数列表放在方法名称之前,即obj.<T>foo()而不是obj.foo<T>()
  • 锈蚀需要在泛型参数列表之前使用::foo::<T>()而不是foo<T>()
  • Scala对泛型使用方括号,没有其他用途(数组下标使用括号):foo[T]()而不是foo<T>()
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50077588

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档