torutkのブログ

ソフトウェア・エンジニアのブログ

セミコロンは型宣言

Java読書会で「Java言語仕様(第3版)」を読んでいるので、文法定義についても詳しく見ています。トップレベルの型宣言として、クラス宣言、インタフェース宣言、およびセミコロンの3つが定義されています。

TypeDeclaration:
    ClassDeclaration
    InterfaceDeclaration
    ;

構文解析上は、単独のセミコロンは型宣言の1つとして扱われる(そして意味はない)ということになります。C++風にclass宣言の最後にセミコロンを付けても文法上はOKとなります。

class Foo {
};

Javaコンパイラが実際にトップレベルのセミコロンをどう構文解析しているのか少し興味があったので、Java Compiler APIおよびTree APIを使って調べてみました。

結果、確かに翻訳単位(ソースファイル)に定義したトップレベルの型と並んでセミコロンも検出されました。

以下、Compiler API/Tree APIを使って構文解析結果を覗いてみるサンプルコード

import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.JavacTask;
import java.io.IOException;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class ParseTypes {
    public static final void main(final String[] args) throws IOException {
        JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
        if (javac == null) {
            System.err.println("Java Compiler is not available.");
            return;
        }
        
        StandardJavaFileManager fileManager = javac.getStandardFileManager(
            null, null, null
        );

        if (args.length < 1) {
            System.err.println("Usage: java ParseTypes <source file>");
            return;
        }

        CompilationTask task = javac.getTask(
            null, fileManager, null, null, null,
            fileManager.getJavaFileObjects(args[0])
        );

        JavacTask javacTask = (JavacTask)task;
        for (CompilationUnitTree unitTree : javacTask.parse()) {
            System.out.println("Tree for " + unitTree.getSourceFile());
            for (Tree root : unitTree.getTypeDecls()) {
                System.out.println("\t TypeDeclaration for " + root.getClass() + " : " + root);
            }
        }
    }
}