コンテンツにスキップ

Go/字句的要素

出典: フリー教科書『ウィキブックス(Wikibooks)』
< Go

字句的要素

[編集]

Goにおける字句的要素(Lexical elements)[1]は、プログラムを構成する基本的な要素です。 これらはプログラム内でのトークンや構造を構築するための基本的な構成要素です。

主な字句的要素は以下のようになります:

トークン (Tokens)
コメント (Comments): コード内の説明や注釈を追加するための文。
識別子 (Identifiers): 変数、関数、メソッドなどの名前を識別するための文字列。
キーワード (Keywords): 言語の構文で予約された単語(if、else、for、など)。
演算子と区切り文字 (Operators and Delimiters): 演算子(+、-、*、/、など)や区切り文字(括弧、セミコロン、コンマ、など)。
リテラル (Literals): 固定された値を表す(整数、浮動小数点数、文字列、真偽値、など)。
空白文字 (Whitespace): スペース、タブ、改行など、プログラム内での空白の文字。

コメント

[編集]

コメントは、プログラムの記録として機能します。コメントには2つの形式があります[2]

行コメント
// という文字列で始まり、その行の終わりで終わります。
一般コメント
/* という文字列で始まり、それに続く最初の文字列 */ で終わります。

コメントは、ルーンや文字列リテラルの中や、コメントの中では始められません。 改行のない一般的なコメントは、スペースのように機能します。それ以外のコメントは改行のように動作します。

セミコロン

[編集]

形式文法(formal grammar)では、多くの Production の終端にセミコロン「;」を使用します。Goプログラムでは、以下の2つのルールにより、これらのセミコロンのほとんどを省略することができます[3]

  1. 入力がトークンに分割されたとき、1行の最後のトークンの直後にセミコロンが自動的に挿入されます。
    識別子
    リテラル
    整数、浮動小数点、虚数、ルーンまたは文字列
    キーワード
    break、continue、fallthroughまたはreturn
    演算子および句読点
    ++, --, ), ], または }
  2. 複雑な文を1行にまとめるために、セミコロンを閉じの") "や"}"の前で省略することができます。

慣用的な使用法を反映させるために、このドキュメント(The Go Programming Language Specification)のコード例では、これらの規則に従ってセミコロンを省略しています。

識別子

[編集]

識別子(Identifiers)は、変数や型などのプログラムの実体を表すものです。識別子は、1つ以上の文字と数字を組み合わせたものです。識別子の最初の文字は文字でなければなりません[4]

構文
identifier = letter { letter | unicode_digit } .
有効な識別子の例
a
_x9
ThisVariableIsExported
αβ

識別子の中には宣言済み識別子として、あらかじめ宣言されているものがあります。

キーワード

[編集]

キーワード(Keywords)[5]

演算子と区切子

[編集]

以下の文字列は、代入演算子(assignment operators)を含む演算子(operators)と区切子(punctuation)を表します[6]。 Go1.18で新たに ~ が追加されました。

演算子と区切子
+    &     +=    &=     &&    ==    !=    (    )
-    |     -=    |=     ||    <     <=    [    ]
*    ^     *=    ^=     <-    >     >=    {    }
/    <<    /=    <<=    ++    =     :=    ,    ;
%    >>    %=    >>=    --    !     ...   .    :
     &^          &^=          ~

リテラル

[編集]

整数リテラル

[編集]

整数リテラル(An integer literal)とは、整数の定数を表す一連の数字のことです。オプションのプレフィックスは、非10進数の基数を設定します。2進法では0bまたは0B、8進法では0、0o、または0O、16進法では0xまたは0Xです。0は10進数の0とみなされます。16進数のリテラルでは、aからfまでの文字とAからFまでの文字が10から15までの値を表します[7]

可読性を高めるために、アンダースコア文字 _ が基本の接頭辞の後や連続する数字の間に表示されることがありますが、このようなアンダースコアはリテラルの値を変更するものではありません。

構文
int_lit        = decimal_lit | binary_lit | octal_lit | hex_lit ;
decimal_lit    = "0" | ( "1"  "9" ) [ [ "_" ] decimal_digits ] ;
binary_lit     = "0" ( "b" | "B" ) [ "_" ] binary_digits ;
octal_lit      = "0" [ "o" | "O" ] [ "_" ] octal_digits ;
hex_lit        = "0" ( "x" | "X" ) [ "_" ] hex_digits ;

