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