Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 1787] ファイルの概要

このコミットは、Go言語のscannerパッケージにおけるドキュメンテーションの改善を目的としています。具体的には、scanner.goファイル内のコメントが更新され、パッケージの利用方法やScanner構造体、Init関数、Scan関数の役割がより明確に記述されています。

コミット

commit 2aa77352fcdc0cc67612d682f9e16437fb423d76
Author: Robert Griesemer <gri@golang.org>
Date:   Mon Mar 9 17:16:42 2009 -0700

    scanner.go documentation
    
    R=r
    DELTA=22  (8 added, 3 deleted, 11 changed)
    OCL=25947
    CL=25955

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/2aa77352fcdc0cc67612d682f9e16437fb423d76

元コミット内容

scanner.go documentation

R=r
DELTA=22  (8 added, 3 deleted, 11 changed)
OCL=25947
CL=25955

変更の背景

このコミットは2009年3月に行われており、Go言語がまだ一般に公開される前の初期開発段階に当たります。Go言語は2009年11月に初めて公開されました。この時期は、言語の基本的なツールチェインや標準ライブラリが活発に構築・洗練されていた段階です。

scannerパッケージは、Go言語のソースコードを字句解析(トークン化)するための基本的なコンポーネントであり、コンパイラやその他のツールにとって不可欠な部分です。初期の段階では、機能の実装が優先され、ドキュメンテーションは後回しにされることがよくあります。しかし、コードベースが成長し、より多くの開発者が関わるようになるにつれて、コードの理解を深め、利用を促進するための明確で包括的なドキュメンテーションの重要性が増します。

このコミットの背景には、scannerパッケージの内部構造と利用方法を、将来の利用者や開発者に対してより分かりやすく説明するという意図があったと考えられます。特に、Scanner構造体の初期化方法やScan関数の振る舞いに関する説明を充実させることで、パッケージの使いやすさを向上させることが目的だったでしょう。

前提知識の解説

字句解析(Lexical Analysis / Tokenization)

字句解析とは、プログラミング言語のソースコードを、意味を持つ最小単位である「トークン」の並びに分解するプロセスのことです。例えば、x = 10 + y;というコードは、x(識別子)、=(代入演算子)、10(整数リテラル)、+(加算演算子)、y(識別子)、;(セミコロン)といったトークンに分解されます。このプロセスは、コンパイラやインタプリタがソースコードを理解し、次の段階である構文解析(Parsing)に進むための前処理として非常に重要です。

スキャナー(Scanner / Lexer / Tokenizer)

字句解析を行うプログラムやモジュールをスキャナー、レキサー、またはトークナイザーと呼びます。Go言語のscannerパッケージは、この役割を担います。ソースコードのバイト列を入力として受け取り、それをトークンに変換して出力します。

Go言語のパッケージとドキュメンテーション

Go言語では、コードは「パッケージ」という単位で組織されます。各パッケージは、関連する機能の集合体であり、再利用可能なモジュールとして機能します。Goの標準的なドキュメンテーションツールであるgo docは、ソースコード内のコメント(特にエクスポートされた識別子の直前のコメント)を解析してドキュメントを生成します。そのため、Go言語では、コード内に適切なコメントを記述することが、そのまま公式ドキュメントとなるため非常に重要視されています。

ErrorHandler インターフェース

このコミットで言及されているErrorHandlerは、スキャナーが字句解析中にエラー(例えば、不正な文字シーケンス)を検出した場合に、そのエラーをどのように処理するかを定義するためのインターフェースです。これにより、スキャナーの利用者(例えば、コンパイラ)は、独自のエラー処理ロジックを実装して、エラーメッセージの表示方法やエラーからの回復方法をカスタマイズできます。

技術的詳細

このコミットの技術的な詳細は、主にscanner.goファイル内のコメントの変更に集約されます。

  1. パッケージコメントの移動と追加:

    • 元のコードではpackage scannerの直後にパッケージ全体の説明が書かれていましたが、これがimport文の後に移動し、さらに//\n+package scannerという行が追加されています。これは、Goのドキュメンテーションツールがパッケージコメントを正しく認識するための慣習に合わせたものと考えられます。
    • パッケージコメントの例示コード(main関数を含む)がより明確になり、Scan()関数の戻り値の利用方法が示されています。
  2. ErrorHandlerインターフェースのコメント改善:

    • ErrorHandlerインターフェースの定義前に、その役割(構文エラーが発生した場合にError()が呼び出されること)がより詳細に説明されています。
  3. Scanner構造体のコメント追加:

    • Scanner構造体の定義前に、Scannerが「与えられたテキストを処理する間のスキャナーの内部状態を保持する」こと、そして「使用前にInit()を介して初期化されなければならない」ことが明記されました。
    • さらに、「パッケージコメントのサンプル使用例も参照」という指示が追加され、ドキュメント間の連携が図られています。
  4. Init関数のコメント改善:

    • Init関数のコメントが大幅に書き直されています。
    • 変更前は「スキャナーを初期化する」という一般的な説明でしたが、変更後は「Init()はスキャナーSをテキストsrcをトークン化するために準備する」と具体化されています。
    • err(エラーハンドラ)とscan_comments(コメントをトークンとして認識するかどうか)の引数の役割がより詳細に説明されています。特にscan_commentsfalseの場合に、改行文字とコメントが空白として扱われ無視される点が明確にされました。
  5. Scan関数のコメント改善:

    • Scan関数のコメントも書き直されています。
    • 変更前は「次のトークンをスキャンする」という説明でしたが、変更後は「Scan()は次のトークンをスキャンし、ソース内のトークンのバイト位置、そのトークン値、そしてトークンが識別子、基本型リテラル、またはコメントである場合の対応するリテラルテキストを返す」と、戻り値の詳細が追加されました。特に、コメントもリテラルテキストとして返される可能性がある点が追記されています。