decimal_digits = decimal_digit { [ "_" ] decimal_digit } ;
binary_digits  = binary_digit { [ "_" ] binary_digit } ;
octal_digits   = octal_digit { [ "_" ] octal_digit } . 
hex_digits     = hex_digit { [ "_" ] hex_digit } ;
42
4_2
0600
0_600
0o600
0O600       // second character is capital letter 'O'
0xBadFace
0xBad_Face
0x_67_7a_2f_cc_40_c6
170141183460469231731687303715884105727
170_141183_460469_231731_687303_715884_105727

_42         // 識別子、整数リテラルではない
42_         // 無効:_ は連続した数字を区切らなければならない
4__2        // 無効:一度に1つの_しか使えない 
0_xBadFace  // 無効:_ は連続した数字を区切らなければならない

浮動小数点リテラル

[編集]

浮動小数点リテラル(A floating-point literal)とは、浮動小数点定数(a floating-point constant)を10進数または16進数で表したものです[8]

10進数の浮動小数点リテラルは、整数部(10進数)、小数点、分数部(10進数)、指数部(eまたはEの後に任意の符号と10進数)で構成されます。整数部または小数部のいずれかを省略することができ、小数点部または指数部のいずれかを省略することができます。指数値expは、仮数部(整数部と小数部)を10expに拡大する。

16進浮動小数点リテラルは、0xまたは0Xの接頭辞、整数部(16進数)、基数点、分数部(16進数)、指数部(pまたはPの後に任意の符号と10進数)で構成されます。整数部と分数部のいずれかを省略することができます。基数点も省略できますが、指数部は必須です。(この構文は、IEEE 754-2008の§5.12.3の構文と同じです。) 指数値expは、仮数部(整数部と小数部)を2expだけ拡大したものです。

読みやすさのために、下線文字 _ が接頭辞の後や連続する数字の間に現れることがありますが、このような下線文字はリテラル値を変更するものではありません。

構文
float_lit         = decimal_float_lit | hex_float_lit ;

decimal_float_lit = decimal_digits "." [ decimal_digits ] [ decimal_exponent ] |
                    decimal_digits decimal_exponent |
                    "." decimal_digits [ decimal_exponent ] ;
decimal_exponent  = ( "e" | "E" ) [ "+" | "-" ] decimal_digits ;

hex_float_lit     = "0" ( "x" | "X" ) hex_mantissa hex_exponent ;
hex_mantissa      = [ "_" ] hex_digits "." [ hex_digits ] |
                    [ "_" ] hex_digits |
                    "." hex_digits ;
hex_exponent      = ( "p" | "P" ) [ "+" | "-" ] decimal_digits ;
0.
72.40
072.40       // == 72.40
2.71828
1.e+0
6.67428e-11
1E6
.25
.12345E+5
1_5.         // == 15.0
0.15e+0_2    // == 15.0

0x1p-2       // == 0.25
0x2.p10      // == 2048.0
0x1.Fp+0     // == 1.9375
0X.8p-0      // == 0.5
0X_1FFFP-16  // == 0.1249847412109375
0x15e-2      // == 0x15e - 2 (integer subtraction)

0x.p1    // 無効:仮数に桁がない
1p-2     // 無効:pの指数が16進数の仮数を必要とする
0x1.5e-2 // 無効:16進法の仮数にp指数が必要
1_.5     // 無効:16進数でp指数が必要
1._5     // 無効:_ は連続した数字を区切らなければならない
1.5_e1   // 無効:_ は連続した数字を区切らなければならない
1.5e_1   // 無効:_ は連続した数字を区切らなければならない 
1.5e1_   // 無効:_ は連続した数字を区切らなければならない

虚数リテラル

[編集]

虚数リテラル(An imaginary literal)は、複素数定数(a complex constant)の虚数部(the imaginary part)を表します。虚数リテラルの値は、それぞれの整数または浮動小数点リテラルの値に虚数単位の を掛けたものになります[9]

構文
imaginary_lit = (decimal_digits | int_lit | float_lit) "i" ;
0i
0123i         // == 123i 下位互換性のために
0o123i        // == 0o123 * 1i == 83i
0xabci        // == 0xabc * 1i == 2748i
0.i
2.71828i
1.e+0i
6.67428e-11i
1E6i
.25i
.12345E+5i
0x1p-2i       // == 0x1p-2 * 1i == 0.25i

