D 1.0   D 2.0
About Japanese Translation

Last update Wed Nov 10 12:48:19 2010

字句の構成

Dでは、 字句解析は構文解析や意味解析とは独立しています。 字句解析器は文法に従ってソーステキストをトークンに分解しますが、 Dの字句解析の文法は、 特殊な規則をできる限り減らしてあるので、 正確で高速な解析器が簡単に書けるようになっています。 各トークンは、 C/C++に慣れた人にはわかりやすいものです。

コンパイルの段階

コンパイル処理は複数の段階に分かれています。 各々の段階どうしには依存関係はありません。例えば、 構文解析器は意味解析の結果に依存していません。 このように段階ごとにわかれていることで、 予約語の色分けのできるエディタの開発などが書きやすくなっています。 Dのソースを圧縮して、 'トークン分けされた'状態で保持することも可能です。
  1. ソースの文字セット
    ソースファイルがどの文字コードで書かれているのかを調べ、 適切な解析器を呼び出します。 ASCIIかUTF形式が利用できます。
  2. スクリプト行
    先頭の行が #! で始まっていた場合、 その先頭行は無視されます。
  3. 字句解析
    ソースファイルをトークンの列へと分解します。 特殊トークン は他のトークンへと置換されます。 特殊トークン列 はこの段階で処理され、取り除かれます。
  4. 構文解析
    トークンの列から構文木を作ります。
  5. 意味解析
    構文木をたどって、変数を宣言したりシンボルテーブルをロードしたり式に型を割り当てたり します。まとめて言うと、プログラムの意味を決定します。
  6. 最適化
    最適化、プログラムを書き換えて、 意味は同等でもより高速に実行されるバージョンを作ろうとする課程です。
  7. コード生成
    プログラムの意味を実現するために、 目的のアーキテクチャの命令コードが選ばれます。 典型的な出力形式は、リンカへの入力に適した、オブジェクトファイルです。

ソーステキスト

Dのソーステキストは次のフォーマットのいずれかです: UTF-8 は 7bit ASCII のスーパーセットです。 以下の BOM (Byte Order Mark) がソースの先頭に置かれていても構いません:

UTF バイト順マーク
形式 BOM
UTF-8 EF BB BF
UTF-16BE FE FF
UTF-16LE FF FE
UTF-32BE 00 00 FE FF
UTF-32LE FF FE 00 00
ASCII BOMはつかない

ソースファイルが BOM で始まらない場合は、 最初の2文字は必ず U0000007F 以下でなければなりません。

二連文字(digraph)や三連文字(trigraph)はDには存在しません。

ソーステキストは、Unicode文字の列へとデコードされ、 解釈されます。 Unicode文字は、以下に分類されます: 空白文字行終端コメント特殊トークン列トークン、 そして最後に、ファイル終端

トークンへ分解する際には、最長一致戦略を用います。つまり、 字句解析器はできるだけ長いトークンを探そうとします。 例えば >> は右シフトトークンであって、 2個の不等号トークンとは解釈しません。この規則の例外は、 浮動小数点数リテラルとして読めるトークンに挟まれた .. です。 例えば 1..2 は、.. が先頭の 1 と空白で区切られているかのように解釈されます。

ファイル終端

EndOfFile:
	physical end of the file
	\u0000
	\u001A
どれかが一番最初に出現した点をソースの終端とします。

行終端

EndOfLine:
	\u000D
	\u000A
	\u000D \u000A
	EndOfFile
バックスラッシュで行を分けることはできません。 1行の文字数に制限はありません。

空白

WhiteSpace:
	Space
	Space WhiteSpace

Space:
	\u0020
	\u0009
	\u000B
	\u000C

コメント

Comment:
	/* Characters */
	// Characters EndOfLine
	NestingBlockComment

Characters:
	Character
	Character Characters

NestingBlockComment:
	/+ NestingBlockCommentCharacters +/

NestingBlockCommentCharacters:
	NestingBlockCommentCharacter
	NestingBlockCommentCharacter NestingBlockCommentCharacters