これらの変更は、コードの機能自体には影響を与えませんが、Go言語のドキュメンテーションのベストプラクティスに沿って、パッケージの利用者がより簡単にscannerパッケージを理解し、正しく使用できるようにするための重要な改善です。

コアとなるコードの変更箇所

src/lib/go/scanner.go ファイルの変更がコアとなります。

--- a/src/lib/go/scanner.go
+++ b/src/lib/go/scanner.go
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package scanner
-
 // A Go scanner. Takes a []byte as source which can then be
 // tokenized through repeated calls to the Scan() function.
 //
@@ -23,6 +21,8 @@ package scanner
 //			println(pos, token.TokenString(tok), string(lit));
 //		}
 //	}
+//
+package scanner
 
 import (
 	"utf8";
@@ -36,12 +36,17 @@ import (
 // If a syntax error is encountered, Error() is called with the exact
 // token position (the byte position of the token in the source) and the
 // error message.
-\n+//
 type ErrorHandler interface {
 	Error(pos int, msg string);
 }
 
 
+// A Scanner holds the scanner's internal state while processing
+// a given text.  It can be allocated as part of another data
+// structure but must be initialized via Init() before use.
+// See also the package comment for a sample use.
+//
 type Scanner struct {
 	// immutable state
 	src []byte;  // source
@@ -94,13 +99,12 @@ func (S *Scanner) next() {
 }
 
 
-// Initialize the scanner.
+// Init() prepares the scanner S to tokenize the text src. Calls to Scan()
+// will use the error handler err if they encounter a syntax error. The boolean
+// scan_comments specifies whether newline characters and comments should be
+// recognized and returned by Scan as token.COMMENT. If scan_comments is false,
+// they are treated as white space and ignored.
 //
-// The error handler (err) is called when an illegal token is encountered.
-// If scan_comments is set to true, newline characters ('\n') and comments
-// are recognized as token.COMMENT, otherwise they are treated as white
-// space and ignored.
-\n func (S *Scanner) Init(src []byte, err ErrorHandler, scan_comments bool) {
 	S.src = src;
 	S.err = err;
@@ -397,10 +401,11 @@ func (S *Scanner) switch4(tok0, tok1, ch2, tok2, tok3 int) int {
 }
 
 
-// Scans the next token. Returns the token byte position in the source,\n-// its token value, and the corresponding literal text if the token is\n-// an identifier or basic type literal (token.IsLiteral(tok) == true).\n-\n+// Scan() scans the next token and returns the token byte position in the\n+// source, its token value, and the corresponding literal text if the token\n+// is an identifier, basic type literal (token.IsLiteral(tok) == true), or\n+// comment.\n+//
 func (S *Scanner) Scan() (pos, tok int, lit []byte) {
 scan_again:
 	S.skipWhitespace();

コアとなるコードの解説

このコミットは、Go言語のscannerパッケージのドキュメンテーションを改善するためのものです。コードのロジック自体には変更がなく、主にコメントの追加、修正、移動が行われています。

  1. パッケージコメントの配置:

    • package scannerの宣言がファイルの先頭からimport文の後に移動し、その直前に//で始まるパッケージ全体の説明コメントが配置されました。これはGoのドキュメンテーションツール(go doc)がパッケージコメントを正しく認識し、生成されるドキュメントに含めるための標準的な慣習です。
    • パッケージの利用例を示すコードスニペットも更新され、より具体的で分かりやすいものになっています。
  2. ErrorHandlerインターフェースのコメント:

    • ErrorHandlerインターフェースの役割について、より詳細な説明が追加されました。これにより、このインターフェースがどのようにエラー処理に使用されるかが明確になります。
  3. Scanner構造体のコメント:

    • Scanner構造体の定義の直前に、その目的と使用方法に関する新しいコメントが追加されました。特に、「使用前にInit()を介して初期化されなければならない」という重要な利用規約が明記されています。また、パッケージコメントのサンプル使用例を参照するように促すことで、関連するドキュメントへの誘導も行われています。
  4. Init関数のコメント:

    • Init関数のコメントが全面的に書き直されました。変更前は簡潔な説明でしたが、変更後は引数(src, err, scan_comments)のそれぞれの役割と、それらがスキャナーの動作にどのように影響するかについて、より詳細な説明が提供されています。特に、scan_commentsfalseの場合にコメントや改行が空白として扱われる点が明確にされました。
  5. Scan関数のコメント:

    • Scan関数のコメントも更新され、戻り値(pos, tok, lit)がそれぞれ何を表すのか、そしてlitがどのような場合に返されるのか(識別子、基本型リテラル、またはコメント)がより具体的に記述されています。特に「コメント」が追加されたことで、scan_commentstrueの場合のScan関数の振る舞いがより明確になりました。

これらの変更は、Go言語の初期段階において、コードの可読性と保守性を高め、将来の利用者がscannerパッケージをより効果的に利用できるようにするための、ドキュメンテーションの洗練作業の一環です。

関連リンク

参考にした情報源リンク