编译原理 Part3词法分析1
编译原理与实现03第3章 词法分析
利用状态图识别句子的方法是一种自底向上的分析方法。开始时,处于开 始状态,此时句柄是随后扫描的字符,即输入串的的第一个符号,所要归 约的符号就是从开始状态经过标记有句柄符号的弧到达的下一个状态的名 字。以后每一步(除第一步外)的句柄是当前状态的名字和随后扫描的字 符,而句柄所要归约的符号就是下一个状态的名字。
3.3.2 状态图的用法
例3.2,对句子0110进行的分析。 解:根据上面介绍的状态图使用方法,我们在图3.5(a)列出分析的每一步。 由于这些规则很简单,所以分析也非常简单。首先,在开始状态S下扫描的第 一个符号是0,转到状态V,表示0是句柄,归约到V。接下来,在状态V扫描1, 转到状态Z,此时句柄为V1,归约成Z。再往下扫描1,由状态Z转到状态U,表 示句柄为Z1归约为U。最后,扫描0,转到状态Z,此时句柄为U0,归约为Z, 从而形成图3.5(b)所示的语法树。 步骤 1 2 状态 S V 扫描的字符 0 1 余留部分 110 10
3.3.2 状态图的用法
状态图画好后,就可以利用状态图来分析和识别字符串,其方法如下: 1.首先设置初始状态S为当前状态。从输入串的最左字符开始重复步骤2,直 到到达输入串的右端为止。 2.扫描输入串的下一个字符,在当前状态所射出的弧中,找出标记有该字符 的弧,并沿此弧前进,过渡到下一个状态。如果找不到标记有该字符的弧, 则说明输入串不是合法的句子,分析过程失败结束;如果我们扫描输入串 的最后一个字符,并从当前状态出发沿着标记有该字符的弧到达终结状态, 则表示输入串是该文法的合法句子,识别过程成功结束;如果扫描输入串 的最后一个符号后到达的状态不是状态图的终结状态,则表示输入串不是 该文法的合法句子,识别过程失败结束。
3.3 正则文法及状态图
程序设计语言的单词符号可用3型文法来描述,3型文法也称为正 则文法。对于正则文法所描述的语言可以用一种有穷自动机来识 别。我们的目的是实现词法分析程序,所以为了简化问题,我们 直接介绍这种自动机的非形式表示,即状态图。
编译原理课件-词法分析
號等記號的文法
—— 正規文法
語法:借助於記號來描述語言的結構的文法
—— 上下文無關文法
21/76
二、記號的文法
識別字 常數
–整數 –無符號數
運算符 分界符 關鍵字
22/76
Wensheng Li BUPT @ 2008
識別字
識別字定義為“由字母打頭的、由字母或數字組成
的符號串”
正規運算式?
描述識別字集合的正規運算式:
9/76
Wensheng Li BUPT @ 2008
3.2 詞法分析程式的輸入與輸出
一、詞法分析程序的實現方法 二、設置緩衝區的必要性 三、配對緩衝區 四、詞法分析程序的輸出
10/76
Wensheng Li BUPT @ 2008
一、詞法分析程式的實現方法
利用詞法分析程序自動生成器
–從基於正規運算式的規範說明自動生成詞法分析程序。 –生成器提供用於根源程式字元流讀入和緩沖的若干副程
記號的屬性
詞法分析程式在識別出一個記號後,要把與之有關 的資訊作為它的屬性保留下來。 記號影響語法分析的決策,屬性影響記號的翻譯。 在詞法分析階段,對記號只能確定一種屬性
–識別字:單詞在符號表中入口的指針 –常數:它所表示的值 –關鍵字:(一符一種、或一類一種) –運算符:(一符一種、或一類一種) –分界符:(一符一種、或一類一種)
4/76
Wensheng Li BUPT @ 2008
3.1 詞法分析程式與語法分析程式的關係
詞法分析程式與語法分析程式之間的三種關係
–詞法分析程式作為獨立的一遍 –詞法分析程序作為語法分析程序的副程式 –詞法分析程序與語法分析程序作為協同程式
分離詞法分析程序的好處
编译原理第三版 第三章 词法分析
超前搜索
例:FORTRAN语言中关键字的识别: DO99K=1,10 识别DO为关键字要搜 DO99K=1.10 索到“,” FORTRAN语言中常数的识别:
5.EQ.M, 5.E08
识别5为常数要搜索到Q
2、状态转换图
大多数程序设计语言中单词符号的词法规则可 以用正规文法描述。如: <标识符>→ 字母|<标识符>字母|<标识符>数字 <整数>→数字|<整数>数字 <运算符>→+|-|×|÷„ <界符>→; |, |( | )|„
#
3.3 正规表达式与有限自动机
目的: 形式化地描述词法规则和词法分析程序 词法分析程序的自动生成 主要内容 正规式与正规集 确定有限自动机 (DFA) 非确定有限自动机(NFA) 正规式与有限自动机的等价性 确定有限自动机的化简
正规文法
多数程序设计语言单词的语法都能用正规文法 (3型文法)描述 正规文法回顾 文法的任一产生式α→β的形式都为
单词符号的种类
(3) 常数 常数的类型一般有整型、实型、布 尔型、字符型等。
(4) 运算符 如 +,-,*,/等,对具体语言个 数是确定的。 (5) 界符 如 , ;()等,对具体语言个数是 确定的。
单词符号的表示形式
词法分析器所输出的单词符号常常表示成如下的 二元式:<单词种别,单词符号的属性值> 单词种别:由语法分析阶段使用的抽象符号。如: 用整数编码。 最简单的编码方案为一类一码,种别编码可设为: 1,2,3,4,5。 另一种编码方案(如本教材中): 标识符:列为一种,用一个整数编码表示; 常数:按类型分种编码; 关键字、运算符、界符:采用一字一种编码。
《编译原理》第三章 词法分析器
有限自动机模型
Finite Automata (FA):
一个有限自动机的模型如下所示:
... ... head finite control input tape
输入带被分成一个个的小单元来装输入符号, 其右边是无限延伸的。 有限状态控制器由有限个状态组成,并根据读 入字符将当前状态转换成下一个状态
有限自动机与正规式的等价性证明
• 证明一: 对于∑上的NFA M,我们来构造∑上的正规式r, 使得L(r)=L(M)。 首先,我们将状态图的概念拓广,令每条弧可 用正规式作标记。并在M的转换图上加进两个 结点,一个为X,一个为Y。从X用ε弧连接到Y, 从而形成一个新的NFA,记为M’,它只有一个初 态X和一个终态Y。显然L(M)=L(M’)。即,这 两个NFA是等价的。 现在来逐步消去M’中的所有结点,直至只剩下 X和Y为止。
有限自动机接受的语言
The language accepted by FA
一个FA 能够接受的语言定义如下:
• 对于一个 DFA M, 可接受的语言表示为: L(M)={ x | x∈Σ* and f(s0 , x)∈Z} • 对于一个 NFA M, 其接受的语言为: L(M)={x | x∈Σ*and f(s0, x)∩Z≠Φ} • 两个 FA M and M’ 是等价的当且仅当 L(M) = L(M’)
M
M
a
M
假设对于任意 正规式 r1 and r2, 如果 |r1| < k 而 且 |r2| < k, 那么就于一个NFA M1 and M2 对应 于r1 和 r2. 所以对于任意 RE r, |r| = k, 我们有:
• 这个自动机所接受的语言是所有被3整除 以后余数为2的二0, q1, q2, q3}, {0, 1}, f1, q0 {q3} ) . 其中f1如下所示 :
《编译原理》第3章 词法分析
仅由有限次使用上述三步骤而定义的表达式才 是上的正规式,仅由这些正规式表示的字集 才是上的正规集。
所有词法结构一般都可以用正规式描述。
若两个正规式所表示的正规集相同,则称 这两个正规式等价。如
Concat(); GetChar(); end Retract();//搜索指针回调 code := Reserve(); //判断是否为保留字 if (code = 0) //标识符 begin
value := InsertId(strToken); return ($ID, value); end else return (code, -); //保留字
a
➢ 状态之间用箭弧连结,箭弧 1
2
上的标记(字符)代表射出结 状态下可能出现的输入字符
数字 3
或字符类。
➢ 一张转换图只包含有限个状态,其中
有一个为初态,至少要有一个终态。
一个状态转换图可用于识别(或接受)一定 的字符串。
数字
数字
其他
*
1
2
3
识别整常数的状态转换图
字母或数字
字母
其他
*
1
2
3
识别标识符的状态转换图
b(ab)*=(ba)*b
(a*b*)*=(a|b)*
L(b(ab)*) = L(b)L((ab)*) = L(b) (L(ab))* = L(b) (L(a)L(b))* ={b} {ab}* = {b} {, ab, abab, ababab, …} = {b, bab, babab, bababab, …}
词法分析器设计流程
编译原理课件(三)词法分析
为了讨论词法分析器的自动生成,还需要将转换
图的概念形式化。
为此我们引入:正规式,正规集,自动机等概
念。
3.3.1 正规式与正规集
1. ε 和都是 Σ 上的正规式,他们所表示的正规集分别为{ε } 和 ; 2. 任何a Σ , a是Σ 上的一个正规式,它所表示的正规集为{a};
若M的初态结点同时又是终态结点,则为空字可以为M
所识别。DFA M所能识别的字的全体记为L(M).
DFA及其所识别的语言描述
[M=({0,1,2,3},{a,b},,0,{3}) 其中: (0,a)=1; (0,b)=2 (1,a)=3; (1,b)=2 (2,a)=1; (2,b)=3 (3,a)=3; (3,b)=3 问:L(M)=?
输入字符 状态 s1 s2 s1 s2 s2 s1 a b
DFA的(确定的)状态转换图表示
• 假定DFA M 含有m个状态n个输入字符,
– 那么,这张图含有m个状态结点,
– 每个结点顶多有n条箭弧射出和别的结点相连接,
– 每条箭弧用上的一个不同字符作标记, – 整张图含有唯一的初态和若干个(可以是0个)终 态结点。
留字i表进行。
1 DO99K=1,10 2 IF(5.EQ.M)I=10 3 DO99K=1.10 4 IF(5)=55
标识符的识别
• 标识符的定义:字母开头,字母和数字的 组合 • 标识符后通常有界符
常数的识别
• 算术常数有时需要超前搜索
– 5.EQ. M
• 逻辑常数:.T. , .F., 有界符,容易识 别
3.1.2 词法分析器的构造方式-词法分析器 作为独立子程序
词法分析器安排成语法分析的子程序。 好处在于:编译器结构清晰。
编译原理 第3章
一般而言 ,当一个语言的两种单词有相同的前缀时,其扫描 器都应当考虑采用超前搜索和多字符回退操作。
编译原理
8
3.1.4 源程序的输入及预处理 •为了提高读盘的效率和便于扫描器工作,通常采用缓冲 输入的方案,即在内存设置一个适当大小的输入缓冲区, 让操作系统直接将磁盘上的源程序字符串分批送入次缓 冲区,供扫描器处理。
∴M能识别出L(G)中的全部句子。
编译原理 21
二、对于左线性文法构造状态转换图 设G=(Vn,Vt,P,S)是一左线性文法,Vn中的每个非终结符号 对应状态图中的一个结点。与右线性文法不同的是,增 设一个不属于V的符号R标记初态结点,并用S作为终态 结点 。|Vn|=k,共有k+1个节点(状态)。 1. 对于G中的每一条形如A→a的规则,从初态结点R引一 条矢线到结点A,并用符号a标记这条矢线。 2. 对于G中每一条形如A→Ba的规则,从结点B引一条矢线 到结点A,并用符号a标记这条矢线。
编译原理
16
E d
d 0
d
d
d 5 d 6
1
.
d
2
E
4
±
. 图3.4文法G<无符号数>的状态图
编译原理
17
状态图识别符号串
利用状态转换图可识别相应文法所表示的符号串。 定义:设α∈VT * ,如果状态转换图中存在一条从初态到 终态的路径,此路径上的标记符号顺序相连构成符号串α, 则称α为状态图所识别串。
状态图识别语言:状态图所识别的串集合。
a 开始 0 a 1 b 2
编译原理 18
b
2)状态转换图对符号串的识别 对符号串W=a1a2a3……an,ai∈ VT 识别过程:
从初态S出发,自左至右逐个扫描W中的字符,在S 状态下扫视的符号为a1; 在节点S所射出诸矢线中寻找标记为a1的矢线(若 不存在,则说明W有错);
编译原理流程
编译原理流程编译原理是计算机科学的重要分支,主要研究如何将高级语言程序转化为机器语言的过程。
编译原理的流程可以分为词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成等几个阶段。
1. 词法分析词法分析是编译原理的第一步,主要任务是将源代码分解成一个个的词法单元,如标识符、关键字、运算符和常量等。
词法分析器会根据预先定义的词法规则,逐个扫描源代码,将识别出的词法单元转化为记号(token)并生成记号流。
2. 语法分析语法分析是编译原理的第二步,主要任务是根据词法分析生成的记号流,判断程序是否符合语法规则。
语法分析器会根据预先定义的语法规则,逐个分析记号流,构建语法树(parse tree)。
如果程序存在语法错误,则会报告错误信息。
3. 语义分析语义分析是编译原理的第三步,主要任务是对语法树进行语义检查,并生成中间代码。
语义分析器会根据预先定义的语义规则,对语法树进行遍历,检查变量的声明和使用是否符合规范,以及类型的一致性等。
同时,语义分析器会根据语义规则生成中间代码,用于后续的优化和目标代码生成。
4. 中间代码生成中间代码生成是编译原理的第四步,主要任务是将源代码转化为一种中间表示形式,以便进行优化和目标代码生成。
中间代码可以是抽象语法树(Abstract Syntax Tree,AST)、三地址码(Three Address Code)或虚拟机代码等。
中间代码的生成可以通过遍历语法树并根据语法规则进行转换。
5. 代码优化代码优化是编译原理的第五步,主要任务是对中间代码进行优化,以提高程序的执行效率。
代码优化包括常量折叠、公共子表达式消除、循环优化等技术。
优化器会根据预先定义的优化规则,对中间代码进行分析和转换,以减少不必要的计算和内存访问。
6. 目标代码生成目标代码生成是编译原理的最后一步,主要任务是将中间代码转化为目标机器代码,使得程序可以在目标机器上运行。
目标代码生成器会根据目标机器的特定指令集和寄存器分配策略,将中间代码转化为对应的目标机器代码,并生成可执行文件或目标文件。
编译原理第三章词法分析
z19
step1 : 对语言的各类单词分别构造状态图;
step1
L
1
2
other
*
3 其中: other表示非L| D | _字符
z8
3.2.1 单词与属性字
注意:
(1) 同一个字符开头+后续字符->跨多个单词类;
(2) 非单词成分和预处理成分;
•例:源程序注释;/* …….*/
预处理指令:
•# define… # include…
z9
3.2.1 单词与属性字
2. 属性字 对所识别的单词的数据结构表示。
控制线
数据线
X : 固定长度的存储空间 ; z16
预处理程序(作用)
(1) 减少内存空间占用;
(2) 减轻扫描器实质性处理的负担;
预处理程序主要任务:
(1) 滤掉源程序中的非单词成分(如无用空格;换行
符等);
•滤掉注释;
(2) 实际的预处理工作
•宏替换; •文件包含的嵌入;
L1= ( T,C)
属性字 Token
Code
刻画单词类别(单词性质)
如:标识符;运算符;…
单词的内码值(可空)
z10
说明
单词类别通常用整数编码 单词类别提供给语法分析程序使用 单词符号属性信息记录单词符号的特征或特性 单词的属性值提供给语义分析程序使用
编码形式:
一类一种:关键字、标识符、常数、运算符、界符 一字一种:关键字、运算符、分界符各一码
编译原理_课件_第三章_语法分析1
11
例3.1 试构造产生标识符的文法。
I→L|LS S →T|ST T →L|D L →a|b|c|d…|z|A|B…|Z|_ D →0|1|…|9
12
例3.2 写一文法,使其语言是奇数集合,但不 允许出现以 0开头的奇数。
N →A|MA M →B|MD A →1|3|5|7|9 B →1|2|3|4|5|6|7|8|9 D →0|B
4
二、形式语言
? Chomsky于1956年提出了一种用来描述语言的数学系统。 人们把用一组数学符号 和规则来描述语言的方式称为 形式 描述,而把所用的数学符号和规则称为形式语言。
? 形式语言,只是从语法上研究语言。它是抽象的数学系统, 用于模拟程序设计语言的语法,或者是并不很成功地模拟 自然语言如英语的语法。
特定的含义。 语用—在各个记号所出现的行为中,它们的来
源、使用和影响。
3
什么是符号与字母表?
? 字母表:由若干元素(符 号、字母)所组成的有限 非空集合。常用大写英文 字母A,B… 或希腊字母Σ 表示。
? 符号:可以相互区别的记 号(元素)。
? 例如:
Σ = {0,1} V = {a, b,c…z} A={begin,if,real,end}
7
引例2
有如下规则: <标识符>→<字母> <标识符> → <标识符> <字母> <标识符> → <标识符> <数字> <字母> → A <字母> → B <字母> → C <数字> → 0 <数字> → 1
【编译原理】第三章词法分析
【编译原理】第三章词法分析⼀,词法分析器的作⽤词法分析是编译的第⼀阶段。
词法分析器主要任务是读⼊源程序的输⼊字符、将他们组成词素,⽣成并输出⼀个词法单元序列,每个词法单元对应于⼀个词素。
分析部分:词法分析、语法分析(简化编译器设计、提⾼编译器效率、增强编译器可移植性)1)词法单元:词法单元名和可选的属性值组成。
关键字、操作符……2)模式:词法单元词素可能具有的形式,当词法单元是关键字时,模式就是这个关键字的字符序列3)词素:源程序中的⼀个字符序列,它和某个词法单元模式匹配。
4)词法错误:识别出某个错误词素,继续判断下⼀个词素⼆,输⼊缓冲1)我们⾄少向前看⼀个字符,才能判断当前词素是否到头。
2)对付⼤型源程序,需要处理⼤量字符。
处理往往需要很多时间,我们采⽤两个交替读⼊的缓冲区。
(详见73)三,词法单元的规约1)我们会不会⽤完缓冲区?通常对于⽐较长的字符串我们采⽤ ”+“的形式链接起来。
2)正则表达式:letter_(letter_ | digit) * 表⽰字母开头 0个或多个字母或数字3)正则表达式例⼦a |b {a, b}(a | b) (a | b ) {aa, ab, ba, bb}aa | ab | ba | bb {aa, ab, ba, bb}a* 由字母a构成的所有串集(a | b)* 由a和b构成的所有串集复杂的例⼦( 00 | 11 | ( (01 | 10) (00 | 11) * (01 | 10) ) ) * 010011010000100000101110013)正则表达式扩展1>⼀个或多个实例⼀元后缀算符“+”的意思是“⼀个或多个实例”,即正规式a+表⽰⼀个或多个a的所有串的集合。
算符+和算符*有同样的优先级和结合性。
代数恒等式 r* = r+ | 和r+ = rr*表达了这两个算符之间的关系。
2>零个或⼀个实例⼀元后缀算符?的意思是“零个或⼀个实例”,r?是r | 的缩写。
[工学]《编译原理》第3章词法分析
种别码 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
单词 * */ + , — 、 ·· / /* : := ; < <= <> = > >= [ ]
种别码 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
Y
缓冲区空? N 读取单词的第1个 字符 get_nextchar() 根据第1个字 符进行分类 sort()
结束
数字 识别数值常数 recog_dig()
‘ 识别 recog_id() 是关键字? iskeyword(s) N 在符号表中? isexist_sym(s) N 插入符号表 ins_sym(s,token)
源程序 读文件 一行并 打印1.1 源程序 清单 缓冲区 buffer 读一非 空字符 1.2 字符 首字符 分类1.3
其它
字 母
识别标 识符/关 键字1.5
标 识
数
字
识别数 值常数 1.6 处理注释 和除法符 号1.7 识别文 字常数 1.8 识别界 符和运 算符1.9
数字
/关 符
常数
键 字
/
除号/
词法分析器的输出
• 1. Token串: 输出源文件中各个有用的单词
– 格式: (单词的种别码,单词符号的属性值) – 单词种别:是对能识别的单词的分类编码(P42) – 单词符号的属性值:单词的某种特性或特征 • 常数的值,标识符的名字等 • 保留字、运算符、分界符的属性值可以省略 – 文件存放最好有格式,如每个单词占一行方便 “语法分析”程序调用 – P38 例
编译原理词法分析(1)课件
分析阶段
词法分析器
语法分析器
符 号
语义分析器
错
表
误
管
处
理
中间代码生成
理
器
器
代码优化
代码生成
综合阶段
目标程序
0、回顾:词法分析
• 词法分析是编译过程中将字符流转换成为符号流 的一个工作阶段,是编译的第一步工作,其后续 工作是语法分析。
▫ 词法分析的输入是源代码; ▫ 词法分析的输出是符号流; ▫ 词法分析需要识别词法错误,即非法的符号、单词
示例:词法分析的输入和输出
• ffoorr ( i(=1i;=i1<;=1i0<0=1; 0i+0;+)i++) • sumsu=msu=msu+mi;+ i;
• <保留字,for> <分隔符,(> <标识符,i> <算符 ,= > <常量,1> <分隔符,;> <标识符,i> <算符 ,<= > <常量,100> <分隔符,;> <标识符,i> < 算符,++ > <分隔符,)> <标识符,sum> <算 符,= > <标识符,sum> <算符,+ > <标识符,i> < 分隔符,;>
αn 定义为 αα…αα n个α连接 α1 =α, α2 =αα,注:α0 =ε
2.1 串和语言
连接(乘积) 两个符号串集合 A 和 B 的乘积定义为: AB ={ xy | x A 且 y B } 例如:集合A={ab,cde} B={0,1} 则 AB={ ab1,ab0,cde0,cde1 }
编译课件 03 第三章 词法分析
2020/7/7
2
词法分析器的接口
CharList 附 属 词法分析器
call Token
语法分析
2020/7/7
5
设计与实现--有限自动机描述
1. 按类构造出相应的状态转换图。
2. 合并各类单词的状态转换图,构成一个能 识别语言所有单词的状态转换图。
1) 将各类单词的状态转换图的初始状态合
并为一个唯一的初始状态;
2) 化简调整状态冲突和对冲突状态重新编
号;
3) 如果有必要,增加出错状态。
2020/7/7
CurrentCharEof do begin State:=T(State, CurrentChar);
Read(CurrentChar);
end;
if StateFinalStates then Accept else Error;
特点 2020/7/7 程序短小,但占用存储空间多。
7
设计与实现--自动机实现
4) 特殊符号:包括运算符和界限符。运算符表示程 序中算术运算、逻辑运算、字符运算、赋值运 算的确定的字符或字符串。
2020/7/7
4
设计与实现--正则表达式描述
1) 标识符: L(L | D)* 其中L=[a-z, A-Z], D=[0-9]
2) 整数: D1D*|0, 其中D1=[1-9] 3) 特殊符号:+ | ;| :| := | < | <= | … 4) 保留字: if | else | …
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
状态转换图
状态转换图是一张有限方向图; 状态转换图是一张有限方向图;
结点代表状态,用圆圈表示; 结点代表状态,用圆圈表示; 状态之间用箭弧连接, 状态之间用箭弧连接, 箭弧上的标记(字符)代表在射出结点( 箭弧上的标记(字符)代表在射出结点(即箭弧始结 状态下可能出现的输入字符或字符类。 点)状态下可能出现的输入字符或字符类。
一张转换图只包含有限个状态(即有限个结点),其 一张转换图只包含有限个状态(即有限个结点),其 ), 中一个被人为是初态, 中一个被人为是初态,而且实际上至少要有一个终态 用双圆圈表示)。 (用双圆圈表示)。 一个状态转换图可用于识别(或接收)一定的字符串。 一个状态转换图可用于识别(或接收)一定的字符串。
*
0
1
2
ቤተ መጻሕፍቲ ባይዱ
状态转换图实例
其中的假设条件是: 其中的假设条件是: 1.关键字都是保留字, 1.关键字都是保留字,不允许使用他们作为自己 关键字都是保留字 定义的标识符
*
3
=
4
5 6
+
* . . . . . .
7
*
*
*
8 9
2.将关键字作为一类特殊标识符来处理。 2.将关键字作为一类特殊标识符来处理。把它们 将关键字作为一类特殊标识符来处理 预先安排在一张表格中。 预先安排在一张表格中。 3.再次,如果关键字、 3.再次,如果关键字、标识符和常数之间没有确 再次 定的运算符或界符做间隔, 定的运算符或界符做间隔,则必须至少用一个空 白符做间隔。 白符做间隔。
如果后面还有状态图,出现在这个地方的代码应为: 如果后面还有状态图,出现在这个地方的代码应为: 将搜索指示器回退一个位置, 将搜索指示器回退一个位置,并令下一个状态图开始 工作。 工作。 如果后面没有其他的状态图, 如果后面没有其他的状态图,则出现在上述位置的代 码应该进行真正的出错处理, 码应该进行真正的出错处理,报告源程序含有非法符 并进行善后处理。 号,并进行善后处理。
状态转换图的实现( 状态转换图的实现(续1)
InsertId:整型函数过程,将strToken中的标识符插 :整型函数过程, 中的标识符插 入符号表, 入符号表,返回符号表指针 InsertConst:整型函数过程,将strToken中的常数插 :整型函数过程, 中的常数插 入常数表,返回常数表指针。 入常数表,返回常数表指针。 关于出错处理的一些说明: 关于出错处理的一些说明:
•运算符可采用一字一种的分 运算符可采用一字一种的分 法。也可以把具有一定共性 的运算符视为一种 •界符一般用一符一种的分法。 界符一般用一符一种的分法。 界符一般用一符一种的分法
分类方法: 分类方法: •关键字:可将 关键字: 关键字 其全体视为一 种,也可以一 字一种。 字一种。后者 更方便。 更方便。 •标识符:一般 标识符: 标识符 统归为一种 •常数则宜按照 常数则宜按照 类型(整型、 类型(整型、 实型、 实型、布尔型 等)分种
单词符号分类举例
单词符号 种别编码 DIM IF DO STOP END 标识符 常数 1 2 3 4 5 6 7 助忆符 $DIM $IF $DO $STOP $END $ID $INT 单词符号 = + * ** , ( ) 种别编码 8 9 10 11 12 13 14 助忆符 $ASSIGN $PLUS $STAR $POWER $COMMA $LPAR $RPAR
状态转换图的实现( 状态转换图的实现(续1)
对于不含回路的分叉结点来说,可让它对应一个 语句, 对于不含回路的分叉结点来说,可让它对应一个switch语句, 语句 或一组if…then…else语句 或一组 语句
j
i
/
k
GetChar() if(IsLetter()){…状态 的对应程序段 状态j的对应程序段 状态 的对应程序段…} else if (IsDigit()) {…状态 的对应程序段 状态k的对应程序段 状态 的对应程序段…} else if (ch == ‘/’) {…状态 的对应程序段 状态l的对应程序段 状态 的对应程序段…} else {…错误处理 错误处理…} 错误处理
其他单词符号的识别
标识符的识别
多数语言的标识符是字母开头的“字母 数字 数字” 多数语言的标识符是字母开头的“字母/数字”串,而且在程序 中标识符的出现都后跟这算符或者界符。 中标识符的出现都后跟这算符或者界符。因此标识符的识别没 有太大的困难。 有太大的困难。
常数的识别
基本来讲常数的识别也是很直接的,有些需要用到超前搜索。 基本来讲常数的识别也是很直接的,有些需要用到超前搜索。 超前搜索 如5.E08和5.EQ.M。 和 。
算符和界符的识别
词法分析器将那些多个字符复合成的算符和界符(如 、 、 词法分析器将那些多个字符复合成的算符和界符 如++、--、>=) 拼合成一个单词符号。因为这些单词符号是不可分的整体, 拼合成一个单词符号。因为这些单词符号是不可分的整体,若 分划开来,便失去了原来的意义。这里需要超前搜索。 分划开来,便失去了原来的意义。这里需要超前搜索。
词法分析器的设计与实现
输入、预处理和单词的识别(超前搜索) 输入、预处理和单词的识别(超前搜索)
预处理,主要是针对空白符、跳格符、 预处理,主要是针对空白符、跳格符、回车符和换行符等编 辑性字符的处理。 辑性字符的处理。
输入
输入缓冲区 预处理子程序
列表
扫描缓冲区 扫描器
单词符号
双缓冲区技术
关键字的识别
词法分析中的错误
词法分析器不能从全局的角度考察源程序, 词法分析器不能从全局的角度考察源程序,所以能在 词法分析阶段发现的错误是有限的。 词法分析阶段发现的错误是有限的。主要是不符合合 法标识符拼写的错误。 法标识符拼写的错误。 例如,如果词法分析器第一次碰到如下的C语言程序 语言程序: 例如,如果词法分析器第一次碰到如下的 语言程序: fi(a==f(x))… 词法分析器无法区别fi究竟是关键字 究竟是关键字if的错误拼写还 词法分析器无法区别 究竟是关键字 的错误拼写还 是一个未声明的函数标识符。由于fi是合法的标识符 是合法的标识符, 是一个未声明的函数标识符。由于 是合法的标识符, 词法分析器必须返回该标识符的记号,让编译器的其 词法分析器必须返回该标识符的记号, 他阶段去处理这种错误。 他阶段去处理这种错误。
第一步: 第一步:词法分析
词法分析器在编译器中的位置
词法分析是编译的第一阶段。 词法分析是编译的第一阶段。其任务是从左到右逐字的对源 程序进行扫描,产生一个一个的单词符号,把作为字符串的 程序进行扫描,产生一个一个的单词符号, 源程序改造成为单词符号串的中间程序。 源程序改造成为单词符号串的中间程序。 词法分析是编译过程中的一个阶段, 词法分析是编译过程中的一个阶段,在语法分析前进行 。也 可以和语法分析结合在一起作为一遍,由语法分析程序调用 可以和语法分析结合在一起作为一遍, 词法分析程序来获得当前单词供语法分析使用。 词法分析程序来获得当前单词供语法分析使用。
(单词种别,单词符号的属性值) 单词种别,单词符号的属性值)
单词符号的属性信息是指单词符号的特性或特征, 单词符号的属性信息是指单词符号的特性或特征,属性 值则是反应特性和特征的值。 值则是反应特性和特征的值。 对于某个标识符, 对于某个标识符,常将存放它的有关信息的符号表项的 指针作为其属性值 对于某个常数, 对于某个常数,则将存放它的常数表项的指针作为其属 性值。 性值。
状态转换图示例
识别整数的转换图
转换图示例
识别标识符的转换图
终态结点上打了一个星号*, 终态结点上打了一个星号 ,意味着多读进了一个不属于标识符部分的字 应该把它退还给输入串。 符,应该把它退还给输入串。 如果在状态0时的输入不能符合任何一条转换路径 时的输入不能符合任何一条转换路径, 如果在状态 时的输入不能符合任何一条转换路径,那么就说明这个转换 图工作不成功,不能识别出标识符。 图工作不成功,不能识别出标识符。
记号 源程序 词法分析器 取下一 个记号 语法分析器
符号表
词法分析程序的功能
词法分析:根据词法规则识别及组合单词, 词法分析:根据词法规则识别及组合单词,进行词法检查 对数字常数完成数字字符串到二进制数值的转换 删去空格字符和注释
词法分析器的输出形式
词法分析器所输出的单词符号常常表示成如下的二元 式:
这样的语言, 像FORTRAN这样的语言,关键字不加以特殊保护, 这样的语言 关键字不加以特殊保护, 关键字和用户自定义的标识符或标号之间没有特殊的 界符做间隔。这使得关键字的识别甚为麻烦。 界符做间隔。这使得关键字的识别甚为麻烦。
1.DO99K = 1, 10 2.IF(5.EQ.M) I = 10 3.DO99K = 1.10 4.IF(5.EQ.M) = 55 其中,语句1和 是 语句, 其中,语句 和2是DO和IF语句,他们都是以基本字开 和 语句 头的,语句3和 是赋值语句 是赋值语句, 头的,语句 和4是赋值语句,都是以用户自定义的标 识符开头的。 识符开头的。
单词符号输出例子
对于C++语言的代码:while (i >= j) i--; 语言的代码: 对于 语言的代码 经词法分析器处理后,应该成为: 经词法分析器处理后,应该成为:
<$WHILE, - > <$LPAR, - > <$ID, 指向i的符号表项的指针 > 指向 的符号表项的指针 < >=, -> <$ID, 指向 的符号表项的指针 指向j的符号表项的指针 的符号表项的指针> <&RPAR, -> <$ID, 指向 的符号表表项的指针 指向i的符号表表项的指针 的符号表表项的指针> < --, -> < ;, ->