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,但尚未找到此问题的答案。
为了正确理解这一点,我们需要认识到所有现代编译器都具有两个识别源语言的级别:词汇级别和语法级别。
\n\n词法级别(“词法分析器”)将源代码拆分为标记:文字(字符串/数字/字符)、运算符、标识符和词法语法的其他元素。这些是编程语言的“单词”和“标点符号”。
\n\n句法级别(“解析器”)涉及将这些低级词汇标记解释为语法,通常由语法树表示。
\n\n词法分析器是需要知道标记是“减”标记 ( -
) 还是“减”--
标记 ( ) 的级别。(减号标记是一元减号还是二进制减号,或者减量标记是后减量标记还是前减量标记,都是在语法级别确定的)
像优先级和从左到右与从右到左之类的东西只存在于语法层面。但是否a---b
是a -- - b
或者a - -- b
是在词汇层面上决定的。
Java 语言规范第 3.2 节“词法翻译”中描述了为什么a---b
会变成这样a -- - b
:
\n\n\n即使结果最终没有生成正确的程序,每一步都会使用尽可能长的翻译,而另一个词法翻译却可以。
\n
这样就形成了尽可能长的词汇标记。
\n\n在 的情况下a---b
,它使标记a
, --
(最长)然后是唯一可能的下一个标记-
,然后b
。
在 的情况下a-----b
,它将被翻译成a
, --
, --
, -
,b
,这在语法上是无效的。
进一步引用一下:
\n\n词法翻译过程有 3 个步骤,在本例中,上述内容适用于本例中的步骤 3:
\n\n\n\n\n使用以下三个词汇转换步骤将原始 Unicode 字符流转换为标记序列,\n 依次应用这些步骤:
\n\n\n
\n- \n
将 Unicode\n 字符的原始流中的 Unicode 转义符 (\xc2\xa73.3) 转换为相应的 Unicode 字符。格式为 \\uxxxx 的 Unicode 转义符(其中 xxxx 是十六进制值)表示编码为 xxxx 的 UTF-16 代码单元。此转换步骤允许仅使用 ASCII 字符来表达任何程序。
- \n
将步骤 1 生成的 Unicode 流转换为输入字符和行终止符 (\xc2\xa73.4) 的\n 流。
- \n
将步骤 2 产生的输入字符流和行终止符\n 转换为输入元素序列序列(\xc2\xa73.5),其中 \n 在空格 (\xc2\xa73.6) 和注释 (\ xc2\xa73.7) 被丢弃,包括作为句法语法 (\xc2\xa72.3) 的终结符号的标记 (\xc2\xa73.5)。
(“输入元素”是“标记”)
\n