ルーンリテラル

[編集]

ルーンリテラル(A rune literal)は、Unicodeコードポイント( a Unicode code point)を示す整数値であるルーン定数(a rune constant)を表す。ルーンリテラルは、 'x' や '\n' のように一重引用符で囲まれた1つ以上の文字で表されます。引用符の中には、改行とエスケープされていない一重引用符以外の任意の文字を入れることができます。一重引用符で囲まれた文字は、その文字自体のUnicode値を表しますが、バックスラッシュで始まる複数の文字列は、さまざまな形式の値をエンコードします[10]

最も単純な形式は、引用符の中の1文字を表すものです。GoのソーステキストはUTF-8でエンコードされたUnicode文字なので、UTF-8でエンコードされた複数のバイトが1つの整数値を表すことがあります。たとえば、リテラルの 'a' は、リテラルのa(Unicode U+0061、値0x61)を表す1バイトを保持し、 'ä' は、リテラルのa-dieresis(U+00E4、値0xe4)を表す2バイト(0xc3 0xa4)を保持します。

いくつかのバックスラッシュエスケープにより、任意の値をASCIIテキストとしてエンコードすることができる。整数値を数値定数として表すには4つの方法があります。\x の後に16進数の数字を2つ並べる方法、 \u の後に16進数の数字を4つ並べる方法、\U の後に16進数の数字を8つ並べる方法、そしてバックスラッシュ \ の後に8進数の数字を3つ並べる方法です。いずれの場合も、リテラルの値は、対応する基数の数字で表される値となります。

これらの表現はすべて整数になりますが、それぞれ有効な範囲が異なります。8進数エスケープは、0から255までの値を表さなければなりません。16進数のエスケープは、構造上この条件を満たします。0x10FFFF以上の値やサロゲートハーフなど、Unicodeのコードポイントを表すエスケープがあります。

バックスラッシュの後、ある1文字のエスケープは特別な値を表します。

\a   U+0007 アラートまたはベル
\b   U+0008 バックスペース
\f   U+000C フォームフィールド
\n   U+000A ラインフィードまたは改行
\r   U+000D キャリッジリターン
\t   U+0009 水平タブ
\v   U+000B 垂直タブ
\\   U+005C バックスラッシュ
\'   U+0027 シングルクォート(ルーンリテラル内でのみ有効なエスケープです)
\"   U+0022 ダブルクォート(文字列リテラル内でのみ有効なエスケープです)

バックスラッシュで始まる他のすべてのシーケンスは、ルーンリテラル内では違法です。

構文
rune_lit         = "'" ( unicode_value | byte_value ) "'" ;
unicode_value    = unicode_char | little_u_value | big_u_value | escaped_char ;
byte_value       = octal_byte_value | hex_byte_value ;
octal_byte_value = `\` octal_digit octal_digit octal_digit ;
hex_byte_value   = `\` "x" hex_digit hex_digit ;
little_u_value   = `\` "u" hex_digit hex_digit hex_digit hex_digit ;
big_u_value      = `\` "U" hex_digit hex_digit hex_digit hex_digit
                           hex_digit hex_digit hex_digit hex_digit ;
escaped_char     = `\` ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | `\` | "'" | `"` ) ;
'a'
'ä'
'本'
'\t'
'\000'
'\007'
'\377'
'\x07'
'\xff'
'\u12e4' 
'\U00101234'
'\''         // rune literal containing single quote character
'aa'         // illegal: too many characters
'\xa'        // illegal: too few hexadecimal digits
'\0'         // illegal: too few octal digits
'\uDFFF'     // illegal: surrogate half
'\U00110000' // illegal: invalid Unicode code point
'\''         // シングルクォート文字を含むルーンリテラル
'aa'         // 違法:文字数が多すぎる
'\xa'        // 違法:16進法の桁数が少なすぎる
'\0'         // 違法:8進数が少なすぎる
'\uDFFF'     // 違法:サロゲートの片割れ
'U00110000'  // 違法:無効な Unicode コードポイント

文字列リテラル

[編集]

文字列リテラル(A string literal)とは、一連の文字を連結して得られる文字列定数のことです。生の文字列リテラル(Raw string literals)と解釈される文字列リテラル(Interpreted string literals)の2つの形式があります[11]

