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

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

このコミットは、Go言語のパーサジェネレータであるgoyaccのサンプルコードunits.yにおけるビルドエラーを修正するものです。このエラーは、Go標準ライブラリのAPI変更(utf8パッケージの移動、strconv.Atof64の削除、文字型がintからruneへの変更など)によって引き起こされました。また、goyaccの利用方法に関するコメントも修正されています。

コミット

commit 26ba35666ec72b0969156c5f2d3f8339c188a7ec
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Thu Jan 12 07:54:20 2012 -0800

    goyacc: fix units.y build breakage
    This breakage is mainly due to API changes in pkg.
    (e.g., package utf8 moved to unicode/utf8;
           remove of strconv.Atof64;
           change character type from int to rune.)
    Also correct the usage comment.
    
    This fixes issue 2646.
    PS: I don't change the goyacc.go, because I think token type
        should not be force to rune.
    
    R=golang-dev, adg, rogpeppe, r, r
    CC=golang-dev
    https://golang.org/cl/5502093

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

https://github.com/golang/go/commit/26ba35666ec72b0969156c5f2d3f8339c188a7ec

元コミット内容

goyacc: fix units.y build breakage
This breakage is mainly due to API changes in pkg.
(e.g., package utf8 moved to unicode/utf8;
       remove of strconv.Atof64;
       change character type from int to rune.)
Also correct the usage comment.

This fixes issue 2646.
PS: I don't change the goyacc.go, because I think token type
    should not be force to rune.

R=golang-dev, adg, rogpeppe, r, r
CC=golang-dev
https://golang.org/cl/5502093

変更の背景

このコミットの主な背景は、Go言語の標準ライブラリにおけるAPIの変更です。Go言語は当時まだ開発の初期段階にあり、言語の安定化と改善のためにAPIの変更が頻繁に行われていました。goyaccunits.yサンプルコードは、これらの変更に追従できておらず、ビルドが失敗する状態になっていました。具体的には、以下の主要な変更が影響していました。

  1. utf8パッケージの移動: utf8パッケージがunicode/utf8という新しいパスに移動しました。
  2. strconv.Atof64の削除: 浮動小数点数文字列をパースするためのstrconv.Atof64関数が削除され、より汎用的な関数に置き換えられました。
  3. 文字型の変更: 文字を表す型がintからruneに移行しました。これはGo言語がUnicodeをより適切に扱うための重要な変更でした。

これらのAPI変更により、units.yは古いAPIを参照しているためコンパイルエラーが発生していました。このコミットは、これらの変更に対応し、units.yが再びビルドできるようにすることを目的としています。コミットメッセージに「This fixes issue 2646」とあることから、これは既知の不具合として追跡されていたことがわかります。

前提知識の解説

このコミットを理解するためには、以下のGo言語に関する前提知識が役立ちます。

  • Go言語の進化とAPI変更: Go言語は2009年に公開され、2012年時点ではまだバージョン1.0がリリースされたばかりの比較的新しい言語でした。そのため、言語仕様や標準ライブラリのAPIが頻繁に変更される時期でした。これは、言語設計の改善や安定化のために必要なプロセスです。
  • goyacc: goyaccは、Go言語で書かれたYacc(Yet Another Compiler Compiler)互換のパーサジェネレータです。Yaccは、文法定義から構文解析器(パーサ)のソースコードを自動生成するツールであり、コンパイラやインタプリタの作成によく用いられます。units.ygoyaccの機能を示すためのサンプル文法ファイルです。
  • rune: Go言語において、rune型はUnicodeのコードポイント(文字)を表す組み込み型です。これはint32のエイリアスであり、UTF-8でエンコードされた文字列から個々のUnicode文字を扱う際に使用されます。Go言語の初期には、文字をint型で扱うことがありましたが、Unicodeの複雑さを適切に扱うためにrune型が導入されました。
  • utf8パッケージとunicode/utf8パッケージ: utf8パッケージは、UTF-8エンコーディングされたテキストを扱うためのユーティリティ関数を提供します。Goの標準ライブラリの整理の一環として、このパッケージはunicodeパッケージの下に移動され、unicode/utf8という新しいインポートパスになりました。
  • strconvパッケージ: strconvパッケージは、基本的なデータ型(文字列、整数、浮動小数点数、真偽値など)と文字列との間の変換機能を提供します。初期のGoではAtof64のような特定の型に特化した関数がありましたが、後にParseFloatのようなより汎用的な関数に統合されました。

技術的詳細

このコミットは、src/cmd/goyacc/units.yファイルに対して、Go標準ライブラリのAPI変更に合わせた複数の修正を適用しています。

  1. インポートパスの変更:

    • utf8パッケージのインポートパスが"utf8"から"unicode/utf8"に変更されました。これは、パッケージの再編成による直接的な影響です。
  2. 文字型のintからruneへの移行:

    • peekrune変数の型がintからruneに変更されました。
    • UnitsLex型のLexメソッド内のローカル変数cの型がintからruneに変更されました。
    • ralpha関数とrdigit関数の引数cの型がintからruneに変更されました。
    • getrune関数の戻り値の型がintからruneに変更され、ローカル変数cの型もintからruneに変更されました。
    • Lexメソッドの戻り値はトークン型を表すintであるため、rune型のcを返す際にはint(c)と明示的な型変換が追加されました。これにより、Unicodeコードポイントをintとして返すという既存のインターフェースが維持されます。
  3. strconv.Atof64からstrconv.ParseFloatへの変更:

    • strconv.Atof64(sym)の呼び出しがstrconv.ParseFloat(sym, 64)に変更されました。ParseFloatは、文字列を浮動小数点数に変換するより汎用的な関数であり、第2引数でビットサイズ(float64の場合は64)を指定する必要があります。
  4. goyacc使用方法コメントの修正:

    • units.yの冒頭にあるgoyaccの利用方法に関するコメントが、goyacc units.yからgoyacc -p "units_" units.yに修正されました。これは、goyaccが生成するコードのパッケージ名を指定する-pオプションの一般的な使用法を反映しています。

