3

在任何编程语言教科书中,我们总是被告知该语言中的每个运算符如何具有左关联性或右关联性。似乎关联性是任何运算符的基本属性,无论它采用多少操作数。在我看来,无论我们如何将关联性分配给其他运算符,我们都可以将任何关联性分配给任何运算符。

但为什么会这样呢?也许举个例子更好。假设我想设计一种假设的编程语言。以这种任意方式为这些运算符分配关联性是否有效(都具有相同的优先级):

unary operator: 
! right associative 
binary operators:
+ left associative
- right associative
* left associative 
/ right associative

!+ - * / 是我的 5 个运算符都具有相同的优先级。

如果是的话,我假设的解析器如何将像 2+2!3+5*6/3-5!3!3-3*2 这样的表达式括起来?以及为什么。

编辑:

第一个示例 (2+2!3+5*6/3-5!3!3-3*2) 不正确。也许忘记一元操作,让我这样说吧,我们可以像我上面那样分配具有相同优先级不同关联性的运算符吗?如果是,将如何评估示例,例如 2+3-4*5/3+2?因为大多数编程语言似乎为具有相同优先级的运算符分配了相同的关联性。但是我们总是谈论操作员关联性,就好像它是单个操作员的属性——而不是优先级的属性。

4

2 回答 2

5

让我们记住关联性的含义。以任何运算符为例@。众所周知,它的结合性是消除形式表达式歧义的规则a @ b @ c:如果@是左结合的,则将其解析为(a @ b) @ c; 如果它是正确的联想,a @ (b @ c). 它也可能是非关联的,在这种情况下a @ b @ c是语法错误。

如果我们有两个不同的运算符,比如说@and ,会#怎样?如果一个优先级高于另一个,则无话可说,关联性没有工作可做;优先级负责消除歧义。但是,如果它们具有相同的优先级,我们需要关联性来帮助我们。有三种简单的情况:

  • 如果两个运算符都是左关联的,a @ b # c则表示(a @ b) # c.
  • 如果两个运算符都是右结合的,a @ b # c则表示a @ (b # c).
  • 如果两个运算符都是非关联的,a @ b @ c则为语法错误。

在其余情况下,运营商不同意关联性。哪个运营商的选择优先?你可能会设计出这样的关联性优先规则,但我认为最自然的规则是声明任何这样的案例语法错误。毕竟,如果两个运算符具有相同的优先级,为什么一个会比另一个具有关联性优先级?

根据我刚刚给出的自然规则,您的示例表达式是语法错误。

现在,我们当然可以为具有相同优先级的运算符分配不同的关联性。但是,这意味着存在相同优先级的运算符组合(例如您的示例!)是语法错误。大多数语言设计者似乎更愿意避免这种情况,并为所有具有相同优先级的运算符分配相同的关联性。这样,所有组合都是合法的。我认为这只是美学。

于 2012-07-29T20:27:18.460 回答
1

您必须以某种方式定义关联性,并且大多数语言选择“自然地”分配关联性(和优先级) - 以匹配普通数学的规则。

然而,也有明显的例外——APL 具有严格的从右到左的关联性,所有运算符都具有相同的优先级。

于 2012-07-28T11:26:03.617 回答