生の文字列リテラル(Raw string literals)は、`foo`のようにバッククォートで囲まれた文字列です。引用符の中には、バッククォート以外の任意の文字を入れることができます。生の文字列リテラルの値は、引用符の間にある解釈されていない(暗黙のうちにUTF-8にエンコードされている)文字で構成される文字列です。生の文字列リテラルに含まれるキャリッジリターン文字('\r')は、生の文字列値から削除されます。

解釈される文字列リテラル(Interpreted string literals)は、"bar" のように二重引用符で囲まれた文字列です。引用符の中には、改行とエスケープされていない二重引用符以外の任意の文字を入れることができます。引用符の間の文字はリテラルの値を形成し、バックスラッシュのエスケープはルーンリテラルの場合と同様に解釈されます(ただし、\' は違法、 \" は合法です)。3桁の8進数(\nnn)と2桁の16進数(\xnn)のエスケープは、結果として得られる文字列の個々のバイトを表します。他のすべてのエスケープは、個々の文字の(おそらく複数バイトの)UTF-8エンコーディングを表します。文字列リテラルの中では、\377と\xFFは0xFF=255の値を持つ1バイトを表し、ÿ、\u00FF、\U000000FF、\xc3\xbfは、文字U+00FFのUTF-8エンコーディングの2バイト0xc3 0xbfを表します。

構文
string_lit             = raw_string_lit | interpreted_string_lit ;
raw_string_lit         = "`" { unicode_char | newline } "`" ;
interpreted_string_lit = `"` { unicode_value | byte_value } `"` ;
`abc`                // "abc" に同じ
`\n
\n`                  // "\\n\n\\n" に同じ
"\n"
"\""                 // `"` に同じ
"Hello, world!\n"
"日本語"
"\u65e5本\U00008a9e"
"\xff\u00FF"
"\uD800"             // 違法:サロゲートの片割れ
"\U00110000"         // 違法:無効な Unicode コードポイント

これらの例はすべて同じ文字列を表しています。

"日本語"                                // UTF-8入力テキスト
`日本語`                                // UTF-8の入力テキストを生のリテラルにしたもの
"\u65e5\u672c\u8a9e"                    // 明示的なUnicodeコードポイント
"\U000065e5\U0000672c\U00008a9e"        // 明示的なUnicodeコードポイント 
"\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"  // 明示的なUTF-8の8バイト

ソースコードが、アクセントと文字を含む結合形式( combining form)のように、1つの文字を2つのコードポイントで表現している場合、ルーンリテラルに入れるとエラーになり(1つのコードポイントではありません)、文字列リテラルに入れると2つのコードポイントとして表示されます。

脚註

[編集]
  1. ^ “Lexical elements ¶”. The Go Programming Language Specification. The Go website. (Jul 26, 2021). https://golang.org/ref/spec#Lexical_elements. 
  2. ^ “Comments ¶”. The Go Programming Language Specification. The Go website. (Jul 26, 2021). https://golang.org/ref/spec#Comments. 
  3. ^ “Semicolons ¶”. The Go Programming Language Specification. The Go website. (Jul 26, 2021). https://golang.org/ref/spec#Semicolons. 
  4. ^ “Identifiers ¶”. The Go Programming Language Specification. The Go website. (Jul 26, 2021). https://golang.org/ref/spec#Identifiers. 
  5. ^ “Keywords ¶”. The Go Programming Language Specification. The Go website. (Jul 26, 2021). https://golang.org/ref/spec#Keywords. 
  6. ^ “Operators and punctuation ¶”. The Go Programming Language Specification. The Go website. (March 10, 2022). https://golang.org/ref/spec#Operators_and_punctuation. 
  7. ^ “Integer literals¶”. The Go Programming Language Specification. The Go website. (Jul 26, 2021). https://golang.org/ref/spec#Integer_literals. 
  8. ^ “Floating-point literals¶”. The Go Programming Language Specification. The Go website. (Jul 26, 2021). https://golang.org/ref/spec#Floating-point_literals. 
  9. ^ “Imaginary literals¶”. The Go Programming Language Specification. The Go website. (Jul 26, 2021). https://golang.org/ref/spec#Imaginary_literals. 
  10. ^ “Rune literals¶”. The Go Programming Language Specification. The Go website. (Jul 26, 2021). https://golang.org/ref/spec#Rune_literals. 
  11. ^ “String literals¶”. The Go Programming Language Specification. The Go website. (Jul 26, 2021). https://golang.org/ref/spec#String_literals.