これらの変更は、units.yがGo言語の進化するAPIと互換性を保ち、正しくビルドおよび実行されるようにするために不可欠でした。

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

src/cmd/goyacc/units.yファイルにおける主要な変更点は以下の通りです。

--- a/src/cmd/goyacc/units.y
+++ b/src/cmd/goyacc/units.y
@@ -14,7 +14,7 @@
 // units.y
 // example of a goyacc program
 // usage is
-//	goyacc units.y (produces y.go)
+//	goyacc -p "units_" units.y (produces y.go)
 //	6g y.go
 //	6l y.6
 //	./6.out $GOROOT/src/cmd/goyacc/units
@@ -33,7 +33,7 @@ import (
 	"os"
 	"math"
 	"strconv"
-	"utf8"
+	"unicode/utf8"
 )
 
 const (
@@ -58,7 +58,7 @@ var lineno int       // current input line number
 var linep int        // index to next rune in unput
 var nerrors int      // error count
 var one Node         // constant one
-var peekrune int     // backup runt from input
+var peekrune rune    // backup runt from input
 var retnode1 Node
 var retnode2 Node
 var retnode Node
@@ -212,7 +212,8 @@ expr0:
 type UnitsLex int
 
 func (UnitsLex) Lex(yylval *units_SymType) int {
-	var c, i int
+	var c rune
+	var i int
 
 	c = peekrune
 	peekrune = ' '
@@ -242,7 +243,7 @@ loop:
 		yylval.numb = 3
 		return SUP
 	}
-	return c
+	return int(c)
 
 alpha:
 	sym = ""
@@ -267,7 +268,7 @@ numb:
 		}
 	}
 	peekrune = c
-	f, err := strconv.Atof64(sym)
+	f, err := strconv.ParseFloat(sym, 64)
 	if err != nil {
 		fmt.Printf("error converting %v\n", sym)
 		f = 0
@@ -362,7 +363,7 @@ func main() {
  * all characters that have some
  * meaning. rest are usable as names
  */
-func ralpha(c int) bool {
+func ralpha(c rune) bool {
 	switch c {
 	case 0, '+', '-', '*', '/', '[', ']', '(', ')',
 		'^', ':', '?', ' ', '\t', '.', '|', '#',
@@ -375,7 +376,7 @@ func ralpha(c int) bool {
 /*
  * number forming character
  */
-func rdigit(c int) bool {
+func rdigit(c rune) bool {
 	switch c {
 	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
 		'.', 'e', '+', '-':
@@ -577,8 +578,9 @@ func readline() bool {
 	return false
 }
 
-func getrune() int {
-	var c, n int
+func getrune() rune {
+	var c rune
+	var n int
 
 	if linep >= len(line) {
 		return 0

コアとなるコードの解説

  • goyacc使用方法コメントの更新:

    -//	goyacc units.y (produces y.go)
    +//	goyacc -p "units_" units.y (produces y.go)
    

    この変更は、goyaccのコマンドライン引数の推奨される使用法を反映しています。-pオプションは、生成されるGoコードのパッケージ名を指定するために使用され、これにより生成されたパーサが特定のパッケージに属するように設定できます。

  • utf8パッケージのインポートパス変更:

    -	"utf8"
    +	"unicode/utf8"
    

    これは、Go標準ライブラリ内でutf8パッケージがunicodeパッケージのサブディレクトリに移動したことによる直接的な修正です。これにより、units.yは正しいパスからutf8関連の関数をインポートできるようになります。

  • intからruneへの型変更:

    -var peekrune int     // backup runt from input
    +var peekrune rune    // backup runt from input
    
    -	var c, i int
    +	var c rune
    +	var i int
    
    -func ralpha(c int) bool {
    +func ralpha(c rune) bool {
    
    -func rdigit(c int) bool {
    +func rdigit(c rune) bool {
    
    -func getrune() int {
    -	var c, n int
    +func getrune() rune {
    +	var c rune
    +	var n int
    

    これらの変更は、Go言語が文字を表現するためにintからrune型に移行したことに対応しています。peekruneLexメソッド内のcralphardigitgetrune関数内のcなど、文字を扱う変数の型がruneに変更されました。これにより、Unicode文字が正しく扱われるようになります。

  • Lexメソッドの戻り値の型変換:

    -	return c
    +	return int(c)
    

    Lexメソッドは、Yaccの仕様によりトークン型を表すintを返す必要があります。しかし、文字cの型がruneに変更されたため、int(c)と明示的に型変換を行うことで、Lexメソッドのインターフェースを維持しつつ、内部でrune型を扱うことができるようになります。

  • strconv.Atof64からstrconv.ParseFloatへの変更:

    -	f, err := strconv.Atof64(sym)
    +	f, err := strconv.ParseFloat(sym, 64)
    

    strconvパッケージのAPI変更に対応しています。Atof64は削除され、より汎用的なParseFloat関数が導入されました。ParseFloatは、パースする浮動小数点数のビットサイズを第2引数で指定する必要があり、ここではfloat64を表す64が渡されています。

これらの変更により、units.yはGo言語の最新のAPIに準拠し、ビルドエラーが解消されました。

関連リンク

参考にした情報源リンク

  • なし (提供された情報とコミット内容のみで解説を生成しました)