410 likes | 630 Views
第 3 章 词法分析. 词法分析 (Lexical Analysis) 词法的表示 词法分析器的设计与实现. 主要内容. 词法分析器 (Lexical Analyzer, Scanner) 的功能 正规表达式 有穷状态自动机 FA—— 状态图 词法分析器的设计与实现. 3 .1 词法分析(扫描)器的功能. 功能:输入源程序,输出 ( 单词 ) 符号 (token) 。即:把构成源程序的字符串转换成单词符号的序列 单词符号的形式 按照最小的语义单位设计 通常表示为二元组: (单词符号种别,属性值 ) 关键 —— 找出符号的分割符
E N D
第3章 词法分析 词法分析(Lexical Analysis) 词法的表示 词法分析器的设计与实现
主要内容 • 词法分析器(Lexical Analyzer, Scanner)的功能 • 正规表达式 • 有穷状态自动机FA——状态图 • 词法分析器的设计与实现
3.1 词法分析(扫描)器的功能 • 功能:输入源程序,输出(单词)符号(token)。即:把构成源程序的字符串转换成单词符号的序列 • 单词符号的形式 • 按照最小的语义单位设计 • 通常表示为二元组: (单词符号种别,属性值 ) • 关键——找出符号的分割符 • 例如:axx=70.35+12+exp(2.7)
1) 单词符号的表示 • 常用单词符号种别——分类(P42) • 各关键字(保留字、基本字),各种运算符,各种分界符——各用一个种别码标识 • 其它标识符——用一个种别码标识 • 常数——用一个种别码标识 • 属性(值)——单词符号的值 • 常数的值,标识符的名字等 • 保留字、运算符、分界符的属性值可以省略
例 3-1: 单词符号序列while(pointer!=N){S=S++;pointer++;} while (WHILE, _ ) ( (SLP, _ ) pointer (IDN,符号表项指针) != (NE, _ ) N (IDN,符号表项指针) ) (SRP, _ ) { (LP, _ ) S (IDN,符号表项指针) = (EQ, _) S (IDN,符号表项指针) ++ (INC, _ ) ; (SEMI, _ ) pointer (IDN, 符号表项指针) ++ (INC, _ ) ; (SEMI, _ ) } (RP, _ )
正拼单词 扫描指针 单词开始指针 2)相关问题 • 词法分析器可以作为一个独立的子程序,也可以作为一遍独立的扫描来安排。 • 输入缓冲区 工作区(token) • 双缓冲区 • 并行、捻接
2)相关问题 每次移动向前指针都需要做两次测试 forward := forward +1; ifforward在缓冲区第一部分末尾then 重装缓冲区第二部分 else if forward在缓冲区第二部分末尾then begin 重装缓冲区第一部分; 将forward移到缓冲区第一部分开始 end forward := forward + 1; if forward!= eof then ifforward在第一部分末尾then重装第二部分 else if forward在第二部分末尾then begin 重装第一部分; 将forward移到第一部分开始 end else终止词法分析 /* eof在表示输入结束 */ • 大小问题128Byte*2|1024Byte*2|4096Byte*2 • ?如何设计和实现扫描器
3.2 符号的描述——正规(表达)式 • 例:标识符的文法描述 • 约定:用d表示数字:0,1,2,…,9; 用l表示字母:A,B,…,Z,a,b,…,z • G =({d,l}, {S,T}, P, S) • S→l • S→S d • S→S l • 左线性文法 • S→l |lT • T→l T|l • T→dT|d • 右线性文法 • 表示集合:{l}{l,d}*
1) 正规式:正规语言的另一种描述方法 • 例3-2:标识符的另一种表示 • l (l|d)* • | 表示"或" • * 表示Kleene闭包 • 符号的并列表示符号连接关系 • 正规式 r 表示正规集,相应的正规集记为 L(r)
正规(表达)式(Regular Expression——RE) 设∑是一个字母表, ⑴ Φ是∑上的RE,L(Φ)=Φ; ⑵ ε是∑上的RE,L(ε)={ε}; ⑶ 对于a∈∑,a是RE,L(a)={a}; ⑷如果r和s是RE,L(r)=R,L(s)=S,则: r与s的“和” (r|s)是RE,L(r|s)=R∪S; r与s的“乘积” (rs)是RE,L(rs)=RS; r的克林闭包(r*)是RE,L(r*)=R*。 ⑸ 只有满足⑴、⑵、⑶、⑷的才是RE。
运算的优先级 运算优先级和结合性: • *高于“连接” 和| , “连接” 高于 | • | 具有交换律、结合律 • “连接” 具有结合律、和对|的分配律 • ( ) 指定优先关系 意义清楚时,括号可以省略 例:L(a(a|b)*(ε|((.|_)(a|b)(a|b)*))) {a}{a,b}*({ε}∪{.,_}{a,b}{a,b}* )
2) 正规文法与正规式 • 正规文法与正规式等价 • 对任何正规文法,存在定义同一语言的正规式 • 对任何正规式,存在生成同一语言的正规文法
例 3-3 标识符定义的转换 • 引入 S S→l (l|d)* • 引入A消除闭包 S→l A A→(l|d)A|ε • 执行连接对|的分配律 S→lA A→lA|dA|ε
例3-4正规式到正规文法的转换 • a(a|b)*(ε|((.|_)(a|b)(a|b)*)) = a(a|b)* |a(a|b)*.(a(a|b)*|b(a|b)*) |a(a|b)*_(a(a|b)*|b(a|b)*) =aA|aC A→aA|bA|ε C→aC|bC|.B|_B B→aA|bA S→aA|aC A→aA|bA|ε C→aC|bC|.B|_B B→aA|bA
正规式到正规文法的转换 • 按如下方法构造正规定义式,并逐步将其转换成正则文法 • 引入开始符号S,从如下正规定义式开始 • S→r • 对r中的形如r1|r2|…|rn的子串 • 用产生式组 A→ r1|r2|…|rn 表示
正规式到正规文法的转换 • 对r中的形如r1*的子串 • 用产生式组 A→ε|r1A 表示 • 对r中的形如r1+的子式子, • 用产生式组 A→ r1| r1A 表示 • 执行连接对|的分配律 • 对连接运算,要作特殊处理:按出现顺序定义 • 正规式到正规文法的转换用到了正规定义式的概念
例 3-5:一个简单词法的正规定义式 词法规则 单词种别 属性 <标识符>→<字母>(<字母>|<数字>)*IDN 符号表项入口 <无符号整数>→ <数字> (<数字>)*NUM 数值 <赋值符>→ := ASG 无 <加号>→+ + 无 <减号>→- MINUS 无 <星号>→* STAR 无
变换为正规文法 <标识符>→letter<标识符尾> <标识符尾>→ε|letter<标识符尾>|digit<标识符尾> <整数>→digit <整数尾> <整数尾>→ε| digit<整数尾> <赋值号>→:= <加号>→+ <等号>→= … (其它:实数、算术运算符、关系运算符、分号、括号等)
正规文法到正规定义式的转换 • 代入:对于 A→xB, B→y,构造 A→xy • 递归:对于 A→xA|y,构造 A→x*y • 多候选式:对于 A→x,A→y,构造A→x|y S→0A A→1B B→2B|2C C→3C|3 S→01B S→012*2C S→012*23*3 S→ 012+3+ • 一个语言的文法描述不是唯一的(等价文法)
3.3 符号的识别──状态转换图 1 状态转换图(有穷自动机 FA M=(Q,∑,δ,q0,F) ) 用来描述词法分析器识别记号的分析过程 • 结点:状态用○表示;终态用◎表示 • 有向弧 ── 箭头 • 弧标记 ── 输入字符 • 标识符的状态图<标识符>→letter(letter|digit)* letter,digit 初态 终态 1 2 3 开始 letter 其它
例3-5的状态图 词法规则 单词种别 属性 <标识符>→letter(letter|digit)*IDN 符号表项入口 <无符号整数>→digit (digit)*NUM 数值 <赋值符>→ := ASG 无 <加号>→+ + 无 <减号>→- MINUS 无 <星号>→* STAR 无
例3-5的状态图 IDN→letter(letter|digit)* letter,digit s letter (其它) (IDN,入口) NUM→digit(digit)* digit digit : (其它) (NUM,值) 其它 (ASG,_) + ASG→:= = (ADD,_) + (INC,_) ADD→+ INC→++
利用状态转换图识别单词符号 1. 从初态出发 2. 读入一字符 3. 按当前字符转入下一状态 4. 重复 2,3 直到无法继续转移 • 在遇到读入的字符是Token的分割符时,若当前状态是终止状态,说明读入的字符组成一单词;否则,说明输入不符合词法规则。
B A a A a s A r B 2、从正规文法出发,构造状态图 1.以每个非终结符为状态结点,开始符号对应初态 S 2.增设一个终态 T 3.对于规则 A→aB,画从状态 A 到 B 的弧,标为 a 4.对于规则 A→a,画从状态 A 到终态 T 的弧,标为 a *. 对于规则 A→rB,B →sB,画从状态 A 到状态 N 的弧,标为 r和状态N到N的标记为s的弧
s A r 例 3-6 C语言无符号整数的识别1、正规定义式描述 八进制数: ( OCT,值 ) • oct→0(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)* 十进制数: ( DEC,值 ) • dec→(1|...|9)(0|...|9)* |0 十六进制数: ( HEX,值 ) • hex→0x(0|1|...|9|a|...|f|A|…|F)(0|...|9|a|...|f |A|…|F)*
2、识别不同进制数的状态图 oct→0(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)* 0-7 八进制整数 0 1 2 3 4 (其它) 0-7 dec→(1|...|9)(0|...|9)* |0 0-9 十进制整数 1 5 6 (其它) 1-9 0
2、识别不同进制数的状态图 状态图合并 1、从开始状态出发; 2、选择输入符号,构成目标状态集 3、从新状态集出发,重复1、2 hex→0x(0|1|...|9|a|...|f|A|…|F)(0|...|9|a|...|f |A|…|F)* 十六进制整数 x (其它) 0 0-9,a-f 1 7 8 9 10 0-9,a-f
4 10 6 3、C语言无符号整数识别的状态图 (OCT,值) 0-7 3 其它 0-7 (HEX,值) 0 0-9 ,a-f x 1 2,6,7 8 9 其它 0-9,a-f 其它 1-9 0-9 5 其它 (DEC,值)
0-7 其它 5 0-7 0 开始 x 0-9 ,a-f 其它 1 2 3 4 其它 0-9 ,a-f 0-9 其它 6 1-9 另一种做法 (OCT,值) (HEX,值) (DEC,值)
3.4 词法分析程序的设计与实现 • 状态转移图——教材P43 • 状态转移图的实现——教材P44-46 • 另一种实现:子程序 scan( ) • 输入:字符流 • 输出: • Symbol(Code) :单词种别 • Attr(value):属性(全局变量)
数据结构与子例程 • 数据结构 • ch 当前输入字符 • token 输入缓冲区(字符数组) • symbol 单词种别(子程序的返回值) • attr 属性(全局变量) • 子程序 • Lookup(token):将 token 存入符号表,返回入口指针 • isKeyword(token):判别 token是关键字?返回关键字种别或 -1 • getchar():从输入缓冲区中读入一个字符放入ch • isdigit() isalpha()
例3-3的状态图的实现算法 1. getchar() 2. WHILE ch 是空格 //跳过空格 2.1 DO getchar(); 3. CASE ch OF 4. isdigit(ch) : 4.1 ch→token; getchar(); 4.2 WHILE isdigit(ch) DO { ch→token; getchar();} 4.3 输入指针回退一个字符; 4.4 将token中的字符串变成数值→attr 4.5 返回 NUM
5. isalpha(ch) : 5.1 ch→token; getchar(); 5.2 WHILE isalpha(ch) OR isdigit(ch) DO {ch→token; getchar()}; 5.3 输入指针回退一个字符; 5.4 key = isKeyword(token); 5.5 IF key≥0 THEN 返回 key 5.6 Lookup(token)→attr; 5.7 返回 IDN 6 ':' : getchar(); 6.1 IF ch等于'=' THEN 返回 ASG 6.2 出错处理
7 '+' : 返回 ADD 8 '-' : 返回 SUB 9 '*' : 返回 MUL 10 '/' : 返回 DIV 11 '=' : 返回 EQ 12 '>' : 返回 GT 13 '<' : 返回 LT 14 '(' : 返回 LP 15 ')' : 返回 RP 16 ';' : 返回 SEMI 17 其它 : 出错处理 18 END OF CASE
需要说明的问题 • 缓冲区预处理,超前搜索 • 关键字的处理,符号表的实现 • Lookup:查找效率,算法的优化实现 • 词法错误处理 • 由于高级语言的词组成的集合为3型语言,所以,这里讨论的词法分析技术可以用于处理所有的3型语言,也就是所有的可以用3型文法描述的语言。如:信息检索系统的查询语言、命令语言等
LEX简介:实现过程 Lex源程序 Lex.yy.c Lex编译器 Lex.yy.c C编译器 词法分析器L 词法分析器L Token序列 输入流
LEX简介:Lex程序结构 %{ 常量定义 %} 正规定义 声明部分 (正规定义式) %% 转换规则 (识别规则) %% 辅助过程
扫描器的自动生成:LEX简介 1、正规定义式 letter→A|B|C|…|Z|a|b|c|…|z digit→0|1|2|…|9 identifier→letter(letter|digit)* integer→digit(digit)* 2、识别规则 正规式 动作描述 token1 {action1} token2 {action2} …… tokenn {actionn}
本章总结 • 词法分析器从组成源程序的字符行中寻找出单词,并给出它们的种别和属性——输出二元组序列 • 高级语言的单词组成一个3型语言 • 3型语言可以用RE、RG、FA描述 • FA的状态转移图,可以被用来指导相应的词法分析器的实现
本章总结 正规表达式 ↓ 正规定义式 ↓ 状态图 ↓ 识别过程的实现算法 ↓ 程序实现和测试 • 3型语言相应的理论指导人们构造出了高级语言的词法分析器的自动生成器——如:Lex