[インデックス 1191] ファイルの概要
このコミットは、Go言語のコンパイラ(gc
)の構文解析器において、パッケージインポートの「隠された」リストが空であることを許容するように文法規則を修正するものです。具体的には、src/cmd/gc/go.y
ファイル内のYacc文法定義から、hidden_import_list_r
規則の非再帰的なベースケースを削除することで、このリストがゼロ個の要素を持つことを許可します。
コミット
commit 10002bb0fbd9897fe0a3bb54b022306bc9d6c3fe
Author: Russ Cox <rsc@golang.org>
Date: Wed Nov 19 14:27:48 2008 -0800
accept empty list of package imports.
R=ken
OCL=19617
CL=19617
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/10002bb0fbd9897fe0a3bb54b022306bc9d6c3fe
元コミット内容
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -1624,7 +1624,6 @@ import_stmt_list_r:
|\timport_stmt_list_r osemi import_stmt
hidden_import_list_r:
---\thidden_import
|\thidden_import_list_r hidden_import
hidden_funarg_list_r:
変更の背景
プログラミング言語の構文解析において、リスト構造を扱う場合、そのリストが空であるケースを許容するかどうかは重要な設計判断です。このコミットが行われた2008年11月は、Go言語がまだ初期開発段階にあり、文法やコンパイラの細部が頻繁に調整されていた時期です。
この変更の背景には、おそらく以下のような理由が考えられます。
- 文法の柔軟性向上:
hidden_import_list_r
が常に少なくとも1つのhidden_import
を要求していた場合、特定のコードパターンや、hidden_import
が全く存在しない状況を正しく解析できない、または不必要に複雑な構文を要求する可能性がありました。空リストを許容することで、文法がより柔軟になり、多様な入力に対応できるようになります。 - コード生成の簡素化: コンパイラやコードジェネレータがGoコードを生成する際、
hidden_import
が不要な場合に、強制的にダミーのhidden_import
を生成する必要がなくなります。これにより、生成されるコードがよりクリーンになり、ジェネレータの実装も簡素化されます。 - エラーハンドリングの改善: 構文解析器が空のリストを予期しない場合、それがエラーとして扱われる可能性があります。空リストを明示的に許容することで、不必要な構文エラーを回避し、より堅牢なパーサーを構築できます。
- 文法の一貫性: 他のリスト構造が空を許容している場合、
hidden_import_list_r
も同様に空を許容することで、文法全体の一貫性が保たれます。
この変更は、Go言語のコンパイラが、より広範な有効なGoプログラムを正しく解析できるようにするための、細かながらも重要な改善点と言えます。
前提知識の解説
このコミットを理解するためには、以下の概念について知っておく必要があります。
- Go言語 (Golang): Googleによって開発された静的型付けのコンパイル型プログラミング言語です。シンプルさ、効率性、並行処理のサポートを重視しています。このコミットはGo言語の初期段階(オープンソース公開前)のものであり、コンパイラの内部構造に関する変更です。
- Goコンパイラ (gc): Go言語の公式コンパイラの実装の一つです。Go言語のソースコードを機械語に変換する役割を担います。
src/cmd/gc
ディレクトリは、このコンパイラのソースコードが格納されている場所です。 - Yacc (Yet Another Compiler Compiler) / Bison: Yaccは、文法定義からLALRパーサー(構文解析器)を自動生成するツールです。BisonはYaccのGNU版です。プログラミング言語のコンパイラやインタプリタのフロントエンド(字句解析と構文解析)を実装する際によく用いられます。
.y
拡張子のファイルは、Yacc/Bisonの文法定義ファイルを示します。このファイルには、言語の構文規則がBNF(バッカス・ナウア記法)に似た形式で記述されます。- Yacc/Bisonは、これらの文法規則を基に、C言語などのソースコードを生成し、それがコンパイラの一部としてコンパイルされます。
- 文法規則 (Grammar Rules): プログラミング言語の構文は、一連の文法規則によって定義されます。Yaccファイルでは、非終端記号(構文の抽象的な要素、例:
expression
,statement
)と終端記号(実際のトークン、例:IDENTIFIER
,+
,;
)を用いて規則が記述されます。hidden_import_list_r
: これは非終端記号であり、「隠されたインポートのリスト」を表します。末尾の_r
は、しばしば再帰的な規則であることを示唆します。hidden_import
: これは非終端記号であり、「隠されたインポート」という単一の構文要素を表します。|
: Yacc文法において、|
は「または」を意味し、一つの非終端記号が複数の異なる形式で構成されうることを示します。- 再帰的定義:
A: A B
のような形式は、A
がB
のリストであることを表現する一般的な方法です。例えば、list: item | list item
は、item
が1つ以上あるリストを意味します。
技術的詳細
src/cmd/gc/go.y
ファイルは、Goコンパイラの構文解析器の核となる部分を定義しています。このファイルはYaccによって処理され、Go言語のソースコードがどのように構造化されているかをコンパイラに教えます。
変更前のhidden_import_list_r
の定義は以下のようでした。
hidden_import_list_r:
hidden_import
|\thidden_import_list_r hidden_import
この定義は、hidden_import_list_r
が以下のいずれかの形式で構成されることを意味します。
hidden_import
: これはリストのベースケースであり、hidden_import_list_r
が少なくとも1つのhidden_import
を含むことを強制します。つまり、空のhidden_import_list_r
は文法的に許容されませんでした。hidden_import_list_r hidden_import
: これは再帰的なケースであり、既存のhidden_import_list_r
にさらにhidden_import
が追加されることを意味します。
このコミットでは、最初の行であるhidden_import
が削除されました。変更後のhidden_import_list_r
の定義は以下のようになります。
hidden_import_list_r:
/* empty */
|\thidden_import_list_r hidden_import
(Yaccでは、規則の最初のプロダクションが空の場合、それは空文字列にマッチすることを意味します。ここではコメントで/* empty */
と示しましたが、実際にはその行が削除されたことで空のプロダクションが暗黙的に定義されます。)
この変更により、hidden_import_list_r
は以下のいずれかの形式で構成されることになります。
- 空文字列: これが新しいベースケースです。
hidden_import_list_r
が何も含まない(空である)ことを許容します。 hidden_import_list_r hidden_import
: これは以前と同じ再帰的なケースです。
結果として、この修正はGoコンパイラの構文解析器が、hidden_import
が全く存在しない場合でも、hidden_import_list_r
という構文要素を正しく認識し、構文エラーとしないようにします。これは、Go言語の文法がより柔軟になり、特定のコンテキストでインポートリストが空である状況を自然に扱えるようになったことを意味します。
コアとなるコードの変更箇所
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -1624,7 +1624,6 @@ import_stmt_list_r:
|\timport_stmt_list_r osemi import_stmt
hidden_import_list_r:
---\thidden_import
|\thidden_import_list_r hidden_import
hidden_funarg_list_r:
コアとなるコードの解説
変更はsrc/cmd/gc/go.y
ファイルの1626行目付近にあります。
削除された行: ---\thidden_import
この行は、hidden_import_list_r
という非終端記号が、少なくとも1つのhidden_import
という非終端記号から構成されなければならないという文法規則を定義していました。これは、hidden_import_list_r
の「ベースケース」として機能し、リストが空であることを許容しませんでした。
この行が削除されたことで、hidden_import_list_r
の定義は以下のようになります。
hidden_import_list_r:
/* (implicitly empty production) */
|\thidden_import_list_r hidden_import
Yacc/Bisonの文法では、非終端記号のプロダクションリストの最初の選択肢が空である場合(つまり、右辺に何も書かれていない場合)、その非終端記号は空文字列にマッチすると解釈されます。これにより、hidden_import_list_r
は、hidden_import
が一つも存在しない場合でも、文法的に有効な要素として認識されるようになります。
この変更は、Go言語の構文解析器が、hidden_import
のリストが空である状況をエラーとせず、正しく処理できるようにするためのものです。
関連リンク
参考にした情報源リンク
- Yacc/Bisonのドキュメント(一般的な文法定義の理解のため)
- Go言語の初期開発に関する情報(コミットの背景理解のため)