在任何编程语言教科书中,我们总是被告知该语言中的每个运算符如何具有左结合性或右结合性。结合性似乎是任何运算符的基本属性,无论其需要多少操作数。在我看来,我们可以将任何关联性分配给任何运算符,无论我们如何将关联性分配给其他运算符。
但为什么会这样呢?也许举个例子更好。假设我想设计一种假设的编程语言。以这种任意方式为这些运算符分配关联性是否有效(全部具有相同的优先级):
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 这样的表达式如何被我的假设解析器括起来?以及为什么。
EDIT:
第一个示例 (2+2!3+5*6/3-5!3!3-3*2) 不正确。也许忘记一元操作,让我这样说,我们可以像上面那样分配具有相同优先级不同结合性的运算符吗?如果是,如何评估 2+3-4*5/3+2 的示例?因为大多数编程语言似乎都为具有相同优先级的运算符分配相同的结合性。但我们总是谈论运算符关联性,就好像它是单个运算符的属性,而不是优先级的属性。
让我们记住关联性的含义。采取任何运算符,例如@
。众所周知,它的结合性是消除形式表达式歧义的规则a @ b @ c
: if @
是左结合的,它被解析为(a @ b) @ c
;如果它是右结合词,a @ (b @ c)
。它也可以是非关联的,在这种情况下a @ b @ c
是一个语法错误。
如果我们有两个不同的运算符呢?@
and #
?如果其中一个的优先级高于另一个,则无需多说,关联性无需做任何工作;优先级负责消除歧义。然而,如果它们具有相同的优先级,我们就需要关联性来帮助我们。简单的情况分为三种:
- 如果两个运算符都是左结合的,
a @ b # c
means (a @ b) # c
.
- 如果两个运算符都是右结合的,
a @ b # c
means a @ (b # c)
.
- 如果两个运算符都是非结合的,那么
a @ b @ c
是一个语法错误。
在其余情况下,运算符不同意关联性。哪个操作员的选择优先?您可能会设计这样的关联性优先规则,但我认为最自然的规则是声明任何此类情况语法错误。毕竟,如果两个运算符具有相同的优先级,为什么其中一个运算符的结合优先级高于另一个运算符呢?
根据我刚刚给出的自然规则,您的示例表达式是语法错误。
现在,我们当然可以为相同优先级的运算符分配不同的结合性。但是,这意味着存在相同优先级的运算符组合(例如您的示例!),这是语法错误。大多数语言设计者似乎更愿意避免这种情况,并将相同的结合性分配给所有具有相同优先级的运算符;这样,所有组合都是合法的。我认为这只是美学。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)