NestingBlockCommentCharacter:
	Character
	NestingBlockComment
Dには三種類のコメントがあります:
  1. ネストしないブロックコメント
  2. 行コメント
  3. ネストできるブロックコメント

文字列とコメントの中身はトークン分けされません。従って、 文字列中に埋め込まれたコメント開始記号ではコメント扱いになりませんし、 コメント内に埋め込まれた引用符では文字列扱いになりません。 "/+" コメントの中の "/+" をのぞき、 コメント中のコメント開始記号も 単純に無視されます。

a = /+ // +/ 1;		// 'a = 1;' として解析される
a = /+ "+/" +/ 1";	// 'a = " +/ 1";' として解析される
a = /+ /* +/ */ 3;	// 'a = */ 3;' として解析される
コメントを間に挟むと、トークンは分割されます。例えば abc/**/def は2つのトークン abcdef です。1つの abcdef ではありません。

トークン

Token:
	Identifier
	StringLiteral
	CharacterLiteral
	IntegerLiteral
	FloatLiteral
	Keyword
	/
	/=
	.
	..
	...
	&
	&=
	&&
	|
	|=
	||
	-
	-=
	--
	+
	+=
	++
	<
	<=
	<<
	<<=
	<>
	<>=
	>
	>=
	>>=
	>>>=
	>>
	>>>
	!
	!=
	!<>
	!<>=
	!<
	!<=
	!>
	!>=
	(
	)
	[
	]
	{
	}
	?
	,
	;
	:
	$
	=
	==
	*
	*=
	%
	%=
	^
	^=
	~
	~=

識別子

Identifier:
	IdentiferStart
	IdentiferStart IdentifierChars

IdentifierChars:
	IdentiferChar
	IdentiferChar IdentifierChars

IdentifierStart:
	_
	Letter
	UniversalAlpha

IdentifierChar:
	IdentiferStart
	0
	NonZeroDigit
識別子はアルファベットか _、または普遍基本文字(Universal Alpha)で始まり、 アルファベット,_,数字,普遍基本文字の列が後ろに続いたものです。 普遍基本文字は ISO/IEC 9899:1999(E) Appendix D. (C99標準です) に (訳注: Universal character names for identifiers として)定義されています。識別子は大文字小文字を区別します。 長さに制限はありません。 __ (2個のアンダースコア)で始まる識別子は処理系側に予約されています。

文字列リテラル

StringLiteral:
	WysiwygString
	AlternateWysiwygString
	DoubleQuotedString
	EscapeSequence
	HexString


WysiwygString:
	r" WysiwygCharacters " Postfixopt

AlternateWysiwygString:
	` WysiwygCharacters ` Postfixopt

WysiwygCharacters:
	WysiwygCharacter
	WysiwygCharacter WysiwygCharacters

WysiwygCharacter:
	Character
	EndOfLine

DoubleQuotedString:
	" DoubleQuotedCharacters " Postfixopt

DoubleQuotedCharacters:
	DoubleQuotedCharacter
	DoubleQuotedCharacter DoubleQuotedCharacters

DoubleQuotedCharacter:
	Character
	EscapeSequence
	EndOfLine

EscapeSequence:
	\'
	\"
	\?
	\\
	\a
	\b
	\f
	\n
	\r
	\t
	\v
	\ EndOfFile
	\x HexDigit HexDigit
	\ OctalDigit
	\ OctalDigit OctalDigit
	\ OctalDigit OctalDigit OctalDigit
	\u HexDigit HexDigit HexDigit HexDigit
	\U HexDigit HexDigit HexDigit HexDigit HexDigit HexDigit HexDigit HexDigit
	\& NamedCharacterEntity ;

HexString:
	x" HexStringChars " Postfixopt

HexStringChars:
	HexStringChar
	HexStringChar HexStringChars

HexStringChar:
	HexDigit
	WhiteSpace
	EndOfLine

Postfix:
	c
	w
	d


文字列リテラルは、二重引用符かWYSIWYG引用符で囲まれた 文字列やエスケープシーケンス、 16進文字列です。

