- 浏览: 221158 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
dysking:
SWT 和 JFace -
wangyuhfut:
东西不少啊。学习中。。。
一个比较好、中文说明的emacs配置文件 1 -
pacocai:
呵呵!学习,学习~~~不过要说编辑器的话个人更喜欢用VIM,比 ...
一个比较好、中文说明的emacs配置文件 1 -
zhf1zhf2:
这两百多个记起来也不容易啊
英国人是这样背的! -
regex:
试了两次,都是乱码,版本是23.1.1,看来不适合
汉化 Emacs 菜单
在 D 中,词法分析独立于语法分析和语义分析。词法分析器是将源文件分割成特征符。词
法描述的是特征符是些什么。D 的词法设计适合高速扫描,它拥有最小的特例集;由于只有
一遍翻译,使得编写一个正确的扫描程序相当容易。对于熟悉 C 和 C++ 的人来说,特征符
也很容易识别。
1.1 编译的阶段
编译被分为多个阶段。每个阶段都不依赖于后继的阶段。例如,扫描程序不依赖于语义分析
程序。这种分离使语法制导编辑器等语言工具相对容易构造。这也使通过将其存储为‘符
号’形式来压缩 D 源码成为可能。
1. 源文件字符集(source character set)
先检查源文件使用的字符集是什么,然后装载相应的扫描器(scanner)。允许的格式是
ASCII 或 UTF。
2. 脚本行(script line)
如果第一行以 #! 开头,那么第一行将被忽略。
3. 词法分析(lexical analysis)
源文件被分割为特征符序列。特殊特征符会被替换成其它的特征符。特殊特征符序列
先会被处理,接着被移除。
4. 语法分析(syntax analysis)
特征符序列会被解析为语法树。
5. 语义分析(semantic analysis)
通过遍历语法树来声明变量、载入符号表、分配类型并在大体上判断程序的意图。
6. 优化(optimization)
这步是可选的——它试着在保持语义等价的同时重写程序,只是生成一个运行速度更
快的版本。
7. 代码生成(code generation)
根据目标架构选取相应的指令来实现程序的语义。通常的结果是生成一个目标文件,
方便用于连接器的输入。
1.2 源文本(Source Text)
D 源文本可以是下面各种形式之一:
• ASCII
• UTF-8
• UTF-16BE
• UTF-16LE
• UTF-32BE
• UTF-32LE
UTF-8 是传统的“7-位 ASCII”的超集(superset)。源文本的开头可以是下列 UTF 字节序标志
(BOM)之一:
格式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
如果源文件不是以 BOM 开头,那么第一个字符必须小于或等于 U0000007F。
在 D 中没有“双连字(digraphs)”或者“三连字(trigraphs)”。
源文本的源表示(source representation)被解码成 Unicode 字符。这些 字符 又被进一步分
成: 空白符、行尾符、注释符、特殊特征符序列、特征符,以及跟在前面那些字符之后的
文尾符。
应用贪心算法(即:词法分析器每次都尽量生成一个最长的特征符)将源代码文本分割成很
多特征符。如:“>>”是一个右移符号,而不是两个大于符号。
1.3 文尾符(End of File)
文尾符:
文件的物理结束符
\u0000
\u001A
在遇到上述符号之一时就认为文件终止。
1.4 行尾符(End of Line)
行尾符:
\u000D
\u000A
\u000D \u000A
文尾符
不允许用反斜线来将一行分为多行,每行的长度也没有限制。
1.5 空白符(White Space)
空白:
空格
空格 空白符
空格:
\u0020
\u0009
\u000B
\u000C
1.6 注释(Comments)
注释:
/* 字符 */
// 字符 行尾符
嵌套注释块
字符:
单个字符
单个字符 多个字符
嵌套注释块:
/+ 嵌套注释块字符 +/
嵌套注释块字符:
嵌套注释块单个字符
嵌套注释块单个字符 嵌套注释块多个字符
嵌套注释块单个字符:
单个字符
嵌套注释块
D 语言有三种注释:
1. 可以跨越多行,但是不能嵌套的块注释。
2. 在行尾结束的单行注释。
3. 可以跨越多行并且可以嵌套的嵌套注释。
字符串和注释的内容不会被分析成特征符。因此,在一个字符串内注释起始符并不会引导一
个注释,并且在注释内的字符串分割符也不会影响对注释结尾符以及嵌套的"/+"注释起始符
的识别。为了避免"/+"出现在"/+"注释中,在注释里的注释起始符将会被忽略。
a = /+ // +/ 1; // 解析为 'a = 1;'
a = /+ "+/" +/ 1"; // 解析为 'a = " +/ 1";'
a = /+ /* +/ */ 3; // 解析为 'a = */ 3;'
注释不能被用作连接符,例如:abc/**/def 是两个特征符:abc 和 def,而不是只有一
个 abcdef。
1.7 特征符(Tokens)
特征符:
标识符
单个字符串文字
字符文字
整数文字
浮点数文字
关键字
/
/=
.
..
...
&
&=
&&
|
|=
||
-
-=
--
+
+=
++
<
<=
<<
<<=
<>
<>=
>
>=
>>=
>>>=
>>
>>>
!
!=
!<>
!<>=
!<
!<=
!>
!>=
(
)
[
]
{
}
?
,
;
:
$
=
==
*
*=
%
%=
^
^=
~
~=
1.8 标识符(Identifiers)
标识符:
标志符起始符
标志符起始符 多个标志符字符
多个标志符字符:
单个标志符字符
单个标志符字符 多个标志符字符
标志符起始符:
_
字母
通用字母
单个标志符字符:
标志符起始符
0
非零数字
标识符的起始符由一个字母、_ 或通用字母组成,紧跟的字符可以是字母、_、数字或通用
字母。通用字母在ISO/IEC 9899:1999(E)的附录 D(即 C99 标准)中有定义。标识符长度任
意,并且区分大小写。以'__ (两个下划线)'开头的标识符被保留了。
1.9 字符串字法(String Literals)
字符串文字:
所见即所得字符串
另一种所见即所得字符串
双引号字符串
转义序列
十六进制字符串
DelimitedString 2.0
TokenString 2.0
所见即所得字符串:
r" 多个所见即所得字符 " 后缀可选的
另一种所见即所得字符串:
` 所见即所得字符 ` 后缀可选的
多个所见即所得字符:
单个所见即所得字符
单个所见即所得字符 多个所见即所得字符
所见即所得字符:
单个字符
行尾符
双引号字符串:
" 多个双引号字符 " 后缀可选的
多个双引号字符:
单个双引号字符
单个双引号字符 多个双引号字符
单个双引号字符:
单个字符
转义序列
行尾符
转义序列:
\'
\"
\?
\\
\a
\b
\f
\n
\r
\t
\v
\ 文尾符
\x 单个十六进制数字 单个十六进制数字
\ 单个八进制数字
\ 单个八进制数字 单个八进制数字
\ 单个八进制数字 单个八进制数字 单个八进制数字
\u 单个十六进制数字 单个十六进制数字 单个十六进制数字 单个十六进制数字
\U 单个十六进制数字 单个十六进制数字 单个十六进制数字 单个十六进制数字 单个十六进制数
字 单个十六进制数字 单个十六进制数字 单个十六进制数字
\& 命名的字符实体 ;
十六进制字符串:
x" 多个十六进制串字符 " 后缀
可选的
多个十六进制串字符:
单个十六进制串字符
单个十六进制串字符 多个十六进制串字符
单个十六进制串字符:
单个十六进制数字
空白
行尾符
后缀:
c
w
d
DelimitedString: 2.0
q" Delimiter WysiwygCharacters MatchingDelimiter " 2.0
TokenString: 2.0
q{ Tokens } 2.0
字符串文字可以是一个双引号字符串、一个引起来的所见即所得字符串、一个转义序列、a delimited string, a token string,(2.0) 或
者一个十六进制字符串。
所见即所得字符串需要使用‘r"’和‘"’封闭引起来。所有位于‘r"’和‘"’之间的字符都是字
符串的一部分,不过对于 行尾,它会被当作一个单一的‘\n’字符。在‘r" "’中没有转义序
列:
r"hello"
r"c:\root\foo.exe"
r"ab\n" // 由四个字符组成的字符串:'a'、'b'、'\'、'n'
所见即所得字符串还有另外一种形式,即使用反引号‘`’。由于‘`’字符并不是所有的键盘
上都有,而且有时在屏幕上难以同另一个常用的字符‘'’区分。因此,还是尽量少用‘`’为
好;不过当用在由‘"’引起来的字符串中时,它就变得很有用了。
`hello`
`c:\root\foo.exe`
`ab\n` // 由四个字符组成的字符串:'a'、'b'、'\'、'n'
双引号字符串指的是用‘""’引起来的字符串。在这种串中,可以嵌入由标准的‘\特征
符’构成的嵌入转义序列。行尾 则被视作一个单一的‘\n’字符。
"hello"
"c:\\root\\foo.exe"
"ab\n" // 由三个字符组成的字符串:'a'、'b'和一个换行符
"ab
" // 由三个字符组成的字符串:'a'、'b'和一个换行符
转义字符串由一个‘\’引导,并构成了一个转义字符序列。相邻的转义字符串会被连接在一
起:
\n 换行符
\t 制表符
\" 双引号
\012 8进制
\x1A 十六进制
\u1234 wchar 字符
\U00101234 dchar 字符
\® ® dchar 字符
\r\n 回车换行
其它未定义的转义序列都是错误的。虽然字符串文字被定义为由 UTF 字符组成,但也允许
使用八进制和十六进制转义序列符插入任意二进制数据。\u 和 \U 转义序列符仅被用来插入
有效的 UTF 字符。
十六进制字符串使用十六进制数据构造字符串。十六进制数据不需要组成有效的 UTF 字
符。
x"0A" // 等同于 "\x0A"
x"00 FBCD 32FD 0A" // 等同于 "\x00\xFB\xCD\x32\xFD\x0A"
空白和换行符都会被忽略,因此格式化十六进制数据就很方便了。十六进制字符的个数必须
是 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"
可选的 后缀 字符产生了特定类型的字符串,而且还需要由上下文来确定。这在字符类型不
能清楚地确定时相当有用,例如,基于字符串类型的重载。后缀字符的种类有:
后缀类型
c char[ ]
w wchar[ ]
d dchar[ ]
"hello"c // char[]
"hello"w // wchar[]
"hello"d // dchar[]
字符串文字是只读的。对字符串文字的写入并不能总是被检测到,而写入的话会引起“未定
义的行为(undefined behavior)”。
10 字符字法(Character Literals)
字符字法:
' 单引号字符 '
单引号字符:
单个字符
转义序列
字符文字是单个的字符或者由单引号' '括起来的转义序列。
11 整数字法(Integer Literals)
整数字法:
整数
整数 整数后缀
整数:
十进制数
二进制数
八进制数
十六进制数
整数后缀:
L
u
U
Lu
LU
uL
UL
十进制数:
0
非零数字
非零数字 多个十进制数字
二进制数:
0b 多个二进制数字
0B 多个二进制数字
八进制数:
0 多个八进制数字
十六进制数:
0x 多个十六进制数字
0X 多个十六进制数字
非零数字:
1
2
3
4
5
6
7
8
9
多个十进制数字:
单个十进制数字
单个十进制数字 多个十进制数字
9
第 1 章 词法 — 张雪平
单个十进制数字:
0
非零数字
_
多个二进制数字:
单个二进制数字
单个二进制数字 多个二进制数字
单个二进制数字:
0
1
_
多个八进制数字:
单个八进制数字
单个八进制数字 多个八进制数字
单个八进制数字:
0
1
2
3
4
5
6
7
_
多个十六进制数字:
单个十六进制数字
单个十六进制数字 多个十六进制数字
单个十六进制数字:
单个十进制数字
a
b
c
d
e
f
A
B
C
D
E
F
_
整数可以采用十进制、二进制、八进制或者十六进制。
十进制整数是十进制数字的序列。
二进制整数是二进制数字的序列,以‘0b’为前缀。
八进制整数是八进制数字的序列,以‘0’为前缀。
十六进制整数指的是一个以‘0x’为前缀的十六进制数字序列。
整数可以内嵌 '_' 字符,它们会被忽略。嵌入的 '_' 可以用于格式化较长的文字,例如作为千位分隔符:
123_456 // 123456
1_2_3_4_5_6_ // 123456
整数后可以紧跟着一个 'l' 或者一个 'u' 或者两者都有。
整数的类型按照下述规则判断:
十进制范围类型
0 .. 2_147_483_647 int
2_147_483_648 .. 9_223_372_036_854_775_807L long
十进制范围,带L后缀类型
0L .. 9_223_372_036_854_775_807L long
十进制范围,带U后缀类型
0U .. 4_294_967_296U uint
4_294_967_296U .. 18_446_744_073_709_551_615UL ulong
十进制范围,带UL后缀类型
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
非十进制范围,带L后缀类型
0x0L .. 0x7FFF_FFFF_FFFF_FFFFL long
0x8000_0000_0000_0000L .. 0xFFFF_FFFF_FFFF_FFFFL ulong
非十进制范围,带U后缀类型
0x0U .. 0xFFFF_FFFFU uint
0x1_0000_0000UL .. 0xFFFF_FFFF_FFFF_FFFFUL ulong
非十进制范围,带UL后缀类型
0x0UL .. 0xFFFF_FFFF_FFFF_FFFFUL ulong
1.12 浮点数字法(Floating Literals)
浮点数字法:
浮点数
浮点数 后缀
整数 虚数后缀
整数 浮点后缀 虚数后缀
整数 实数后缀 虚数后缀
浮点数:
十进制浮点数
十六进制浮点数
十进制浮点数:
多个十进制数字 .
多个十进制数字 .多个十进制数字
多个十进制数字 .多个十进制数字 十进制指数
. 十进制数
. 十进制数 十进制指数
多个十进制数字 十进制指数
十进制指数
e 多个十进制数字
E 多个十进制数字
e+ 多个十进制数字
E+ 多个十进制数字
e- 多个十进制数字
E- 多个十进制数字
十六进制浮点数:
十六进制前缀 多个十六进制数字 .多个十六进制数字 十六进制指数
十六进制前缀 .多个十六进制数字 十六进制指数
十六进制前缀 多个十六进制数字 十六进制指数
十六进制前缀:
0x
0X
十六进制指数:
p 多个十六进制数字
P 多个十六进制数字
p+ 多个十六进制数字
P+ 多个十六进制数字
p- 多个十六进制数字
P- 多个十六进制数字
后缀:
浮点后缀
实数后缀
虚数后缀
浮点后缀 虚数后缀
实数 虚数后缀
浮点后缀:
f
F
实数后缀:
L
虚数后缀:
i
浮点数可以使用十进制或者十六进制格式,如同标准 C 一样。
十六进制浮点数以 0x 开头,阶码以 p 或 P 开头,后面跟着以 2 为底的阶数。
浮点数可以内嵌 '_' 字符,它们会被忽略。嵌入的‘_’用来格式化冗长的文字以提高可读
性,例如可以将它们用作千位分隔符:
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 后缀。f 或 F 后缀说明是fload;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 // 复数
1.13 关键字(Keywords)
关键字是保留的标识符:
关键字:
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
import
in
inout
int
interface
invariant
ireal
is
lazy
long
macro
mixin
module
nothrow 2.014
new
null
out
override
package
pragma
private
protected
public
pure 2.014
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__ 2.014
__LINE__ 2.014
__traits 2.014
1.14 特殊特征符(Special Tokens)
这些特征符会根据下面的表格替换成其它的特征符:
特殊特征符替换为...
__FILE__ 字符串文字,表示的是源文件名 2.014 文档的里没有
__LINE__ 整型文字,表示的是当前源文件的行号 2.014 文档的里没有
__DATE__ 字符串文字,表示的是编译日期:"mmm dd yyyy"
__TIME__ 字符串文字,表示的是编译时间:"hh:mm:ss"
__TIMESTAMP__ 字符串文字,表示的是编译日期和时间:"www mmm dd hh:mm:ss
yyyy"
__VENDOR__ 字符串文字,表示的是编译器服务商,如"Digital Mars D"
__VERSION__ 整数,表示的是编译器版本,如:2001
1.15 特殊特征符序列(Special Token Sequences)
特殊特征符序列由词法分析程序处理,它可以出现在其他特征符之间,并且不影响语法分
析。
目前只有一个特殊特征符序列,#line。
特殊特征符序列:
# line 整数 行尾
# line 整数 指定文件 行尾
指定文件:
" 多个字符 "
它会将源代码的行号设置为某一个 整数,可选地将源文件名设置为 指定的文件,紧跟在源
文件文本的下一行。与码文件名和行号用于打印调试信息,还被符号调试器用于将生成的代
码映射回源代码。
例如:
int #line 6 "foo\bar"
x; // 这里是文件 foo\bar 的第6行
注意,Filespec 字符串中的反斜杠不会被特殊处理。
法描述的是特征符是些什么。D 的词法设计适合高速扫描,它拥有最小的特例集;由于只有
一遍翻译,使得编写一个正确的扫描程序相当容易。对于熟悉 C 和 C++ 的人来说,特征符
也很容易识别。
1.1 编译的阶段
编译被分为多个阶段。每个阶段都不依赖于后继的阶段。例如,扫描程序不依赖于语义分析
程序。这种分离使语法制导编辑器等语言工具相对容易构造。这也使通过将其存储为‘符
号’形式来压缩 D 源码成为可能。
1. 源文件字符集(source character set)
先检查源文件使用的字符集是什么,然后装载相应的扫描器(scanner)。允许的格式是
ASCII 或 UTF。
2. 脚本行(script line)
如果第一行以 #! 开头,那么第一行将被忽略。
3. 词法分析(lexical analysis)
源文件被分割为特征符序列。特殊特征符会被替换成其它的特征符。特殊特征符序列
先会被处理,接着被移除。
4. 语法分析(syntax analysis)
特征符序列会被解析为语法树。
5. 语义分析(semantic analysis)
通过遍历语法树来声明变量、载入符号表、分配类型并在大体上判断程序的意图。
6. 优化(optimization)
这步是可选的——它试着在保持语义等价的同时重写程序,只是生成一个运行速度更
快的版本。
7. 代码生成(code generation)
根据目标架构选取相应的指令来实现程序的语义。通常的结果是生成一个目标文件,
方便用于连接器的输入。
1.2 源文本(Source Text)
D 源文本可以是下面各种形式之一:
• ASCII
• UTF-8
• UTF-16BE
• UTF-16LE
• UTF-32BE
• UTF-32LE
UTF-8 是传统的“7-位 ASCII”的超集(superset)。源文本的开头可以是下列 UTF 字节序标志
(BOM)之一:
格式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
如果源文件不是以 BOM 开头,那么第一个字符必须小于或等于 U0000007F。
在 D 中没有“双连字(digraphs)”或者“三连字(trigraphs)”。
源文本的源表示(source representation)被解码成 Unicode 字符。这些 字符 又被进一步分
成: 空白符、行尾符、注释符、特殊特征符序列、特征符,以及跟在前面那些字符之后的
文尾符。
应用贪心算法(即:词法分析器每次都尽量生成一个最长的特征符)将源代码文本分割成很
多特征符。如:“>>”是一个右移符号,而不是两个大于符号。
1.3 文尾符(End of File)
文尾符:
文件的物理结束符
\u0000
\u001A
在遇到上述符号之一时就认为文件终止。
1.4 行尾符(End of Line)
行尾符:
\u000D
\u000A
\u000D \u000A
文尾符
不允许用反斜线来将一行分为多行,每行的长度也没有限制。
1.5 空白符(White Space)
空白:
空格
空格 空白符
空格:
\u0020
\u0009
\u000B
\u000C
1.6 注释(Comments)
注释:
/* 字符 */
// 字符 行尾符
嵌套注释块
字符:
单个字符
单个字符 多个字符
嵌套注释块:
/+ 嵌套注释块字符 +/
嵌套注释块字符:
嵌套注释块单个字符
嵌套注释块单个字符 嵌套注释块多个字符
嵌套注释块单个字符:
单个字符
嵌套注释块
D 语言有三种注释:
1. 可以跨越多行,但是不能嵌套的块注释。
2. 在行尾结束的单行注释。
3. 可以跨越多行并且可以嵌套的嵌套注释。
字符串和注释的内容不会被分析成特征符。因此,在一个字符串内注释起始符并不会引导一
个注释,并且在注释内的字符串分割符也不会影响对注释结尾符以及嵌套的"/+"注释起始符
的识别。为了避免"/+"出现在"/+"注释中,在注释里的注释起始符将会被忽略。
a = /+ // +/ 1; // 解析为 'a = 1;'
a = /+ "+/" +/ 1"; // 解析为 'a = " +/ 1";'
a = /+ /* +/ */ 3; // 解析为 'a = */ 3;'
注释不能被用作连接符,例如:abc/**/def 是两个特征符:abc 和 def,而不是只有一
个 abcdef。
1.7 特征符(Tokens)
特征符:
标识符
单个字符串文字
字符文字
整数文字
浮点数文字
关键字
/
/=
.
..
...
&
&=
&&
|
|=
||
-
-=
--
+
+=
++
<
<=
<<
<<=
<>
<>=
>
>=
>>=
>>>=
>>
>>>
!
!=
!<>
!<>=
!<
!<=
!>
!>=
(
)
[
]
{
}
?
,
;
:
$
=
==
*
*=
%
%=
^
^=
~
~=
1.8 标识符(Identifiers)
标识符:
标志符起始符
标志符起始符 多个标志符字符
多个标志符字符:
单个标志符字符
单个标志符字符 多个标志符字符
标志符起始符:
_
字母
通用字母
单个标志符字符:
标志符起始符
0
非零数字
标识符的起始符由一个字母、_ 或通用字母组成,紧跟的字符可以是字母、_、数字或通用
字母。通用字母在ISO/IEC 9899:1999(E)的附录 D(即 C99 标准)中有定义。标识符长度任
意,并且区分大小写。以'__ (两个下划线)'开头的标识符被保留了。
1.9 字符串字法(String Literals)
字符串文字:
所见即所得字符串
另一种所见即所得字符串
双引号字符串
转义序列
十六进制字符串
DelimitedString 2.0
TokenString 2.0
所见即所得字符串:
r" 多个所见即所得字符 " 后缀可选的
另一种所见即所得字符串:
` 所见即所得字符 ` 后缀可选的
多个所见即所得字符:
单个所见即所得字符
单个所见即所得字符 多个所见即所得字符
所见即所得字符:
单个字符
行尾符
双引号字符串:
" 多个双引号字符 " 后缀可选的
多个双引号字符:
单个双引号字符
单个双引号字符 多个双引号字符
单个双引号字符:
单个字符
转义序列
行尾符
转义序列:
\'
\"
\?
\\
\a
\b
\f
\n
\r
\t
\v
\ 文尾符
\x 单个十六进制数字 单个十六进制数字
\ 单个八进制数字
\ 单个八进制数字 单个八进制数字
\ 单个八进制数字 单个八进制数字 单个八进制数字
\u 单个十六进制数字 单个十六进制数字 单个十六进制数字 单个十六进制数字
\U 单个十六进制数字 单个十六进制数字 单个十六进制数字 单个十六进制数字 单个十六进制数
字 单个十六进制数字 单个十六进制数字 单个十六进制数字
\& 命名的字符实体 ;
十六进制字符串:
x" 多个十六进制串字符 " 后缀
可选的
多个十六进制串字符:
单个十六进制串字符
单个十六进制串字符 多个十六进制串字符
单个十六进制串字符:
单个十六进制数字
空白
行尾符
后缀:
c
w
d
DelimitedString: 2.0
q" Delimiter WysiwygCharacters MatchingDelimiter " 2.0
TokenString: 2.0
q{ Tokens } 2.0
字符串文字可以是一个双引号字符串、一个引起来的所见即所得字符串、一个转义序列、a delimited string, a token string,(2.0) 或
者一个十六进制字符串。
所见即所得字符串需要使用‘r"’和‘"’封闭引起来。所有位于‘r"’和‘"’之间的字符都是字
符串的一部分,不过对于 行尾,它会被当作一个单一的‘\n’字符。在‘r" "’中没有转义序
列:
r"hello"
r"c:\root\foo.exe"
r"ab\n" // 由四个字符组成的字符串:'a'、'b'、'\'、'n'
所见即所得字符串还有另外一种形式,即使用反引号‘`’。由于‘`’字符并不是所有的键盘
上都有,而且有时在屏幕上难以同另一个常用的字符‘'’区分。因此,还是尽量少用‘`’为
好;不过当用在由‘"’引起来的字符串中时,它就变得很有用了。
`hello`
`c:\root\foo.exe`
`ab\n` // 由四个字符组成的字符串:'a'、'b'、'\'、'n'
双引号字符串指的是用‘""’引起来的字符串。在这种串中,可以嵌入由标准的‘\特征
符’构成的嵌入转义序列。行尾 则被视作一个单一的‘\n’字符。
"hello"
"c:\\root\\foo.exe"
"ab\n" // 由三个字符组成的字符串:'a'、'b'和一个换行符
"ab
" // 由三个字符组成的字符串:'a'、'b'和一个换行符
转义字符串由一个‘\’引导,并构成了一个转义字符序列。相邻的转义字符串会被连接在一
起:
\n 换行符
\t 制表符
\" 双引号
\012 8进制
\x1A 十六进制
\u1234 wchar 字符
\U00101234 dchar 字符
\® ® dchar 字符
\r\n 回车换行
其它未定义的转义序列都是错误的。虽然字符串文字被定义为由 UTF 字符组成,但也允许
使用八进制和十六进制转义序列符插入任意二进制数据。\u 和 \U 转义序列符仅被用来插入
有效的 UTF 字符。
十六进制字符串使用十六进制数据构造字符串。十六进制数据不需要组成有效的 UTF 字
符。
x"0A" // 等同于 "\x0A"
x"00 FBCD 32FD 0A" // 等同于 "\x00\xFB\xCD\x32\xFD\x0A"
空白和换行符都会被忽略,因此格式化十六进制数据就很方便了。十六进制字符的个数必须
是 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"
可选的 后缀 字符产生了特定类型的字符串,而且还需要由上下文来确定。这在字符类型不
能清楚地确定时相当有用,例如,基于字符串类型的重载。后缀字符的种类有:
后缀类型
c char[ ]
w wchar[ ]
d dchar[ ]
"hello"c // char[]
"hello"w // wchar[]
"hello"d // dchar[]
字符串文字是只读的。对字符串文字的写入并不能总是被检测到,而写入的话会引起“未定
义的行为(undefined behavior)”。
2.014 内容 Delimited Strings Delimited strings use various forms of delimiters. A nesting delimiter nests, and is one of the following characters: Nesting Delimiters Delimiter Matching Delimiter [ ] ( ) < > { } q"(foo(xxx))" // "foo(xxx)" q"[foo{]" // "foo{" If the delimiter is an identifier, the identifier must be immediately followed by a newline, and the matching delimiter is the same identifier starting at the beginning of the line: writefln(q"EOS This is a multi-line heredoc string EOS" ); The newline following the opening identifier is not part of the string, but the last newline before the closing identifier is part of the string. Otherwise, the matching delimiter is the same as the delimiter character: q"/foo]/" // "foo]" q"/abc/def/" // error Token Strings Token strings open with the characters q{ and close with the token }. In between must be valid D tokens. The { and } tokens nest. The string is formed of all the characters between the opening and closing of the token string, including comments. q{foo} // "foo" q{/*}*/ } // "/*}*/ " q{ foo(q{hello}); } // " foo(q{hello}); " q{ @ } // error, @ is not a valid D token q{ __TIME__ } // " __TIME__ ", i.e. it is not replaced with the time q{ __EOF__ } // error, as __EOF__ is not a token, it's end of file
10 字符字法(Character Literals)
字符字法:
' 单引号字符 '
单引号字符:
单个字符
转义序列
字符文字是单个的字符或者由单引号' '括起来的转义序列。
11 整数字法(Integer Literals)
整数字法:
整数
整数 整数后缀
整数:
十进制数
二进制数
八进制数
十六进制数
整数后缀:
L
u
U
Lu
LU
uL
UL
十进制数:
0
非零数字
非零数字 多个十进制数字
二进制数:
0b 多个二进制数字
0B 多个二进制数字
八进制数:
0 多个八进制数字
十六进制数:
0x 多个十六进制数字
0X 多个十六进制数字
非零数字:
1
2
3
4
5
6
7
8
9
多个十进制数字:
单个十进制数字
单个十进制数字 多个十进制数字
9
第 1 章 词法 — 张雪平
单个十进制数字:
0
非零数字
_
多个二进制数字:
单个二进制数字
单个二进制数字 多个二进制数字
单个二进制数字:
0
1
_
多个八进制数字:
单个八进制数字
单个八进制数字 多个八进制数字
单个八进制数字:
0
1
2
3
4
5
6
7
_
多个十六进制数字:
单个十六进制数字
单个十六进制数字 多个十六进制数字
单个十六进制数字:
单个十进制数字
a
b
c
d
e
f
A
B
C
D
E
F
_
整数可以采用十进制、二进制、八进制或者十六进制。
十进制整数是十进制数字的序列。
二进制整数是二进制数字的序列,以‘0b’为前缀。
八进制整数是八进制数字的序列,以‘0’为前缀。
十六进制整数指的是一个以‘0x’为前缀的十六进制数字序列。
整数可以内嵌 '_' 字符,它们会被忽略。嵌入的 '_' 可以用于格式化较长的文字,例如作为千位分隔符:
123_456 // 123456
1_2_3_4_5_6_ // 123456
整数后可以紧跟着一个 'l' 或者一个 'u' 或者两者都有。
整数的类型按照下述规则判断:
十进制范围类型
0 .. 2_147_483_647 int
2_147_483_648 .. 9_223_372_036_854_775_807L long
十进制范围,带L后缀类型
0L .. 9_223_372_036_854_775_807L long
十进制范围,带U后缀类型
0U .. 4_294_967_296U uint
4_294_967_296U .. 18_446_744_073_709_551_615UL ulong
十进制范围,带UL后缀类型
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
非十进制范围,带L后缀类型
0x0L .. 0x7FFF_FFFF_FFFF_FFFFL long
0x8000_0000_0000_0000L .. 0xFFFF_FFFF_FFFF_FFFFL ulong
非十进制范围,带U后缀类型
0x0U .. 0xFFFF_FFFFU uint
0x1_0000_0000UL .. 0xFFFF_FFFF_FFFF_FFFFUL ulong
非十进制范围,带UL后缀类型
0x0UL .. 0xFFFF_FFFF_FFFF_FFFFUL ulong
1.12 浮点数字法(Floating Literals)
浮点数字法:
浮点数
浮点数 后缀
整数 虚数后缀
整数 浮点后缀 虚数后缀
整数 实数后缀 虚数后缀
浮点数:
十进制浮点数
十六进制浮点数
十进制浮点数:
多个十进制数字 .
多个十进制数字 .多个十进制数字
多个十进制数字 .多个十进制数字 十进制指数
. 十进制数
. 十进制数 十进制指数
多个十进制数字 十进制指数
十进制指数
e 多个十进制数字
E 多个十进制数字
e+ 多个十进制数字
E+ 多个十进制数字
e- 多个十进制数字
E- 多个十进制数字
十六进制浮点数:
十六进制前缀 多个十六进制数字 .多个十六进制数字 十六进制指数
十六进制前缀 .多个十六进制数字 十六进制指数
十六进制前缀 多个十六进制数字 十六进制指数
十六进制前缀:
0x
0X
十六进制指数:
p 多个十六进制数字
P 多个十六进制数字
p+ 多个十六进制数字
P+ 多个十六进制数字
p- 多个十六进制数字
P- 多个十六进制数字
后缀:
浮点后缀
实数后缀
虚数后缀
浮点后缀 虚数后缀
实数 虚数后缀
浮点后缀:
f
F
实数后缀:
L
虚数后缀:
i
浮点数可以使用十进制或者十六进制格式,如同标准 C 一样。
十六进制浮点数以 0x 开头,阶码以 p 或 P 开头,后面跟着以 2 为底的阶数。
浮点数可以内嵌 '_' 字符,它们会被忽略。嵌入的‘_’用来格式化冗长的文字以提高可读
性,例如可以将它们用作千位分隔符:
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 后缀。f 或 F 后缀说明是fload;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 // 复数
1.13 关键字(Keywords)
关键字是保留的标识符:
关键字:
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
import
in
inout
int
interface
invariant
ireal
is
lazy
long
macro
mixin
module
nothrow 2.014
new
null
out
override
package
pragma
private
protected
public
pure 2.014
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__ 2.014
__LINE__ 2.014
__traits 2.014
1.14 特殊特征符(Special Tokens)
这些特征符会根据下面的表格替换成其它的特征符:
特殊特征符替换为...
__FILE__ 字符串文字,表示的是源文件名 2.014 文档的里没有
__LINE__ 整型文字,表示的是当前源文件的行号 2.014 文档的里没有
__DATE__ 字符串文字,表示的是编译日期:"mmm dd yyyy"
__TIME__ 字符串文字,表示的是编译时间:"hh:mm:ss"
__TIMESTAMP__ 字符串文字,表示的是编译日期和时间:"www mmm dd hh:mm:ss
yyyy"
__VENDOR__ 字符串文字,表示的是编译器服务商,如"Digital Mars D"
__VERSION__ 整数,表示的是编译器版本,如:2001
1.15 特殊特征符序列(Special Token Sequences)
特殊特征符序列由词法分析程序处理,它可以出现在其他特征符之间,并且不影响语法分
析。
目前只有一个特殊特征符序列,#line。
特殊特征符序列:
# line 整数 行尾
# line 整数 指定文件 行尾
指定文件:
" 多个字符 "
它会将源代码的行号设置为某一个 整数,可选地将源文件名设置为 指定的文件,紧跟在源
文件文本的下一行。与码文件名和行号用于打印调试信息,还被符号调试器用于将生成的代
码映射回源代码。
例如:
int #line 6 "foo\bar"
x; // 这里是文件 foo\bar 的第6行
注意,Filespec 字符串中的反斜杠不会被特殊处理。
发表评论
-
土耳其文《d编程》range 翻译 一
2011-11-15 02:01 1508Ranges 范围 Ranges are an abstra ... -
土耳其文《d编程》range 翻译 二
2011-11-15 01:59 1008As you can see, that output doe ... -
d2 range 和 标准C++中的Iterator(迭代器)简介
2011-05-07 12:59 2118原文: http://hi.baidu.com/c ... -
三访安德烈Alexandrescu(第2部)
2010-08-20 12:53 1424Google翻译哦 面试------> 应翻成 访谈 ... -
三访安德烈Alexandrescu(第一部分)
2010-08-20 12:43 1350google翻译哦 Interview with Andre ... -
Garden Editor project 日记 之二 10.16 ---
2009-10-16 02:39 02009.10.16 T[new] misgivings ... -
Garden Editor project 日记 之一 09.09.25 --- 10.15
2009-09-24 22:56 0kill two birds with one stone, ... -
template metaprogramming 9
2009-09-09 16:08 1171原文:https://docs.google.co ... -
Floating Point in D (2.030 新)
2009-05-12 23:27 20495.17 23:50 更新 5.16 20:30 翻译更 ... -
Migrating to Shared (2.030 新)
2009-05-12 23:03 11565.19 0:10 更新(完成) ... -
D 2.0 的gc
2008-12-04 19:53 1252http://lucifer1982.wordpress.co ... -
垃圾回收 2.014
2008-06-10 07:20 984无版本差异 D 是一种全面采用垃圾回收(Garbage Co ... -
类 class 2.014
2008-06-09 22:51 1086D 的面向对象的特性都来源于类。类层次里的顶层是 Object ... -
接 口 2.014
2008-06-09 22:51 845接口声明: interface 标 ... -
C 语言接口 2.014
2008-06-09 22:50 1030D 的设计就是要在目标系统上能够很好地符合于 C 编译器。D ... -
Traits 特征 2.014
2008-06-07 11:25 12476.14 翻译 (d语言的反 ... -
常量和不变量 Const and Invariant 2.014
2008-06-07 11:22 1313请参考: D 2.0 Const/Final/Invarian ... -
枚 举 2.014
2008-06-07 08:41 1156枚举声明: enum 枚举标记 枚举体 enum 枚举体 en ... -
函 数 2 (2.014)
2008-06-07 08:22 10337 嵌套函数 函数可以被 ... -
函 数 2.014
2008-06-07 08:21 1298[size=large]函数体: 块 ...
相关推荐
实现C语言小子集程序的词法分析.doc
词法分析.cpp
编译原理\词法分析\词法分析\词法分析.cpp
ch07 词法分析.pptx
编译原理词法分析.ppt 本章内容 词法分析器:把构成源程序的字符流翻译成记号流,还完成和用户接口的一些任务 围绕词法分析器的自动生成展开 介绍正规式、状态转换图和有限自动机概念
编译最终第4章词法分析.pdf
2. **扫描源代码**:词法分析器逐字符读取源代码,根据定义的规则识别出词法单元。这个过程可能涉及到字符串连接、数字解析、转义序列处理等。 3. **生成词法单元**:识别出的词法单元会附带相关信息,如类型(如...
编译原理与技术讲义 第2章 词法分析.ppt
编译原理:第3章-词法分析.ppt
第3章编译原理+词法分析.
北邮计算机科学与技术编译原理词法分析.pdf
#### 2. 词法分析器 词法分析器是一种特殊的软件组件或函数,负责执行词法分析的工作。它通常被称为词法分析器(Lexical Analyzer)或扫描器(Scanner)。词法分析器的主要功能包括: - **扫描**:逐个读取源程序中...
2. TESTscan.c 程序的分析 在这个实验中,我们提供了一个词法分析程序 TESTscan.c。这个程序的主要功能是将源代码转换为中间代码。 * 程序的主要结构: TESTscan.c 程序的主要结构如下所示: ```c #include ...
电子科技大学-计算机学院-编译原理实验-词法分析.doc
2. 正则表达式定义:在Lex中,可以使用正则表达式来定义单词的模式。例如,letter可以定义为a|…|z|A|…|Z,digit可以定义为0|…|9。这些定义可以用于识别保留字和符号。 3. 转换规则定义:在Lex中,规则定义用于...
2. **状态机模型**:词法分析通常采用有限状态自动机(FSM)模型。状态机有若干个状态,每个状态根据输入字符决定如何转换到下一个状态。在C++中,可以使用枚举类型来表示状态,并用条件语句或者switch-case结构实现...