[インデックス 1704] ファイルの概要
このコミットは、Go言語の仕様書である doc/go_spec.html
ファイルにおける字句解析(lexical analysis)に関するセクションの大幅な書き換えと改善を目的としています。具体的には、Go言語のトークン(識別子、キーワード、演算子、リテラルなど)の定義がより明確かつ詳細に記述され、EBNF(Extended Backus-Naur Form)による文法定義の表示方法も改善されています。これにより、仕様書の可読性と正確性が向上し、Goコンパイラや開発ツールの実装者が仕様をより正確に理解できるようになります。
コミット
commit ff70f09d2704cf9e78cded8975141bb9de1520fa
Author: Rob Pike <r@golang.org>
Date: Fri Feb 20 13:36:14 2009 -0800
Rewrite lexical section.
Put grammar productions into a box with a separate background color.
R=gri
DELTA=397 (132 added, 49 deleted, 216 changed)
OCL=25235
CL=25258
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/ff70f09d2704cf9e78cded8975141bb9de1520fa
元コミット内容
Rewrite lexical section.
Put grammar productions into a box with a separate background color.
R=gri
DELTA=397 (132 added, 49 deleted, 216 changed)
OCL=25235
CL=25258
変更の背景
このコミットが行われた2009年2月は、Go言語がまだ一般に公開される前の初期開発段階にありました。Go言語の仕様は継続的に洗練されており、この時期には言語の核となる部分、特に字句解析のルールを明確に定義することが重要でした。
変更の主な背景は以下の点が考えられます。
- 仕様の明確化と厳密化: 初期段階の仕様は、実装を進める中で曖昧な点や不足している点が発見されがちです。字句解析はコンパイラの最初の段階であり、その定義が曖昧だと後続の構文解析や意味解析に影響が出ます。このコミットは、字句解析に関する記述をより厳密にし、誤解の余地をなくすことを目指しています。
- 可読性の向上: EBNFによる文法定義は、プログラミング言語の仕様を記述する上で非常に強力ですが、その表示方法も重要です。
pre
タグにclass="grammar"
を追加し、背景色を変えることで、文法規則が視覚的に際立つようになり、仕様書全体の可読性が向上しています。 - ツールのサポート: 明確で厳密な仕様は、コンパイラ、リンター、IDEなどの開発ツールを正確に実装するために不可欠です。字句解析のルールが詳細に記述されることで、これらのツールの開発が容易になります。
- Unicodeの扱い: Go言語はUnicodeをネイティブにサポートしており、ソースコードがUTF-8でエンコードされることを前提としています。このコミットでは、Unicode文字、特に結合文字(combining characters)の扱いについて、より詳細な説明が追加されており、Go言語がどのようにUnicodeコードポイントを扱うかという設計思想が反映されています。
これらの変更は、Go言語が堅牢で一貫性のある言語として発展していくための基盤を固める上で重要なステップでした。
前提知識の解説
このコミットの変更内容を理解するためには、以下の概念について基本的な知識が必要です。
1. 字句解析 (Lexical Analysis) とトークン (Tokens)
字句解析は、コンパイラの最初のフェーズであり、ソースコードを「トークン」と呼ばれる意味のある最小単位の並びに変換するプロセスです。例えば、var x = 10;
というコードは、var
(キーワード)、x
(識別子)、=
(演算子)、10
(数値リテラル)、;
(区切り文字) といったトークンに分解されます。
- 識別子 (Identifiers): 変数名、関数名、型名など、プログラム内のエンティティを識別するための名前。
- キーワード (Keywords):
if
,for
,var
,func
など、言語によって特別な意味が予約されている単語。識別子として使用することはできません。 - 演算子 (Operators):
+
,-
,*
,/
,=
,==
など、計算や比較などの操作を行う記号。 - 区切り文字 (Delimiters):
(
,)
,{
,}
,[
,]
,,
,;
など、コードの構造を区切る記号。 - リテラル (Literals): ソースコード中に直接記述された定数値。数値リテラル (
10
,3.14
)、文字列リテラル ("hello"
)、文字リテラル ('a'
) などがあります。
2. EBNF (Extended Backus-Naur Form)
EBNFは、プログラミング言語の文法を記述するためのメタ言語です。このコミットでは、Go言語の字句構造をEBNFで定義しています。
=
: 定義|
: 選択 (OR){ ... }
: 0回以上の繰り返し[ ... ]
: 0回または1回 (オプション)( ... )
: グループ化"..."
または'...'
: リテラル(終端記号)...
: 文字の範囲 (例:"0" ... "9"
)
3. UnicodeとUTF-8
- Unicode: 世界中の文字を統一的に扱うための文字コードの国際標準です。各文字には一意の「コードポイント」(例: U+0041 は 'A')が割り当てられています。
- UTF-8: Unicodeコードポイントをバイト列にエンコードするための可変長エンコーディング方式です。ASCII文字は1バイトで表現され、それ以外の文字は2バイト以上で表現されます。Go言語のソースコードはUTF-8でエンコードされることが前提となっています。
- 結合文字 (Combining Characters): 特定の文字(例: 'a')と組み合わせて、その文字の表示を変更する文字(例: アクセント記号)。Unicodeでは、'ä' のような文字は、単一のコードポイント(U+00E4)で表現されることもあれば、基本文字 'a' (U+0061) と結合文字のウムラウト (U+0308) の2つのコードポイントの組み合わせで表現されることもあります。Go言語の仕様では、これらを異なるコードポイントとして扱います。
4. Go言語の設計思想(初期段階)
Go言語は、シンプルさ、効率性、並行処理のサポートを重視して設計されました。字句解析のルールも、これらの原則に沿って、曖昧さを排除し、コンパイラの実装を容易にするように設計されています。特に、C言語のようなプリプロセッサの概念を持たず、コメントが空白として扱われる点や、文字列リテラルにおけるバックスラッシュの解釈の違いなどが特徴です。
技術的詳細
このコミットは、doc/go_spec.html
ファイルの字句解析に関するセクションに広範な変更を加えています。主な技術的変更点は以下の通りです。
1. EBNF表示の改善
-
EBNFで記述された文法規則を表示する
<pre>
タグに、新たにclass="grammar"
属性が追加されました。これにより、CSS(mdbook.css
など)でこれらのブロックに特別なスタイル(例: 背景色の変更)を適用できるようになり、文法規則が視覚的に他のテキストと区別され、可読性が向上しています。-<pre> +<pre class="grammar">
2. ソースコード表現の明確化
- Go言語のソースコードがUnicodeテキストであり、UTF-8でエンコードされることが改めて強調されています。
- 「文字 (character)」という用語がUnicodeコードポイントを指すことが明確に定義されました。
- Unicodeの正規化(canonicalization)が行われないこと、つまり、単一のアクセント付き文字と、基本文字と結合文字の組み合わせが異なるコードポイントとして扱われることが明記されました。これは、Go言語がソースコードのバイト列をそのまま解釈するというシンプルなアプローチを取っていることを示しています。
3. 文字クラスの定義の拡張
unicode_char
、unicode_letter
、capital_letter
に加えて、新たにunicode_digit
が文字クラスとして追加されました。これにより、Unicodeの数字文字の扱いが明確になります。
4. 字句要素 (Lexical elements) の再構成と詳細化
「Vocabulary」セクションが「Lexical elements」に改名され、以下のサブセクションに再構成・詳細化されました。
a. コメント (Comments)
- 単一行コメント (
//
) と複数行コメント (/* ... */
) の両方が明確に定義されました。 - コメントがネストしないこと、および空白として扱われることが明記されました。
b. トークン (Tokens)
- トークンがGo言語の語彙を形成する要素であり、識別子、キーワード、演算子と区切り文字、リテラルの4つのクラスに分類されることが説明されました。
- 空白(スペース、タブ、改行)がトークンを区切る場合を除いて無視されること、コメントも空白として扱われることが明記されました。
- 「最長一致 (longest sequence of characters)」ルールが導入されました。これは、字句解析器が常に有効なトークンを形成する最長の文字シーケンスを次のトークンとして選択するという、一般的な字句解析の原則です。
c. 識別子 (Identifiers)
- 識別子の定義が
letter { letter | unicode_digit }
と変更され、識別子にUnicodeの数字文字も使用できることが明確になりました。 - エクスポートされる識別子(大文字で始まるもの)に関する注意書きが追加されましたが、同時に「TODO: This sentence feels out of place.」というコメントも残されており、仕様書としての構成上の課題が示唆されています。
d. キーワード (Keywords)
- Go言語の予約語のリストが明確に示されました。
e. 演算子と区切り文字 (Operators and Delimiters)
- Go言語で使用されるすべての演算子と区切り文字のリストが提示されました。
f. 数値リテラル (Integer literals, Floating-point literals, Ideal numbers)
- 整数リテラル: 8進数、10進数、16進数の形式がEBNFで詳細に定義されました。
- 浮動小数点リテラル: 整数部、小数点、小数部、指数部からなる浮動小数点数の表現が詳細に説明され、EBNFも更新されました。
- 理想数 (Ideal numbers): 整数リテラルと浮動小数点リテラルが「理想数」として扱われることが明確にされました。理想数は任意精度を持ち、オーバーフローしないというGo言語の重要な特性が説明されています。これは、コンパイル時に定数式を評価する際の精度保証に関連します。
g. 文字リテラル (Character literals)
- 文字リテラルが単一引用符で囲まれた整数値を表すことが明確にされました。
- バックスラッシュエスケープシーケンス(
\x
,\u
,\U
, 8進数エスケープ)の詳細なルールと、それらが表す値の範囲が説明されました。特に、\u
と\U
がUnicodeコードポイントを表し、\x
と8進数エスケープがバイト値を表す点が強調されています。 - C言語との違い(例: 8進数エスケープが常に3桁であること)が以前の記述から削除され、よりGo言語の仕様に特化した記述になりました。
h. 文字列リテラル (String literals)
- 生文字列リテラル (Raw string literals): バッククォート
`
で囲まれ、バックスラッシュが特別に解釈されない文字列リテラル。 - 解釈済み文字列リテラル (Interpreted string literals): 二重引用符
"
で囲まれ、バックスラッシュエスケープが解釈される文字列リテラル。 - 文字リテラルと同様に、
\x
と8進数エスケープがバイトを表し、\u
と\U
がUTF-8エンコードされたUnicode文字を表すことが明確にされました。 - 隣接する文字列リテラルが連結されるルールがEBNF (
StringLit = string_lit { string_lit } .
) とともに導入されました。
5. その他の変更
hr
タグが XHTML 形式のhr/
に変更されました。TODO
コメントがいくつか追加され、仕様のさらなる改善点や未解決の課題が示されています(例: 「TODO: This sentence feels out of place.」や「TODO: This is too vague. It used to say "sufficiently" but that doesn't help. Define a minimum?」)。- ファイルの末尾に「Differences between this doc and implementation - TODO」セクションが追加され、ドキュメントと実際のGoコンパイラの実装との間に存在する既知の差異が示唆されています(例: 「Current implementation accepts only ASCII digits for digits; doc says Unicode.」)。これは、仕様書が常に実装と完全に同期しているわけではないという現実を反映しています。
これらの変更は、Go言語の仕様書がより正確で、詳細で、かつ読みやすいものになるように、初期段階で精力的に改善が行われていたことを示しています。
コアとなるコードの変更箇所
このコミットのコアとなる変更は、doc/go_spec.html
ファイルの以下のセクションに集中しています。
-
EBNF表示の変更:
- 行
156,13
から156,13
の変更:<hr>
が<hr/>
に。 - 行
160,13
から160,13
の変更:<pre>
が<pre class="grammar">
に。 - 行
173,13
から173,13
の変更:<pre>
が<pre class="grammar">
に。 - 同様に、仕様書全体でEBNFを記述している
<pre>
タグにclass="grammar"
が追加されています。
- 行
-
「Source code representation」セクションの変更:
- 行
199
から216
にかけて、ソースコードのUnicodeとUTF-8に関する説明が大幅に加筆・修正されています。特に、Unicodeの正規化が行われないことや、コードポイントの扱いに関する詳細が追加されました。
- 行
-
「Characters」セクションの変更:
- 行
223
から226
にかけて、文字クラスのリストにunicode_digit
が追加され、リストのHTML構造も<li>
タグで閉じられるように修正されました。
- 行
-
「Letters and digits」セクションの変更:
- 行
233
から236
にかけて、アンダースコア_
が文字として扱われることの説明が追加され、EBNFのletter
定義も更新されました。
- 行
-
「Vocabulary」セクションから「Lexical elements」セクションへの変更と再構成:
- 行
240
から242
にかけて、セクションタイトルが変更され、コメントとトークンに関する新しいサブセクションが追加されました。 - コメント: 行
244
から251
にかけて、コメントの形式と振る舞いに関する詳細な説明が追加されました。 - トークン: 行
253
から262
にかけて、トークンの分類と最長一致ルールに関する説明が追加されました。
- 行
-
「Identifiers」セクションの変更:
- 行
268
から271
にかけて、識別子のEBNF定義がunicode_digit
を含むように変更されました。 - エクスポートされる識別子に関する説明が追加されました。
- 行
-
「Numeric literals」セクションの変更:
- 行
289
から366
にかけて、整数リテラル、浮動小数点リテラル、理想数に関する説明が大幅に加筆・修正され、EBNF定義も詳細化されました。
- 行
-
「Character and string literals」セクションの変更と分割:
- このセクションは「Character literals」と「String literals」に分割され、それぞれが大幅に詳細化されました。
- 文字リテラル: 行
370
から460
にかけて、文字リテラルのエスケープシーケンス、値の範囲、およびEBNF定義が詳細に記述されました。 - 文字列リテラル: 行
464
から517
にかけて、生文字列リテラルと解釈済み文字列リテラルの違い、エスケープシーケンスの解釈、隣接する文字列リテラルの連結ルールなどが詳細に記述されました。
-
「Reserved words」と「Operators and delimitors」セクションの移動:
- これらのセクションは、新しい「Lexical elements」の下に移動し、適切な位置に配置されました。
-
ファイルの末尾への追加:
- 行
3737
から3743
にかけて、「Differences between this doc and implementation - TODO」セクションが追加されました。
- 行
これらの変更は、Go言語の字句解析に関する仕様を網羅的かつ正確に記述するための、体系的な取り組みを示しています。
コアとなるコードの解説
このコミットにおけるコアとなるコードの変更は、Go言語の仕様書 doc/go_spec.html
の字句解析に関する記述を、より正確で、詳細で、かつ読みやすいものにするためのものです。
1. EBNF表示の視覚的改善
<pre class="grammar">
の導入は、単なる見た目の変更以上の意味を持ちます。これにより、仕様書内でEBNFによる文法規則が明確に区別され、読者が言語の構文定義を素早く識別し、理解するのに役立ちます。これは、仕様書の「ユーザビリティ」を向上させる重要な変更です。
2. UnicodeとUTF-8の厳密な定義
Go言語がUnicodeをどのように扱うかについての詳細な説明は、言語の国際化対応の基盤を明確にします。特に、Unicodeの正規化を行わないという決定は、Goコンパイラがソースコードのバイト列をシンプルかつ直接的に解釈するという設計哲学を反映しています。これにより、コンパイラの実装が複雑になるのを避けつつ、開発者がUnicode文字を意図した通りに扱えるようになります。結合文字の扱いに関する明確化は、多言語対応アプリケーションを開発する上で重要な情報となります。
3. 字句要素の包括的な定義
字句解析のセクション全体が再構成され、コメント、トークン、識別子、キーワード、演算子、リテラルといった各要素が詳細に定義されたことは、Go言語の字句構造の厳密性を高めます。
- 最長一致ルール: 「最長一致」の原則が明記されたことで、
==
と=
のような曖昧なケースで、字句解析器がどのようにトークンを生成するかが明確になります。これは、コンパイラの実装における字句解析器の振る舞いを一意に定めるために不可欠です。 - 識別子とUnicode数字: 識別子にUnicodeの数字文字が許可されるようになったことは、Go言語が非ASCII文字を識別子に含めることを許容するという、より柔軟なアプローチを取っていることを示唆しています。
- 理想数: 整数リテラルと浮動小数点リテラルが「理想数」として扱われるという概念は、Go言語の型システムにおける重要な特徴です。これにより、コンパイル時に定数式を評価する際に、オーバーフローの心配なく任意精度で計算できることが保証されます。これは、C言語のような固定幅の整数型とは異なる、Go言語の設計上の利点の一つです。
- 文字リテラルと文字列リテラルの詳細化: エスケープシーケンスの厳密な定義と、バイト値とUnicodeコードポイントの区別は、Go言語における文字と文字列の内部表現と操作を正確に理解するために不可欠です。特に、
\x
と8進数エスケープがバイトを表し、\u
と\U
がUTF-8エンコードされたUnicode文字を表すという区別は、Go言語がバイトと文字(ルーン)を明確に区別していることを示しています。 - 隣接文字列リテラルの連結: このルールは、長い文字列を複数行に分割して記述する際の利便性を提供します。
4. TODOコメントの追加
仕様書に TODO
コメントが追加されていることは、当時のGo言語の仕様がまだ開発中であり、完璧ではないことを率直に示しています。これは、仕様策定プロセスが継続的であり、実装との乖離や曖昧な点が認識され、将来の改善が計画されていたことを物語っています。特に、実装とドキュメントの差異に関するTODOは、仕様書が単なる理想論ではなく、実際のコンパイラの実装と同期を取ろうとする努力の証です。
総じて、このコミットは、Go言語の字句解析に関する仕様を、初期段階から非常に高いレベルで詳細化し、厳密化するための重要な一歩でした。これにより、Go言語のコンパイラや関連ツールの開発が促進され、言語の安定性と信頼性が向上しました。
関連リンク
- Go言語公式ドキュメント: Go言語の最新の仕様は、常に公式ウェブサイトで公開されています。
- Go言語の歴史: Go言語の初期の設計に関する情報は、以下の記事などで見つけることができます。
- The Evolution of Go (Rob Pikeによるスライド)
- A Tour of Go (Go言語の基本的な概念を学ぶためのインタラクティブなチュートリアル)
参考にした情報源リンク
- コミット情報:
/home/orange/Project/comemo/commit_data/1704.txt
- GitHubコミットページ: https://github.com/golang/go/commit/ff70f09d2704cf9e78cded8975141bb9de1520fa
- Go言語の公式ドキュメントおよび仕様書 (一般的な知識の補完のため)
- EBNFに関する一般的な情報 (一般的な知識の補完のため)
- UnicodeとUTF-8に関する一般的な情報 (一般的な知識の補完のため)