这个页面说:“前缀运算符通常是右结合的,后缀运算符是左结合的”(我强调了一下)。
是否有左结合的前缀运算符或右结合的后缀运算符的真实示例?如果没有,一个假设的运算符会是什么样子,如何解析?
这个页面说:“前缀运算符通常是右结合的,后缀运算符是左结合的”(我强调了一下)。
是否有左结合的前缀运算符或右结合的后缀运算符的真实示例?如果没有,一个假设的运算符会是什么样子,如何解析?
a ≐ a
很少出现。然而,通常可以找到两个函数f(t)
和g(t)
,使得如果f(a) < g(b)
,则a ⋖ b
为真,如果f(a) > g(b)
,则a ⋗ b
为真。(我们不需要担心"仅当",因为可能不存在a
和b
之间的关系,并且通常a ≐ b
使用不同的机制处理:实际上,它意味着完全不同的东西。)
%left
和%right
(yacc/bison/lemon/...声明)构造了函数f
和g
。它们的做法非常简单。如果操作符(OP)是"左结合"的,那么这意味着expr1 OP expr2 OP expr3
必须被解析为<expr1 OP expr2> OP expr3
,在这种情况下,可以从推导中看出OP ⋗ OP
。同样地,如果ROP
是"右结合"的,那么expr1 ROP expr2 ROP expr3
必须被解析为expr1 ROP <expr2 ROP expr3>
,在这种情况下,可以从推导中看出ROP ⋖ ROP
。f
和g
是单独的函数,所以这是可以的:左结合的运算符将具有f(OP) > g(OP)
,而右结合的运算符将具有f(ROP) < g(ROP)
。这可以通过为每个优先级级别使用两个连续的整数,并依次将它们分配给f
和g
(如果运算符是右结合的),或者依次将它们分配给g
和f
(如果运算符是左结合的)来轻松实现。(这个过程将保证f(T)
永远不等于g(T)
。在通常的表达式语法中,唯一的≐关系是在开放和关闭括号类型符号之间,这些通常不会产生歧义,因此在yacc派生语法中不需要为它们分配优先级值。在Floyd解析器中,它们将标记为≐
。)non-terminal-1: PREFIX non-terminal-2;
没有任何非终止符在PREFIX
之前,因此不可能有任何东西是⋗ PREFIX
(因为a ⋗ b
的定义需要在b
之前有一个非终止符)。因此,如果PREFIX
具有结合性,则必须是右结合的。同样,后缀运算符对应于:
non-terminal-3: non-terminal-4 POSTFIX;
POSTFIX
是可关联的,则必须是左关联的。++ ++ a
在语义上是不正确的(除非 a
的 operator++()
已被以某种方式重新定义),但是它已被语法接受(在情况下 operator++()
已被重新定义)。另一方面,new new T
不是语法上正确的。因此,new
是语法上非关联的。
[1] 在 Floyd 语法中,所有非终结符都合并为单个非终结符类型,通常是 expression
。然而,优先关系的定义并不需要这样做,因此我使用了不同的占位符来表示不同的非终结符类型。
+
是恒等操作符,-
是一个数值的取反操作。+-1
相当于+(-1)
,结果为负一。+-1
将等同于(+-)1
。+-
一个含义。语言通常不需要它具有含义并且不会给出含义,但您可以想象一个函数式语言,其中将恒等操作符应用于否定操作符的结果是一个具有与否定操作符完全相同效果的操作符/函数。然后对于这个例子,完整表达式的结果仍然是-1。(f g)(x) == f(g(x))
的两种不同方式。不过,如果您的语言将+-
定义为与-
不同的含义,则关联方向将很重要(我怀疑对于习惯于“通常”语言的人来说,这种语言将非常难懂...)。+-1
。不允许并置运算是另一种方式,它表示(+-)
没有含义。+-1
等同于(+-)1
。它并不代表其他任何意思。如果在您所描述的那种假想语言中,(+-)1
等同于-(+1)
,那也没关系。但这不是“左结合性”的逻辑结果。 - Steve Jessop--
是C#和C++中的一个独立运算符,它不会被解析为两个一元-
的实例。因此,我们对“结合性”的任何讨论都与--1
的词法分析或语法分析无关。实际上,它被分解为两个标记,--
和1
。由于只有一个标记是运算符,因此结合性完全无关紧要。 - Steve Jessop*
、/
和 %
作为一组具有相同优先级的运算符是左结合的。但是,用 +
和 -
的方向关联性来谈论它们的方向关联性是没有意义的。因此,我认为语法术语与优先级关系密切相关。(这与数学意义上的结合律不同;%
在那种意义下根本不是结合的)。 - rici我不想否定我自己提出的问题,但是在看了另外两个答案之后,我是否无意中提出了一个主观性问题,并且实际上左关联前缀和右关联后缀的解释只是undefined?
记住,即使像表达式这样普遍的符号表示法也是建立在一些约定俗成的基础上,如果有一种边缘情况是这些约定从未考虑过的,那么也许,在某个标准委员会制定定义之前,最好假装它不存在。
我不记得有任何左相关的前缀运算符或右相关的后缀运算符。但我可以想象两者都很容易存在。它们不常见,因为人们对运算符的自然看法是:离身体更近的优先应用。
C#/C++语言的简单例子:
~-3
等于 2
,但
-~3
等于 4
这是因为这些前缀运算符是右相关的,对于 ~-3
来说,它意味着首先应用了 - 运算符,然后应用了 ~ 运算符到前面的结果。这将导致整个表达式的值等于 2
假设你可以想象,如果这些运算符是左相关的,那么对于 ~-3
来说,首先应用最左边的运算符 ~
,然后再应用 -
到前面的结果。这将导致整个表达式的值等于 4
[编辑] 回答 Steve Jessop 的问题:
Steve说:“左结合的意思是+-1等同于(+-)1”
我不同意这个观点,认为它完全是错误的。为了更好地理解左结合,请考虑以下示例:
假设我有一种假想的编程语言,其中前缀运算符是左结合的:
@
- 将操作数乘以3
#
- 将7
添加到操作数
那么在我的语言中,以下构造@#5
将等于(5*3)+7 == 22
。如果我的语言是右结合的(像大多数常见的语言一样),那么我将得到(5+7)*3 == 36
如果您有任何问题,请告诉我。
@#
的含义做出了选择。该含义不是左关联的必然结果,你本可以做出另一种选择。 - Steve Jessop@5
)。也许预处理器操作可以做到这种事情,但公式的结合律规则不能。如果您认为它们可以,请考虑一下如果@
是右结合的,但#
是左结合的,则如何处理@#5
。 - Marc van Leeuwen