解析注释时可能导致Java编译器失败的原因是什么?

时间:2015-09-07 16:15:20

标签: java unicode comments grammar lexical-analysis

以下代码是有效的Java程序。

public class Foo
{
    public static void \u006d\u0061\u0069\u006e(String[] args)
    {
        System.out.println("hello, world");
    }
}

使用Unicode转义序列编写main标识符。它编译并运行良好。

$ javac Foo.java && java Foo
hello, world

虽然这个问题可能不需要以下细节,但我会分享它,以防有人对此感到好奇。我在Debian 8.0上使用OpenJDK的Java编译器,但我在这个问题中的要求应该适用于任何Java编译器。

$ javac -version
javac 1.7.0_79
$ readlink -f $(which javac)
/usr/lib/jvm/java-7-openjdk-amd64/bin/javac

以下程序是错误的,因为用于编写m的{​​{1}}的转义序列无效。

main

编译器抱怨非法的unicode序列。

public class Foo
{
    public static void \u6d\u0061\u0069\u006e(String[] args)
    {
        System.out.println("hello, world");
    }
}

让我感到惊讶的是,即使非法的unicode转义序列似乎出现在评论中,以下程序也无效。

$ javac Foo.java && java Foo
Foo.java:3: error: illegal unicode escape
    public static void \u6d\u0061\u0069\u006e(String[] args)
                           ^
Foo.java:3: error: invalid method declaration; return type required
    public static void \u6d\u0061\u0069\u006e(String[] args)
                            ^
2 error

这是错误。

public class Foo
{
    // This comment contains \u6d.
    public static void main(String[] args)
    {
        System.out.println("hello, world");
    }
}

编译器抱怨非法unicode转义序列,尽管它似乎在评论中。

当我们看到JLS §3.7中如何定义行尾注释时,此行为背后的原因就变得清晰了。

$ javac Foo.java && java Foo
Foo.java:3: error: illegal unicode escape
    // This comment contains \u6d.
                                 ^
1 error

JLS §3.4定义EndOfLineComment: / / {InputCharacter} 如下。

InputCharacter

最后,JLS §3.3定义InputCharacter: UnicodeInputCharacter but not CR or LF 如下。

UnicodeInputCharacter

因此,词法分析器需要首先识别Unicode转义序列以识别注释,如果发现非法的Unicode转义序列,则词法分析将失败并发生错误。因此,编译器永远不会继续识别包含非法Unicode转义序列的注释。

虽然我曾经认为从评论开头(比如说UnicodeInputCharacter: UnicodeEscape RawInputCharacter UnicodeEscape: \ UnicodeMarker HexDigit HexDigit HexDigit HexDigit UnicodeMarker: u {u} HexDigit: (one of) 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F RawInputCharacter: any Unicode character )到结尾的所有内容都被忽略了,但上面的例子表明情况并非如此,因为词法分析器必须识别Unicode转义序列在注释开始和注释结束之间,非法的Unicode转义序列可能导致词法分析失败。

在解析注释时还有什么可能导致编译器失败?

1 个答案:

答案 0 :(得分:2)

短:

没什么(没有 else )。

长:

逻辑上,{<1}}转义序列在词法处理(扫描/标记化)发生之前处理。根据{{​​3}}:

  

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

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

  2.   
  3. 将步骤1产生的Unicode流转换为输入字符和行终止符流(§3.4)。

  4.   
  5. 将步骤2产生的输入字符和行终止符流转换为输入元素序列(第3.5节),在白色空间(第3.6节)和注释(第3.7节)被丢弃之后,令牌(§3.5),它们是句法语法的终点符号(§2.3)。

  6.   

从技术上讲,您示例中的\u NOT 是评论的一部分。是否属于该评论是在之后确定的将其转换回unicode代码点。但遗憾的是它失败了。

作为证明,下面的课应该编译:

\u6d