减量/增量运算符的Java表达式解释规则
这是一个纯粹的理论问题,为了清晰起见,我不会正常编写此代码 为什么这一模棱两可的声明是合法的减量/增量运算符的Java表达式解释规则,java,syntax,lexer,decrement,interpretation,Java,Syntax,Lexer,Decrement,Interpretation,这是一个纯粹的理论问题,为了清晰起见,我不会正常编写此代码 为什么这一模棱两可的声明是合法的 int a = 1, b = 2; int c = a---b; // a=0, b=2, c=-1 (它被解释为a--b) 这个不是吗 int c = a-----b; 第一个语句也可以解释为a--b,而第二个语句显然只有一个逻辑解释,即a--b 还有一个奇怪的问题: int c = a--- -b; // a=0, b=2, c=3 (而且intc=a---b;不是一项法律声明) 如何在Jav
int a = 1, b = 2;
int c = a---b; // a=0, b=2, c=-1
(它被解释为a--b
)
这个不是吗
int c = a-----b;
第一个语句也可以解释为a--b
,而第二个语句显然只有一个逻辑解释,即a--b
还有一个奇怪的问题:
int c = a--- -b; // a=0, b=2, c=3
(而且intc=a---b;
不是一项法律声明)
如何在Java中定义表达式解释?我尝试搜索JLS,但没有找到答案。要回答这个问题,我们必须看看Java 本例的重要规则如下:
- 表达式从左到右求值
Postfix运算符比expr--
加法运算符具有更高的优先级a-b
因此表达式
a--b
的计算结果如下:((a--)b
,这是非法的
您可以在声明中使用大括号来绕过这些规则:(a-)-(-b)
将是法律声明。引言
要正确理解这一点,我们需要认识到,所有现代编译器都有两个识别源语言的级别,即词汇级别和语法级别
词法层(“lexer”)将源代码拆分为标记:文本(string/numeric/char)、运算符、标识符和词法语法的其他元素。这些是编程语言的“单词”和“标点符号”
语法层(“解析器”)负责将这些低级词汇标记解释为语法,通常由语法树表示
lexer是需要知道令牌是“减”令牌(-
)还是“减量”(-
)令牌的级别。(减号标记是一元减号还是二元减号,或者减量标记是减量后标记还是减量前标记,在语法层面上确定)
像优先权和从左到右与从右到左这样的东西只存在于句法层面。但是a--b
是a--b
还是a--b
取决于词汇层面
答复
为什么a--b
变为a--b
,请参见:
在每个步骤中使用最长的可能的翻译,即使
结果不会最终生成正确的程序,而另一个
词法翻译是一种有效的翻译方法
这样就形成了最长的词汇标记
在a--b
的情况下,它使令牌a
,--
(最长),然后是唯一可能的下一个令牌-
,然后是b
在a--b
的情况下,它将被翻译成a
,--
,--
,--
,b
,这在语法上是无效的
再引述一点:
词汇翻译过程有3个步骤,在本例中,上述步骤适用于本例中的步骤3:
原始Unicode字符流被转换为
标记,使用以下三个词汇翻译步骤
依次应用:
(“输入元素”是“标记”)要搜索的神奇单词是
java操作符优先级
。我猜a--b
解释为:((a--)b--)b
,这是不合法的。@KlasLindbäck不,不是。神奇的单词是“lexer”,而不是解析器。lexer是识别标记(数字、标识符、运算符等)的级别。直到解析树的构建,运算符优先级才起作用。@ErwinBolwidt我站在正确的位置<代码>a---b不会compile@AndrewTobilko是的,我知道。在这篇文章中,我试图解释为什么它没有编译…运算符优先级不适用于lexer。它确保a-b--
被解释为a-(b--)
而不是(a-b--
),但它不能确保a--b
被解释为a--b
而不是a--b
@ErwinBolwidt这就是为什么我提到表达式是从左到右求值的原因,Erwin。看起来我做了一个错误的假设,java编译器将尝试理解给定的表达式,而不是使用一些简单的规则来解析表达式,即使它不创建合法的语句。