在D中,詞法分析獨(dú)立于語法分析和語義分析。詞法分析器將源文件分割成記號(hào)。詞法描述了如何識(shí)別記號(hào)。D的詞法被設(shè)計(jì)為適于高速掃描,它擁有最小的特殊規(guī)則集合,只有一遍翻譯,這使得構(gòu)造一個(gè)正確的掃描程序很容易。對(duì)于熟悉
C 和 C++ 的人來說,記號(hào)也很容易識(shí)別。
編譯的階段
編譯被分為多個(gè)階段。每個(gè)階段都不依賴于后繼的階段。例如,掃描程序不依賴于語義分析程序。這種分離使語法制導(dǎo)編輯器等語言工具相對(duì)容易構(gòu)造。這也使通過將其存儲(chǔ)為‘符號(hào)’形式來壓縮
D 源碼成為可能。
- 源碼字符集
先檢查源文件使用的是什么字符集,然后使用合適的掃描程序。可以使用 ASCII 或 UTF 格式。
- 詞法分析
源文件被分割為記號(hào)序列。特殊記號(hào)會(huì)被處理,然后刪除。
- 語法分析
符號(hào)序列被解析為語法樹。
- 語義分析
遍歷語法樹,聲明變量、載入符號(hào)表、分配型別并從大體上決定程序的意義。
- 優(yōu)化
優(yōu)化是可選的一步,它試圖語義等價(jià)的重寫程序,但是生成一個(gè)更為快速的版本。
- 代碼生成
采用目標(biāo)架構(gòu)的指令來實(shí)現(xiàn)程序的語義。典型的結(jié)果是生成一個(gè)目標(biāo)文件,它會(huì)作為連接器的輸入。
源碼文本
D 源碼文本可以是下面各種形式之一:
- ASCII
- UTF-8
- UTF-16BE
- UTF-16LE
- UTF-32BE
- UTF-32LE
UTF-8 是傳統(tǒng)的7位 ASCII 的超集。 源代碼文檔的開始可以是下面的任一個(gè) UTF BOMs(字節(jié)序標(biāo)志)之一:
格式 |
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 |
no BOM |
D 中沒有“雙連符”或者“三連符” 。 (譯注:三連符是一些由 ?? 開頭的連續(xù)的三字符組合,它包括
??=,??/,??',??(,??),??!,??<,??>和??-,這些字符將被直接替換為對(duì)應(yīng)的字符,分別為#,,^,[,],
|,{,}和~。引入三連符是為了方便的輸入這些字符,早期有些鍵盤不支持它們。雙連符同理。顯然 Walter 認(rèn)為這些東西早就過時(shí)了。)
源代碼文檔由 空白、行尾、注釋、特殊記號(hào)序列、記號(hào)等組成,結(jié)尾處必須是 文件尾 。
應(yīng)使用貪心算法將源代碼文檔分割為記號(hào),也就是詞法分析器每次都試圖生成一個(gè)最長(zhǎng)的符號(hào)。例如:>>
是一個(gè)右移運(yùn)算符,而不是兩個(gè)大于運(yùn)算符。
文件尾: 文件的物理結(jié)尾 \u0000 \u001A
EndOfFile: physical end of the file \u0000 \u001A
在遇到上述之一時(shí)認(rèn)為文件終止。
行尾: \u000D \u000A \u000D \u000A 文件尾
EndOfLine: \u000D \u000A \u000D \u000A EndOfFile
不允許用反斜線來將一行分為多行,行長(zhǎng)度也沒有限制。
空白: 空格 空格 空白 空格: \u0020 \u0009 \u000B \u000C 行尾 注釋
WhiteSpace: Space Space WhiteSpace Space: \u0020 \u0009 \u000B \u000C EndOfLine Comment
空白被定義為一系列的一個(gè)或多個(gè)空格、制表符、垂直制表符、表格填充、行尾或者注釋。
注釋: /* 字符 */ // 字符 行尾 /+ 字符 +/
Comment: /* Characters */ // Characters EndOfLine /+ Characters +/
D 有三種注釋:
- 塊注釋可以跨越多行,但是不能嵌套。
- 單行注釋在行尾結(jié)束。
- 嵌套注釋可以跨越多行并且可以嵌套。
從概念上來說,在記號(hào)化之前處理注釋。這意味著嵌入的字符串和注釋不會(huì)影響對(duì)注釋開始和注釋結(jié)束的識(shí)別:
a = /+ // +/ 1; // 解析為 'a = 1;'
a = /+ "+/" +/ 1"; // 解析為 'a = " +/1";'
a = /+ /* +/ */ 3; // 解析為 'a = */ 3;'
注釋不能被用作記號(hào)連接符,例如 abc/**/def
是兩個(gè)符號(hào),abc 和 def
,而不是記號(hào) abcdef 。
記號(hào): 標(biāo)志符 字符串文字量 字符文字量 整數(shù)文字量 浮點(diǎn)數(shù)文字量 關(guān)鍵字
Token: Identifier StringLiteral CharacterLiteral IntegerLiteral FloatLiteral Keyword
/ /= . .. ... & &= && | |= || - -= -- +
+= ++ < <= << <<= <> <>= > >= >>= >>>= >> >>> !
!= !== !<> !<>= !< !<= !> !>= ( ) [ ] { } ?
, ; : $ = == === * *= % %= ^ ^= ~ ~=
標(biāo)志符: 標(biāo)志符起始 標(biāo)志符起始 多個(gè)標(biāo)志符字符 多個(gè)標(biāo)志符字符: 標(biāo)志符字符 標(biāo)志符字符 多個(gè)標(biāo)志符字符
Identifier: IdentiferStart IdentiferStart IdentifierChars IdentifierChars: IdentiferChar IdentiferChar IdentifierChars
標(biāo)志符起始: _ 字母 通用字母 標(biāo)志符字符: 標(biāo)志符起始 數(shù)字
IdentifierStart: _ Letter UniversalAlpha IdentifierChar: IdentiferStart Digit
標(biāo)志符由一個(gè)字母、下劃線或者一個(gè) unicode 字母開頭,后面跟著任意個(gè)字母、下劃線、數(shù)字或者通用字母。通用字母的定義請(qǐng)參考 ISO/IEC
9899:1999(E) 附錄 D 。(這是 C99 標(biāo)準(zhǔn)) 標(biāo)志符長(zhǎng)度任意,并且區(qū)分大小寫。以兩個(gè)下劃線開頭的標(biāo)志符是保留的。