Java表达式自减/自增运算符解释规则

rad*_*doh 6 java syntax lexer interpretation decrement

这是一个纯粹的理论问题,为了清楚起见,我通常不会编写这段代码。

为什么这个相当模糊的声明是合法的

int a = 1, b = 2;
int c = a---b; // a=0, b=2, c=-1
Run Code Online (Sandbox Code Playgroud)

(它被解释为a-- -b

而这个不是?

int c = a-----b;
Run Code Online (Sandbox Code Playgroud)

第一个陈述也可以解释为a- --b,而第二个陈述显然只有 1 个逻辑解释a-- - --b

还有另一个好奇的:

int c = a--- -b; // a=0, b=2, c=3
Run Code Online (Sandbox Code Playgroud)

(并且int c = a----b; 不是法律声明)

Java中的表达式解释是如何定义的?我尝试搜索 JLS,但尚未找到此问题的答案。

Erw*_*idt 4

介绍

\n\n

为了正确理解这一点,我们需要认识到所有现代编译器都具有两个识别源语言的级别:词汇级别和语法级别。

\n\n

词法级别(“词法分析器”)将源代码拆分为标记:文字(字符串/数字/字符)、运算符、标识符和词法语法的其他元素。这些是编程语言的“单词”和“标点符号”。

\n\n

句法级别(“解析器”)涉及将这些低级词汇标记解释为语法,通常由语法树表示。

\n\n

词法分析器是需要知道标记是“减”标记 ( -) 还是“减”--标记 ( ) 的级别。(减号标记是一元减号还是二进制减号,或者减量标记是后减量标记还是前减量标记,都是在语法级别确定的)

\n\n

像优先级和从左到右与从右到左之类的东西只存在于语法层面。但是否a---ba -- - b或者a - -- b是在词汇层面上决定的。

\n\n

回答

\n\n

Java 语言规范第 3.2 节“词法翻译”中描述了为什么a---b会变成这样a -- - b

\n\n
\n

即使结果最终没有生成正确的程序,每一步都会使用尽可能长的翻译,而另一个词法翻译却可以。

\n
\n\n

这样就形成了尽可能长的词汇标记。

\n\n

在 的情况下a---b,它使标记a, --(最长)然后是唯一可能的下一个标记-,然后b

\n\n

在 的情况下a-----b,它将被翻译成a, --, --, -,b,这在语法上是无效的。

\n\n

进一步引用一下:

\n\n

词法翻译过程有 3 个步骤,在本例中,上述内容适用于本例中的步骤 3:

\n\n
\n

使用以下三个词汇转换步骤将原始 Unicode 字符流转换为标记序列,\n 依次应用这些步骤:

\n\n
    \n
  1. 将 Unicode\n 字符的原始流中的 Unicode 转义符 (\xc2\xa73.3) 转换为相应的 Unicode 字符。格式为 \\uxxxx 的 Unicode 转义符(其中 xxxx 是十六进制值)表示编码为 xxxx 的 UTF-16 代码单元。此转换步骤允许仅使用 ASCII 字符来表达任何程序。

  2. \n
  3. 将步骤 1 生成的 Unicode 流转换为输入字符和行终止符 (\xc2\xa73.4) 的\n 流。

  4. \n
  5. 将步骤 2 产生的输入字符流和行终止符\n 转换为输入元素序列序列(\xc2\xa73.5),其中 \n 在空格 (\xc2\xa73.6) 和注释 (\ xc2\xa73.7) 被丢弃,包括作为句法语法 (\xc2\xa72.3) 的终结符号的标记 (\xc2\xa73.5)。

  6. \n
\n
\n\n

(“输入元素”是“标记”)

\n