Wysiwyg 文字列

WYSIWYG文字列は r" と " で囲みます。 r" と " の間の全ての文字は 文字列として扱われます。 行終端文字 は \n 文字1文字となります。 この中ではエスケープシーケンスは使用できません。

r"hello"
r"c:\root\foo.exe"
r"ab\n"			// 4文字 'a', 'b', '\', 'n' からなる文字列

WYSIWYG文字には、バッククォート ` を使った表現もあります。 この ` 文字はキーボードによっては存在しなかったり、 フォントによっては普通の引用符 ' と区別できないことがあります。 このため ` が使用されることはまれですが、" を含む文字列を書くには便利です。

`hello`
`c:\root\foo.exe`
`ab\n`			// 4文字 'a', 'b', '\', 'n' からなる文字列

二重引用符文字列

二重引用符 "" の中では、おなじみの \ を使った記法で エスケープシーケンスを使うことができます。 行終端文字 は \n 文字1文字として扱われます。
"hello"
"c:\\root\\foo.exe"
"ab\n"			// 3文字の文字列 'a', 'b', 改行
"ab
"			// これも3文字の文字列 'a', 'b', 改行

エスケープ文字列

\から始まる文字の並びはエスケープシーケンスになります。 隣り合ったエスケープ文字列は連結されます。

\n			改行文字
\t			タブ文字
\"			二重引用符文字
\012			8進表記
\x1A			16進表記
\u1234			wchar文字
\U00101234		dchar文字
\&reg;			® dchar文字
\r\n			復帰改行

未定義のエスケープシーケンスはエラーとなります。 文字列リテラルはUTF文字の組み合わせであると定義されていますが、 8進/16進エスケープシーケンスを用いることで、 任意のバイナリデータを挿入することも可能です。 一方でエスケープシーケンス \u と \U では、 有効な UTF 文字のみが挿入できます。

16進文字列

16進文字列は、16進データを使って文字列リテラルを記述する方法です。 16進データは有効なUTF文字である必要はありません。

x"0A"			// "\x0A" と同じ
x"00 FBCD 32FD 0A"	// "\x00\xFB\xCD\x32\xFD\x0A" と同じ
空白や改行文字は無視されるので、 16進データを整形して並べることができます。 16進文字の個数は2の倍数でなくてはなりません。

演算子~でつなげられているか、 あるいは単純に並べて書かれている文字列どうしは結合されます:

"hello " ~ "world" ~ \n	// 文字列 'h','e','l','l','o',' ',
			// 'w','o','r','l','d',改行, となる
以下は全て同じ意味です:
"ab" "c"
r"ab" r"c"
r"a" "bc"
"a" ~ "b" ~ "c"
\x61"bc"
追加の Postfix 文字によって、 文字列リテラルの型を文脈から推論させるのではなく、明示的に指定できます。 これは、あいまいなく型を推論することが不可能なとき、例えば 文字列の型によるオーバーロードがあるときなどに役に立ちます。 postfixと対応する型はそれぞれ:

文字列リテラル後置文字
Postfix
c char[ ]
w wchar[ ]
d dchar[ ]
"hello"c          // char[]
"hello"w          // wchar[]
"hello"d          // dchar[]

文字列リテラルは読み取り専用です。文字列リテラルへの書き込みは、 未定義動作となります。

文字リテラル

CharacterLiteral:
	' SingleQuotedCharacter '

SingleQuotedCharacter:
	Character
	EscapeSequence
文字リテラルは、1文字分の文字かエスケープシーケンスです。 一重引用符 ' ' でくくられます。

整数リテラル

IntegerLiteral:
	Integer
	Integer IntegerSuffix

Integer:
	Decimal
	Binary
	Octal
	Hexadecimal

IntegerSuffix:
	L
	u
	U
	Lu
	LU
	uL
	UL

Decimal:
	0
	NonZeroDigit
	NonZeroDigit DecimalDigits

Binary:
	0b BinaryDigits
	0B BinaryDigits

Octal:
	0 OctalDigits

