어휘 구조
어휘 구조 (Lexical)
D 언어는 소스 코드를 읽는 과정부터 독특한 설계를 갖고 있어요. Lexical(어휘) 챕터는 바로 이 최초의 단계 — 원문 텍스트를 토큰(token)으로 쪼개는 규칙 — 을 다루는 부분이에요. 컴파일러가 코드를 이해하는 첫 번째 문턱이니까, 나중에 문법(syntax)이나 의미(semantics)를 배울 때 뼈대가 된다고 생각하면 돼요. 여기서는 코드가 어떻게 인코딩되고, 주석은 어떻게 처리되며, 문자열·숫자 리터럴이 어떻게 생겨먹는지까지 차근차근 설명할게요.
본문
서론
어휘 분석(lexical analysis)은 구문 분석(syntax parsing)이나 의미 분석(semantic analysis)과 독립적으로 동작해요. 어휘 분석기는 소스 텍스트를 토큰들로 쪼개죠. 이 장에서 설명하는 어휘 문법(lexical grammar) 은 바로 그 토큰들의 문법이에요. 이 문법은 고속 스캐닝에 적합하도록, 그리고 올바른 스캐너 구현을 쉽게 만들도록 설계되었어요. 그래서 특수 케이스 규칙이 최소한이고, 번역 단계(phase)도 하나뿐이죠.
소스 텍스트 (Source Text)
소스 파일의 구조는 이런 식이에요:
SourceFile:
ByteOrderMark Moduleopt
Shebang Moduleopt
Moduleopt
ByteOrderMark:
\uFEFF
Shebang:
#! Charactersopt EndOfShebang
EndOfShebang:
\u000A
EndOfFile
소스 텍스트는 다음 중 어떤 인코딩으로든 작성될 수 있어요:
- ASCII (엄밀히 말하면 7-bit ASCII)
- UTF-8
- UTF-16BE
- UTF-16LE
- UTF-32BE
- UTF-32LE
소스 텍스트 시작 부분에는 다음 UTF BOM(Byte Order Mark) 중 하나가 올 수 있어요:
UTF Byte Order Marks
| Format | 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으로 시작하지 않는다면, 첫 번째 문자가 반드시 U+0000007F 이하여야 해요.
소스 텍스트는 원래 표현(source representation)에서 Unicode 문자(Characters) 로 디코딩돼요. 그리고 그 문자들은 다시 WhiteSpace, EndOfLine, Comments, SpecialTokenSequences, Tokens로 나뉘고, 소스는 EndOfFile로 끝나요.
토큰 분리에는 maximal munch(가장 긴 토큰 우선) 알고리즘이 적용돼요. 즉, 어휘 분석기는 가능한 가장 긴 토큰을 가정한다는 뜻이에요. 예를 들어 >>는 두 개의 greater-than 토큰이 아니라 하나의 right-shift 토큰으로 취급되죠. 이 규칙에는 예외가 두 개 있어요:
- 두 개의 부동소수점 리터럴처럼 보이는 것 사이에 끼어 있는
.., 예를 들면1..2는, 마치..가 첫 정수와 공백으로 분리되어 있는 것처럼 해석돼요. 1.a는1,.,a세 개의 토큰으로 해석되는 반면,1. a는1.과a두 개의 토큰으로 해석돼요.
문자 집합 (Character Set)
Character:
any Unicode character
파일의 끝 (End of File)
EndOfFile:
physical end of the file
\u0000
\u001A
소스 텍스트는 다음 중 먼저 오는 것으로 종료돼요: 물리적인 파일 끝, \u0000, 또는 \u001A.
줄의 끝 (End of Line)
EndOfLine:
\u000D
\u000A
\u000D \u000A
\u2028
\u2029
EndOfFile
공백 (White Space)
WhiteSpace:
Space
Space WhiteSpace
Space:
\u0020
\u0009
\u000B
\u000C
주석 (Comments)
Comment:
BlockComment
LineComment
NestingBlockComment
BlockComment:
/* Charactersopt */
LineComment:
// Charactersopt EndOfLine
NestingBlockComment:
/+ NestingBlockCommentCharactersopt +/
NestingBlockCommentCharacters:
NestingBlockCommentCharacter
NestingBlockCommentCharacter NestingBlockCommentCharacters
NestingBlockCommentCharacter:
Character
NestingBlockComment
Characters:
Character
Character Characters
D에는 세 종류의 주석이 있어요:
- 블록 주석(Block comment) — 여러 줄에 걸칠 수 있지만, 중첩(nest)되지는 않아요.
- 줄 주석(Line comment) — 줄의 끝에서 끝나요.
- 중첩 블록 주석(Nesting block comment) — 여러 줄에 걸칠 수 있고 중첩도 가능해요.
문자열과 주석의 내용은 토큰화되지 않아요. 그래서 문자열 안에 나타나는 주석 시작 기호는 주석을 시작시키지 않고, 주석 안의 문자열 구분자도 주석 종료/중첩 /+ 시작을 인식하는 데 영향을 주지 않아요. 단, /+ 주석 안에서 나타나는 /+를 제외하면, 주석 안의 주석 시작 기호는 무시돼요.
a = /+ // +/ 1; // parses as if 'a = 1;'
a = /+ "+/" +/ 1"; // parses as if 'a = " +/ 1";'
a = /+ /* +/ */ 3; // parses as if 'a = */ 3;'
주석은 토큰 연결자(token concatenator)로 쓸 수 없어요. 예를 들어 abc/**/def는 abc와 def라는 두 개의 토큰이지, abcdef라는 한 개의 토큰이 아니에요.
토큰 (Tokens)
Tokens:
Token
Token Tokens
Token:
{
}
TokenNoBraces
TokenNoBraces:
Identifier
StringLiteral
InterpolationExpressionSequence
CharacterLiteral
IntegerLiteral
FloatLiteral
Keyword
/
/=
.
..
...
&
&=
&&
|
|=
||
-
-=
--
+
+=
++
<
<=
<<
<<=
>
>=
>>=
>>>=
>>
>>>
!
!=
(
)
[
]
?
,
;
:
$
=
==
*
*=
%
%=
^
^=
^^
^^=
~
~=
@
=>
식별자 (Identifiers)
Identifier:
IdentifierStart
IdentifierStart IdentifierChars
IdentifierChars:
IdentifierChar
IdentifierChar IdentifierChars
IdentifierStart:
_
Letter
UniversalAlpha
IdentifierChar:
IdentifierStart
0
NonZeroDigit
식별자는 문자(letter), _, 또는 universal alpha로 시작하고, 그 뒤에 문자·_·숫자·universal alpha가 몇 개든 이어질 수 있어요. universal alpha는 C99 표준의 ISO/IEC 9899:1999(E) 부록 D에 정의된 것을 따르고요. 식별자는 길이에 제한이 없고, 대소문자를 구분해요.
구현 정의(Implementation Defined):
__(밑줄 두 개)로 시작하는 식별자는 예약되어 있어요.
문자열 리터럴 (String Literals)
StringLiteral:
WysiwygString
AlternateWysiwygString
DoubleQuotedString
DelimitedString
TokenString
HexString
문자열 리터럴은 wysiwyg 문자열, 이중 따옴표(double quoted) 문자열, delimited 문자열, token 문자열, 또는 hex 문자열 중 하나예요.
모든 문자열 리터럴 형식에서, EndOfLine은 단일 \n 문자 하나로 취급돼요.
Wysiwyg 문자열 (Wysiwyg Strings)
WysiwygString:
r" WysiwygCharactersopt " StringPostfixopt
AlternateWysiwygString:
` WysiwygCharactersopt ` StringPostfixopt
WysiwygCharacters:
WysiwygCharacter
WysiwygCharacter WysiwygCharacters
WysiwygCharacter:
Character
EndOfLine
Wysiwyg(“what you see is what you get”, 보이는 그대로) 문자열은 두 가지 문법 중 하나로 정의할 수 있어요.
첫 번째 형식은 r"와 " 사이에 감싸는 방식이에요. r"와 " 사이의 모든 문자가 전부 문자열의 일부가 되죠. wysiwyg 문자열 안에는 이스케이프 시퀀스가 전혀 없어요.
r"I am Oz"
r"c:\games\Sudoku.exe"
r"ab\n" // string is 4 characters,
// 'a', 'b', '\', 'n'
또는 wysiwyg 문자열을 백쿼트(backquote) ` 문자로 감쌀 수도 있어요.
`the Great and Powerful.`
`c:\games\Empire.exe`
`The "lazy" dog`
`a"b\n` // string is 5 characters,
// 'a', '"', 'b', '\', 'n'
함께 보기: InterpolatedWysiwygLiteral
이중 따옴표 문자열 (Double Quoted Strings)
DoubleQuotedString:
" DoubleQuotedCharactersopt " StringPostfixopt
DoubleQuotedCharacters:
DoubleQuotedCharacter
DoubleQuotedCharacter DoubleQuotedCharacters
DoubleQuotedCharacter:
Character
EscapeSequence
EndOfLine
이중 따옴표 문자열은 "로 감싸요. 그 안에는 이스케이프 시퀀스(EscapeSequence) 를 넣을 수 있어요.
"Who are you?"
"c:\\games\\Doom.exe"
"ab\n" // string is 3 characters,
// 'a', 'b', and a linefeed
"ab
" // string is 3 characters,
// 'a', 'b', and a linefeed
함께 보기: InterpolatedDoubleQuotedLiteral
Delimited 문자열 (Delimited Strings)
DelimitedString:
q" Delimiter WysiwygCharactersopt MatchingDelimiter " StringPostfixopt
q"( ParenDelimitedCharactersopt )" StringPostfixopt
q"[ BracketDelimitedCharactersopt ]" StringPostfixopt
q"{ BraceDelimitedCharactersopt }" StringPostfixopt
q"< AngleDelimitedCharactersopt >" StringPostfixopt
Delimiter:
Identifier
MatchingDelimiter:
Identifier
ParenDelimitedCharacters:
WysiwygCharacter
WysiwygCharacter ParenDelimitedCharacters
( ParenDelimitedCharactersopt )
BracketDelimitedCharacters:
WysiwygCharacter
WysiwygCharacter BracketDelimitedCharacters
[ BracketDelimitedCharactersopt ]
BraceDelimitedCharacters:
WysiwygCharacter
WysiwygCharacter BraceDelimitedCharacters
{ BraceDelimitedCharactersopt }
AngleDelimitedCharacters:
WysiwygCharacter
WysiwygCharacter AngleDelimitedCharacters
< AngleDelimitedCharactersopt >
Delimited 문자열은 다양한 형태의 구분자(delimiter) 를 사용해요. 구분자(문자든 식별자든)는 공백 없이 " 바로 뒤에 와야 해요. 그리고 종료 구분자는 공백 없이 닫는 " 바로 앞에 와야 하죠. 중첩 구분자(nesting delimiter) 는 중첩이 허용되며, 다음 문자 중 하나예요:
Nesting Delimiters
| Delimiter | Matching Delimiter |
|---|---|
| [ | ] |
| ( | ) |
| < | > |
| { | } |
q"(foo(xxx))" // "foo(xxx)"
q"[foo{]" // "foo{"
구분자가 식별자라면, 그 식별자 바로 뒤에 새 줄(newline)이 와야 하고, 짝이 되는 구분자도 같은 식별자여야 하며 줄의 처음에서 시작해야 해요:
writeln(q"EOS
This
is a multi-line
heredoc string
EOS"
);
여는 식별자 다음의 새 줄은 문자열의 일부가 아니지만, 닫는 식별자 바로 앞의 마지막 새 줄은 문자열의 일부가 돼요. 닫는 식별자는 반드시 맨 왼쪽 열에서 자기 줄에 위치해야 해요.
그 외의 경우, 짝 구분자는 구분자 문자 자체와 같아요:
q"/foo]/" // "foo]"
// q"/abc/def/" // error
Token 문자열 (Token Strings)
TokenString:
q{ TokenStringTokensopt } StringPostfixopt
TokenStringTokens:
TokenStringToken
TokenStringToken TokenStringTokens
TokenStringToken:
TokenNoBraces
{ TokenStringTokensopt }
Token 문자열은 q{로 시작해서 } 토큰으로 닫혀요. 그 사이에는 유효한 D 토큰이 와야 해요. {와 } 토큰은 중첩될 수 있고, 문자열은 주석을 포함해서 token 문자열의 여는 부분과 닫는 부분 사이의 모든 문자로 만들어져요.
q{this is the voice of} // "this is the voice of"
q{/*}*/ } // "/*}*/ "
q{ world(q{control}); } // " world(q{control}); "
q{ __TIME__ } // " __TIME__ "
// i.e. it is not replaced with the time
// q{ __EOF__ } // error
// __EOF__ is not a token, it's end of file
함께 보기: InterpolatedTokenLiteral
Hex 문자열 (Hex Strings)
HexString:
x" HexStringCharsopt " StringPostfixopt
HexStringChars:
HexStringChar
HexStringChar HexStringChars
HexStringChar:
HexDigit
WhiteSpace
EndOfLine
Hex 문자열은 hex 데이터로 문자열 리터럴을 만들 수 있게 해줘요. 이 hex 데이터는 유효한 UTF 문자를 이룰 필요가 없어요.
x"0A" // same as "\x0A"
x"00 FBCD 32FD 0A" // same as "\x00\xFB\xCD\x32\xFD\x0A"
공백과 새 줄은 무시되므로 hex 데이터를 쉽게 포맷할 수 있어요. hex 문자 개수는 2의 배수여야 해요.
문자열 접미사 (String Postfix)
StringPostfix:
c
w
d
선택적인 StringPostfix 문자는 문자열에 특정 타입을 부여해요. 문맥에서 추론되는 대신이죠. 접미사 문자에 대응하는 타입은 다음과 같아요:
String Literal Postfix Characters
| Postfix | Type | Alias |
|---|---|---|
| c | immutable(char)[] | string |
| w | immutable(wchar)[] | wstring |
| d | immutable(dchar)[] | dstring |
"hello"c // string
"hello"w // wstring
"hello"d // dstring
문자열 리터럴은 UTF-8 char 배열로 조립된 다음, 마지막 단계에서 접미사에 따라 wchar나 dchar로 변환이 적용돼요.
이스케이프 시퀀스 (Escape Sequences)
EscapeSequence:
\'
\"
\?
\\
\0
\a
\b
\f
\n
\r
\t
\v
\x HexDigit HexDigit
\ OctalDigit
\ OctalDigit OctalDigit
\ OctalDigit OctalDigit OctalDigit
\u HexDigit HexDigit HexDigit HexDigit
\U HexDigit HexDigit HexDigit HexDigit HexDigit HexDigit HexDigit HexDigit
\ NamedCharacterEntity
OctalDigit:
0
1
2
3
4
5
6
7
Escape Sequences
| Sequence | Meaning |
|---|---|
| ' | Literal single-quote: ' |
| " | Literal double-quote: " |
| ? | Literal question mark: ? |
| \ | Literal backslash: \ |
| \0 | Binary zero (NUL, U+0000). |
| \a | BEL (alarm) character (U+0007). |
| \b | Backspace (U+0008). |
| \f | Form feed (FF) (U+000C). |
| \n | End-of-line (U+000A). |
| \r | Carriage return (U+000D). |
| \t | Horizontal tab (U+0009). |
| \v | Vertical tab (U+000B). |
| \xnn | Byte value in hexadecimal, where nn is specified as two hexadecimal digits.For example: \xFF represents the character with the value 255. See also: std.conv.hexString. |
| \n\nn\nnn | Byte value in octal.For example: \101 represents the character with the value 65 ('A'). Analogous to hexadecimal characters, the largest byte value is \377 (= \xFF in hexadecimal or 255 in decimal) See also: std.conv.octal. |
| \unnnn | Unicode character U+nnnn, where nnnn are four hexadecimal digits.For example, \u03B3 represents the Unicode character γ (U+03B3 - GREEK SMALL LETTER GAMMA). |
| \Unnnnnnnn | Unicode character U+nnnnnnnn, where nnnnnnnn are 8 hexadecimal digits.For example, \U0001F603 represents the Unicode character U+1F603 (SMILING FACE WITH OPEN MOUTH). |
| \name | Named character entity from the HTML5 specification. These names begin with & and end with ;, e.g., €. See NamedCharacterEntity. |
문자 리터럴 (Character Literals)
CharacterLiteral:
' SingleQuotedCharacter '
SingleQuotedCharacter:
Character
EscapeSequence
문자 리터럴은 작은 따옴표로 감싼 하나의 문자 또는 이스케이프 시퀀스예요.
'h' // the letter h
'\n' // newline
'\\' // the backslash character
문자 리터럴은 char, wchar, dchar 중 하나의 타입으로 결정돼요 (Basic Data Types 참고).
- 리터럴이
\u이스케이프 시퀀스면wchar타입으로 결정돼요. - 리터럴이
\U이스케이프 시퀀스면dchar타입으로 결정돼요.
그 외에는 들어갈 수 있는 가장 작은 크기의 타입으로 결정돼요.
정수 리터럴 (Integer Literals)
IntegerLiteral:
Integer
Integer IntegerSuffix
Integer:
DecimalInteger
BinaryInteger
HexadecimalInteger
IntegerSuffix:
L
u
U
Lu
LU
uL
UL
DecimalInteger:
0 Underscoresopt
NonZeroDigit
NonZeroDigit DecimalDigitsUS
Underscores:
_
Underscores _
NonZeroDigit:
1
2
3
4
5
6
7
8
9
DecimalDigits:
DecimalDigit
DecimalDigit DecimalDigits
DecimalDigitsUS:
DecimalDigitUS
DecimalDigitUS DecimalDigitsUS
DecimalDigitsNoSingleUS:
DecimalDigitsUSopt DecimalDigit DecimalDigitsUSopt
DecimalDigitsNoStartingUS:
DecimalDigit
DecimalDigit DecimalDigitsUS
DecimalDigit:
0
NonZeroDigit
DecimalDigitUS:
DecimalDigit
_
BinaryInteger:
BinPrefix BinaryDigitsNoSingleUS
BinPrefix:
0b
0B
BinaryDigitsNoSingleUS:
BinaryDigitsUSopt BinaryDigit BinaryDigitsUSopt
BinaryDigitsUS:
BinaryDigitUS
BinaryDigitUS BinaryDigitsUS
BinaryDigit:
0
1
BinaryDigitUS:
BinaryDigit
_
HexadecimalInteger:
HexPrefix HexDigitsNoSingleUS
HexDigits:
HexDigit
HexDigit HexDigits
HexDigitsUS:
HexDigitUS
HexDigitUS HexDigitsUS
HexDigitsNoSingleUS:
HexDigitsUSopt HexDigit HexDigitsUSopt
HexDigitsNoStartingUS:
HexDigit
HexDigit HexDigitsUS
HexDigit:
DecimalDigit
HexLetter
HexDigitUS:
HexDigit
_
HexLetter:
a
b
c
d
e
f
A
B
C
D
E
F
정수는 십진수(decimal), 이진수(binary), 또는 십육진수(hexadecimal) 로 지정할 수 있어요.
- 십진수 정수는 십진 숫자의 나열이에요.
- 이진수 정수는
0b또는0B로 시작하는 이진 숫자의 나열이에요. - C 스타일의 8진수 표기법(예:
0167)은 십진 표기와 혼동되기 쉽다고 판단되어, 문자열 리터럴에서만 완전히 지원돼요. D는 여전히std.conv.octal템플릿(예:octal!167)을 통해 컴파일 타임에 해석되는 8진수 정수 리터럴을 지원해요. - 십육진수 정수는
0x또는0X로 시작하는 십육진 숫자의 나열이에요.
10 // decimal
0b1010 // binary
0xA // hex
정수는 가독성을 위해 숫자 다음에 _ 문자를 끼워 넣을 수 있는데, 이 _는 무시돼요.
20_000 // leagues under the sea
867_5309 // number on the wall
1_522_000 // thrust of F1 engine (lbf sea level)
0xBAAD_F00D // magic number for debugging
정수 바로 뒤에는 L 하나, 또는 u·U 중 하나, 또는 둘 다가 올 수 있어요. l(소문자 L) 접미사는 없다는 점을 기억하세요.
정수의 타입은 다음과 같이 결정돼요:
Decimal Literal Types
| Literal | Type |
|---|---|
| 0 .. 2_147_483_647 | int |
| 2_147_483_648 .. 9_223_372_036_854_775_807 | long |
| 9_223_372_036_854_775_808 .. 18_446_744_073_709_551_615 | ulong |
| 0L .. 9_223_372_036_854_775_807L | long |
| 0U .. 4_294_967_295U | uint |
| 4_294_967_296U .. 18_446_744_073_709_551_615U | ulong |
| 0UL .. 18_446_744_073_709_551_615UL | ulong |
| 0x0 .. 0x7FFF_FFFF | int |
| 0x8000_0000 .. 0xFFFF_FFFF | uint |
| 0x1_0000_0000 .. 0x7FFF_FFFF_FFFF_FFFF | long |
| 0x8000_0000_0000_0000 .. 0xFFFF_FFFF_FFFF_FFFF | ulong |
| 0x0L .. 0x7FFF_FFFF_FFFF_FFFFL | long |
| 0x8000_0000_0000_0000L .. 0xFFFF_FFFF_FFFF_FFFFL | ulong |
| 0x0U .. 0xFFFF_FFFFU | uint |
| 0x1_0000_0000U .. 0xFFFF_FFFF_FFFF_FFFFU | ulong |
| 0x0UL .. 0xFFFF_FFFF_FFFF_FFFFUL | ulong |
정수 리터럴은 이 값들을 초과할 수 없어요.
모범 사례(Best Practices):
정수 리터럴에는 8진수 표기법이 지원되지 않아요. 하지만 8진수 정수 리터럴은 std.conv.octal 템플릿(예: octal!167)을 통해 컴파일 타임에 해석할 수 있어요.
부동소수점 리터럴 (Floating Point Literals)
FloatLiteral:
Float Suffixopt
Integer FloatSuffix ImaginarySuffixopt
Integer RealSuffixopt ImaginarySuffix
Float:
DecimalFloat
HexFloat
DecimalFloat:
LeadingDecimal . DecimalDigitsNoStartingUSopt
LeadingDecimal . DecimalDigitsNoStartingUS DecimalExponent
. DecimalDigitsNoStartingUS DecimalExponentopt
LeadingDecimal DecimalExponent
DecimalExponent:
DecimalExponentStart DecimalDigitsNoSingleUS
DecimalExponentStart:
e
E
e+
E+
e-
E-
HexFloat:
HexPrefix HexDigitsNoSingleUS . HexDigitsNoStartingUS HexExponent
HexPrefix . HexDigitsNoStartingUS HexExponent
HexPrefix HexDigitsNoSingleUS HexExponent
HexPrefix HexExponent
HexPrefix:
0x
0X
HexExponent:
HexExponentStart DecimalDigitsNoSingleUS
HexExponentStart:
p
P
p+
P+
p-
P-
Suffix:
FloatSuffix ImaginarySuffixopt
RealSuffix ImaginarySuffixopt
ImaginarySuffix
FloatSuffix:
f
F
RealSuffix:
L
ImaginarySuffix:
i
LeadingDecimal:
DecimalInteger
0 DecimalDigitsNoSingleUS
부동소수점(실수) 리터럴은 십진 또는 십육진 형식이 될 수 있고, 숫자 하나 이상과 소수점·지수·FloatSuffix 중 하나를 반드시 가져야 해요.
십진 실수는 e 또는 E 다음에 오는 십진 수를 10의 지수로 갖는 지수를 가질 수 있어요.
-1.0
1e2 // 100.0
1e-2 // 0.01
-1.175494351e-38F // float.min
십육진 실수는 0x나 0X로 시작하고, 지수는 p 또는 P 다음에 오는 십진 수를 2의 지수로 사용해요.
0xAp0 // 10.0
0x1p2 // 4.0
0x1.FFFFFFFFFFFFFp1023 // double.max
0x1p-52 // double.epsilon
실수 리터럴도 가독성을 위해 숫자 다음에 _ 문자를 끼워 넣을 수 있는데, 무시돼요.
2.645_751
6.022140857E+23
6_022.140857E+20
6_022_.140_857E+20_
- 접미사가 없는 실수 리터럴은
double타입이에요. f또는F가 뒤따르는 실수 리터럴은float타입이에요.L이 뒤따르는 실수 리터럴은real타입이에요.
0.0 // double
0F // float
0.0L // real
리터럴은 타입의 범위를 넘을 수 없어요. 리터럴은 타입의 유효 숫자(significant digit)에 맞게 반올림돼요.
만약 실수 리터럴이 .과 타입 접미사를 모두 가진다면, 반드시 그 사이에 숫자가 하나 이상 있어야 해요:
1f; // OK, float
1.f; // error
1.; // OK, double
참고(Note):
허수(imaginary) 부동소수점 값을 나타내는 i 접미사가 붙은 실수 리터럴은 더 이상 사용되지 않아요(deprecated).
키워드 (Keywords)
키워드는 예약된 식별자예요.
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
foreach_reverse
function
goto
idouble
if
ifloat
immutable
import
in
inout
int
interface
invariant
ireal
is
lazy
long
macro
mixin
module
new
nothrow
null
out
override
package
pragma
private
protected
public
pure
real
ref
return
scope
shared
short
static
struct
super
switch
synchronized
template
this
throw
true
try
typeid
typeof
ubyte
ucent
uint
ulong
union
unittest
ushort
version
void
wchar
while
with
__FILE__
__FILE_FULL_PATH__
__FUNCTION__
__LINE__
__MODULE__
__PRETTY_FUNCTION__
__gshared
__parameters
__rvalue
__traits
__vector
특수 토큰 (Special Tokens)
이 토큰들은 다음 표에 따라 다른 토큰으로 치환돼요:
Special Tokens
| Special Token | Replaced with |
|---|---|
| DATE | string literal of the date of compilation "mmm dd yyyy" |
| EOF | tells the scanner to ignore everything after this token |
| TIME | string literal of the time of compilation "hh:mm:ss" |
| TIMESTAMP | string literal of the date and time of compilation "www mmm dd hh:mm:ss yyyy" |
| VENDOR | Compiler vendor string |
| VERSION | Compiler version as an integer |
구현 정의(Implementation Defined):
__VENDOR__의 치환 문자열 리터럴과 __VERSION__의 치환 정수 값.
특수 토큰 시퀀스 (Special Token Sequences)
SpecialTokenSequence:
# line IntegerLiteral Filespecopt EndOfLine
# line __LINE__ Filespecopt EndOfLine
Filespec:
" DoubleQuotedCharactersopt "
특수 토큰 시퀀스는 어휘 분석기가 처리하며, 다른 토큰들 사이 어디에든 나타날 수 있고 구문 분석에는 영향을 주지 않아요.
특수 토큰 시퀀스는 시퀀스 시작의 첫 번째 # 토큰 뒤에 오는 첫 번째 새 줄에서 종료돼요.
현재 특수 토큰 시퀀스는 #line 하나뿐이에요.
#line은 다음 소스 줄의 줄 번호와 (선택적으로) 현재 소스 파일 이름을, 다음 줄부터 시작해서 바꿔줘요. 예를 들어:
int #line 6 "pkg/mod.d"
x; // this is now line 6 of file pkg/mod.d
구현 정의(Implementation Defined):
소스 파일과 줄 번호는 주로 오류 메시지를 출력하거나, 생성된 코드를 심볼릭 디버깅 출력을 위해 원본 소스에 다시 매핑할 때 사용돼요.
더 알아보기 (Learn more)
- D 언어 공식 사양 전체 목차: https://dlang.org/spec/spec.html
- 어휘와 직접 이어지는 다음 챕터 — 문법(grammar) 구조: https://dlang.org/spec/grammar.html
- 문자열·매크로 등에 등장하는 보간(interpolation) 관련 규칙: https://dlang.org/spec/istring.html
- 이번 챕터에서 나온
std.conv.octal,std.conv.hexString같은 유틸리티: https://dlang.org/phobos/std_conv.html