[インデックス 16918] ファイルの概要
このコミットは、Goコンパイラのフロントエンドの一部であるcmd/gc
が使用するBisonパーサジェネレータの出力処理に関するものです。具体的には、GNU Bison 3.0で導入された新しい%empty
ディレクティブとの互換性を確保するための変更です。
コミット
- コミットハッシュ:
4eaf91a7a729f96b020324cc78e66bc687f549f5
- Author: Rémy Oudompheng oudomphe@phare.normalesup.org
- Date: Tue Jul 30 04:31:15 2013 +0200
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/4eaf91a7a729f96b020324cc78e66bc687f549f5
元コミット内容
cmd/gc: make bisonerrors compatible with GNU Bison 3.0
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/11990043
変更の背景
この変更の背景には、パーサジェネレータであるGNU Bisonのバージョンアップがあります。Goコンパイラ(cmd/gc
)は、その構文解析のためにBisonを使用しています。Bisonの以前のバージョンでは、空のプロダクションルール(右辺が空のルール)を表現するために、通常は/* empty */
のようなコメントを使用するか、単に右辺を空のままにしていました。
しかし、GNU Bison 3.0では、空のルールを明示的に宣言するための新しいディレクティブ%empty
が導入されました。これは、意図しない空のルールを警告したり、より明確に空のルールを定義したりするための改善です。この変更により、Bison 3.0で生成されたパーサの出力が、以前のバージョンとは異なる形式で空のルールを表現するようになりました。
src/cmd/gc/bisonerrors
スクリプトは、Bisonが生成するエラーレポートや文法情報から、特定の情報を抽出・処理するために使用されていました。Bison 3.0が%empty
という新しいキーワードで空のルールを示すようになったため、このスクリプトが空のルールを正しく認識し、処理できるように更新する必要が生じました。もしこの更新が行われないと、Bison 3.0で生成されたパーサがGoコンパイラで正しく動作しない可能性がありました。
前提知識の解説
Bison (GNU Bison)
Bisonは、GNUプロジェクトによって開発されたパーサジェネレータです。これは、LALR(1)パーサを生成するために使用されます。コンパイラやインタプリタの構築において、ソースコードの構文解析(パース)を行う部分を自動生成するのに非常に役立ちます。開発者は、BNF(バッカス・ナウア記法)に似た形式で文法ルールを記述したファイル(通常.y
または.yy
拡張子)を作成し、Bisonはその文法定義に基づいてC、C++、Java、またはGoなどの言語でパーサのソースコードを生成します。
プロダクションルールと空のルール (Empty Rule / Epsilon Production)
文法は、非終端記号(構文の抽象的な要素、例: expression
, statement
)と終端記号(実際のトークン、例: +
, if
, identifier
)から構成されます。プロダクションルールは、非終端記号がどのように終端記号や他の非終端記号のシーケンスに展開されるかを定義します。
例:
statement: expression ';' | IF '(' condition ')' statement;
「空のルール」または「イプシロンプロダクション」とは、右辺が空であるプロダクションルールを指します。これは、特定の構文要素が「存在しない」ことを許容する場合に用いられます。例えば、オプションのセミコロンや、リストの最後の要素の後に続くカンマなどです。
例:
optional_semicolon: ';' | /* empty */;
GNU Bison 3.0の%empty
ディレクティブ
Bisonの以前のバージョンでは、空のルールは右辺を単に空にするか、/* empty */
のようなコメントを付けて表現するのが一般的でした。しかし、Bison 3.0では、空のルールをより明示的に宣言するための%empty
ディレクティブが導入されました。
例:
optional_semicolon: ';' | %empty;
この%empty
ディレクティブを使用することで、文法の意図がより明確になり、Bisonは意図しない空のルールに対して警告を発するようになります。これにより、文法定義の堅牢性が向上します。
src/cmd/gc/bisonerrors
スクリプト
Goコンパイラのソースツリーにあるsrc/cmd/gc/bisonerrors
は、Bisonが生成する出力(特にエラーや文法に関する情報)を処理するためのスクリプトです。このスクリプトは、Bisonの出力から文法ルールの左辺(rulelhs
)や右辺の要素数(rulesize
)などの情報を抽出し、Goコンパイラが内部的に利用できる形式に変換する役割を担っています。
技術的詳細
このコミットは、src/cmd/gc/bisonerrors
スクリプトが、GNU Bison 3.0で導入された%empty
ディレクティブによって表現される空のルールを正しく解釈できるようにするためのものです。
Bison 3.0では、空のルールが%empty
というキーワードで明示されるようになりました。bisonerrors
スクリプトは、Bisonの出力から各プロダクションルールの情報をパースし、そのルールの右辺の要素数(rulesize
)を計算しています。従来の空のルールは右辺が空であるため、rulesize
が0として計算されていました。しかし、Bison 3.0の出力では、%empty
が右辺の要素として現れるため、単純に要素数を数えるとrulesize
が1と誤って計算されてしまう可能性がありました。
このコミットの目的は、bisonerrors
スクリプトが%empty
を検出した場合に、そのルールのrulesize
を正しく0として扱うように修正することです。これにより、GoコンパイラがBison 3.0で生成されたパーサを使用する際に、文法ルールの解釈に齟齬が生じないようにします。
具体的には、スクリプトはBisonの出力行を解析し、ルールの右辺が%empty
という単一の要素で構成されている場合に、そのルールのサイズを0に設定します。これにより、Bison 3.0の新しい空ルール表現が、Goコンパイラのビルドプロセスで正しく処理されるようになります。
コアとなるコードの変更箇所
変更はsrc/cmd/gc/bisonerrors
ファイルにあります。
--- a/src/cmd/gc/bisonerrors
+++ b/src/cmd/gc/bisonerrors
@@ -35,6 +35,9 @@ grammar && NF>0 {
}
rulelhs[$1] = r
rulesize[$1] = NF-2
+ if(rulesize[$1] == 1 && $3 == "%empty") {
+ rulesize[$1] = 0
+ }
if(rulesize[$1] == 3 && $3 $4 $5 == "/*empty*/") {
rulesize[$1] = 0
}
追加されたのは以下の3行です。
if(rulesize[$1] == 1 && $3 == "%empty") {
rulesize[$1] = 0
}
コアとなるコードの解説
この変更は、awk
スクリプトであるsrc/cmd/gc/bisonerrors
内で行われています。
grammar && NF>0 { ... }
:このawk
ブロックは、Bisonの出力のうち、文法ルールに関する行を処理します。NF
はフィールドの数を表します。rulelhs[$1] = r
:ルールの左辺(非終端記号)を記録しています。$1
は通常、ルールの左辺の非終端記号に対応します。rulesize[$1] = NF-2
:ルールの右辺の要素数を計算しています。Bisonの出力形式では、最初の2つのフィールドがルールの番号や左辺の記号などであるため、NF-2
で右辺の実際の要素数を取得します。if(rulesize[$1] == 1 && $3 == "%empty") { rulesize[$1] = 0 }
:- これが今回追加された主要なロジックです。
rulesize[$1] == 1
:計算されたルールの右辺の要素数が1であるかをチェックします。$3 == "%empty"
:そして、その唯一の要素が文字列"%empty"
であるかをチェックします。Bison 3.0では、空のルールが%empty
という単一のトークンとして出力されるため、この条件が合致します。rulesize[$1] = 0
:もし上記の条件が真であれば、そのルールの実際のサイズは0(空)であると判断し、rulesize
を0に上書きします。
if(rulesize[$1] == 3 && $3 $4 $5 == "/*empty*/") { rulesize[$1] = 0 }
:- これは既存のロジックで、従来の
/* empty */
コメントで表現された空のルールを処理するためのものです。 /* empty */
は3つのトークン(/*
,empty
,*/
)として扱われるため、rulesize
が3になる場合に、それが/*empty*/
であればrulesize
を0に設定していました。
- これは既存のロジックで、従来の
この変更により、bisonerrors
スクリプトは、Bison 3.0で導入された%empty
ディレクティブによって表現される空のルールを正しく認識し、そのサイズを0として処理できるようになりました。これにより、Goコンパイラのビルドシステムが新しいBisonバージョンと互換性を持つことが保証されます。
関連リンク
- Go CL 11990043: https://golang.org/cl/11990043
参考にした情報源リンク
- GNU Bison 3.0 changes empty rule:
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHpamIgaCKtRR3i_WuDSRcJP3mV4ZEsHQFac53boofOh2SbU36NSOCJMQ6Q16joMU3SetZfroXKQZxQy-u0wyr9P33uVqOouH-PiHInMAELUNgU2abyIx8ugKhqGBgkSV7-KvGcWzwK5jQ1E7KvfNWOUKGM5em3XF8q6pZGJ-5gZnCNZQ==
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFsFYsd8hpdWFldV1Hnx8F_ifuWJwWZ0LwwPgFZRV7BVDUl4Qzq1UONnmCKZJDL61OEvlU1QH6n1_c8Gd3DZVXsI2Wc1-hfWgWNh2Yc2MUByIdMv_83aWFSikNdLvIat5caK1J8f6My3_7U0SVZzvB2
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGvHp2aLMwaAFgUf4dnPQPYB36e45Rw_oJqE7mOjxL8rSRk2p87ynjtAMsxYCKQXH4Z2NK_Eeme73DT8u2rUUmXyxS6Kaoy6jfsVYqKGX41IHJAw-Q8nihR-3NhP2PJNIoKpPfmJl9JpzIXqoSjyyTGHJTo-3Y3h3qBPn71hyJCDNlypUQ=
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQEKg4YL-hLPJ7UJH7NBgmrwPQ_IVLs6qsX_48Ljb6MIuDUHXUE-DDXUS06jqCN-DjdtnDutzUQeAC5iSyqiWxL3V7MD1ahAAB7UVnkMN0XRJNEAdxNq2EFkERsC
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGKG1Zp81HIXm70IaTA6rcwsVX2v-X3hk_P6AjWWUpT-c5SWNfX-BRRTWjRLMAmXpzq3c4VTkjKnU6NerVYBQkgI2ChqcTMZZvc053fsZm2-MJLPlo94x9wdasSufR3SoS4W3bxmwukKrXD_bvtEZNFmZZH8h0zK3JqY7KHHUl4
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGYW3U49HedE1-l8IkWWKJLz5SniyV6YPcXUGhPu-o3bt0O-lL4Ln9-ZeJkuqWfZWB5xEUO48xI4Eqqu85iPPBlUPJ-HZaCXoYYdJJ8vpx1ClqGXCIzUh6GhEi6RZgGes1i