Hexadecimal:
	0x HexDigits
	0X HexDigits

NonZeroDigit:
	1
	2
	3
	4
	5
	6
	7
	8
	9

DecimalDigits:
	DecimalDigit
	DecimalDigit DecimalDigits

DecimalDigit:
	0
	NonZeroDigit
	_

BinaryDigits:
	BinaryDigit
	BinaryDigit BinaryDigits

BinaryDigit:
	0
	1
	_

OctalDigits:
	OctalDigit
	OctalDigit OctalDigits

OctalDigit:
	0
	1
	2
	3
	4
	5
	6
	7
	_

HexDigits:
	HexDigit
	HexDigit HexDigits

HexDigit:
	DecimalDigit
	a
	b
	c
	d
	e
	f
	A
	B
	C
	D
	E
	F
	_
整数は10進,2進,8進,16進のどれかの記法で表記します。

10進整数は、0,1,..,9の並びです。

2進整数は '0b' で始まる0,1の並びです。

8進整数は '0'で始まる0,1,..,7の並びです。

16進整数は、'0x' で始まる 0,1,..,9,A,..,F,a,..,f の並びです。

整数の途中に文字 '_' を入れることができます。 この文字は単に無視されます。 長いリテラルの整形に、例えば1000単位の区切りとしてなどで役に立ちます。

123_456		// 123456
1_2_3_4_5_6_	// 123456
整数の後ろに 'L' または 'u' 、あるいはその両方が続くことがあります。

整数の型は次のように決定されます:

10進リテラルの型
10進リテラル
0 .. 2147483647 int
2147483648 .. 9223372036854775807 long
10進リテラル, 接尾辞L
0L .. 9223372036854775807L long
10進リテラル, 接尾辞U
0U .. 4294967295U uint
4294967296U .. 18446744073709551615U ulong
10進リテラル, 接尾辞UL
0UL .. 18446744073709551615UL ulong
非10進リテラル
0x0 .. 0x7FFFFFFF int
0x80000000 .. 0xFFFFFFFF uint
0x100000000 .. 0x7FFFFFFFFFFFFFFF long
0x8000000000000000 .. 0xFFFFFFFFFFFFFFFF ulong
非10進リテラル, 接尾辞L
0x0L .. 0x7FFFFFFFFFFFFFFFL long
0x8000000000000000L .. 0xFFFFFFFFFFFFFFFFL ulong
非10進リテラル, 接尾辞U
0x0U .. 0xFFFFFFFFU uint
0x100000000UL .. 0xFFFFFFFFFFFFFFFFUL ulong
非10進リテラル, 接尾辞UL
0x0UL .. 0xFFFFFFFFFFFFFFFFUL ulong

浮動小数点数リテラル

FloatLiteral:
	Float Suffix
	Integer ImaginarySuffix
	Integer FloatSuffix ImaginarySuffix
	Integer RealSuffix ImaginarySuffix

Float:
	DecimalFloat
	HexFloat

DecimalFloat:
	LeadingDecimal .
	LeadingDecimal . DecimalDigits
	DecimalDigits . DecimalDigits DecimalExponent
	. DecimalDigits
	. DecimalDigits DecimalExponent
	LeadingDecimal DecimalExponent

DecimalExponent
	e DecimalDigits
	E DecimalDigits
	e+ DecimalDigits
	E+ DecimalDigits
	e- DecimalDigits
	E- DecimalDigits

HexFloat:
	HexPrefix HexDigits . HexDigits HexExponent
	HexPrefix . HexDigits HexExponent
	HexPrefix HexDigits HexExponent

HexPrefix:
	0x
	0X

HexExponent:
	p DecimalDigits
	P DecimalDigits
	p+ DecimalDigits
	P+ DecimalDigits
	p- DecimalDigits
	P- DecimalDigits

Suffix:
	FloatSuffix
	RealSuffix
	ImaginarySuffix
	FloatSuffix ImaginarySuffix
	RealSuffix ImaginarySuffix

FloatSuffix:
	f
	F

RealSuffix:
	L

ImaginarySuffix:
	i

LeadingDecimal:
	Decimal
	0 DecimalDigits
浮動小数点数は、標準Cと同様に、 10進または16進表記が可能です。

16進浮動小数は 0x で始まり、 指数部は pP のうしろに 2 の指数を表す数を続けたものです。

浮動小数点数リテラルの途中に文字 '_' を入れることができ、 この文字は単に無視されます。 長いリテラルを整形して読みやすくするのに役立ちます。 例えば、1000単位の区切りとしてなど:

123_456.567_8		// 123456.5678
1_2_3_4_5_6_._5_6_7_8	// 123456.5678
1_2_3_4_5_6_._5e-6_	// 123456.5e-6
接尾辞のない浮動小数点数はdouble型です。 浮動小数点数には接尾辞 f, F, L のうちどれか一つを付けることができます。 fF は値がfloat型であることを示し、 L はreal型であることを示します。

接尾辞 i があれば、 ireal (虚数) 型です。

例:

0x1.FFFFFFFFFFFFFp1023		// double.max
0x1p-52				// double.epsilon
1.175494351e-38F		// float.min
6.3i				// idouble 6.3
6.3fi				// ifloat 6.3
6.3Li				// ireal 6.3
リテラルが型の表現可能な範囲を超えていると、 エラーになります。 リテラルの示す値の下位桁が丸められるのはエラーではありません。

複素数リテラルはトークンではなく、意味解析によって 実数と虚数トークンが組み合わせられます。

4.5 + 6.2i		// 複素数

予約語

以下が予約された識別子です:
Keyword:
	abstract
	alias
	align
	asm
	assert
	auto

	body
	bool
	break
	byte

	case
	cast
	catch
	cdouble
	cent
	cfloat
	char
	class
	const
	continue
	creal

	dchar
	debug
	default
	delegate
	delete
	deprecated
	do
	double

	else
	enum
	export
	extern

	false
	final
	finally
	float
	for
	foreach
	function
	foreach_reverse

	goto

	idouble
	if
	ifloat
	import
	in
	inout
	int
	interface
	invariant
	ireal
	is

	lazy
	long

	macro
	mixin
	module

	new
	null

	out
	override

	package
	pragma
	private
	protected
	public

	real
	ref
	return

	scope
	short
	static
	struct
	super
	switch
	synchronized

	template
	this
	throw
	true
	try
	typedef
	typeid
	typeof

	ubyte
	ucent
	uint
	ulong
	union
	unittest
	ushort

	version
	void
	volatile

	wchar
	while
	with

特殊トークン

特殊トークンは、 以下の表に従って別のトークンへと置換されます:

特殊トークン
特殊トークン 置換後...
__FILE__ ソースファイル名の文字列リテラル
__LINE__ 現在のソース行番号の整数リテラル
__DATE__ コンパイルした日にちの文字列リテラル "mmm dd yyyy"
__TIME__ コンパイルした時刻の文字列リテラル "hh:mm:ss"
__TIMESTAMP__ コンパイルした日時の文字列リテラル "www mmm dd hh:mm:ss yyyy"
__VENDOR__ コンパイラベンダ名文字列。例えば "Digital Mars D"
__VERSION__ コンパイラのバージョン番号を表す整数。例えば 2001

特殊トークン列

特殊トークン列は、トークン列のどの位置にでも登場でき、 字句解析器によって処理されます。 構文解析には影響しません。

現在の所、特殊トークン列は #line 一つだけです。

SpecialTokenSequence:
	# line Integer EndOfLine
	# line Integer Filespec EndOfLine

Filespec:
	" Characters "
これによって、 次の行の行番号は Integer に、 ファイル名は(もしあれば)Filespec に設定されます。 ソースファイル名と行番号は、 エラーメッセージや デバッガ用のシンボルとして使用されています。

例:

int #line 6 "foo\bar"
x;			// ここがファイル foo\bar の6行目扱いになる
バックスラッシュ文字は Filespec 文字列の中では 特別扱いされないことにご注意下さい。