《编译原理及实践教程》第3章词法分析

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

• 单词种别码和单词值的用途:
– 单词的种别码在语法分析时使用 – 单词的值在语义分析和中间代码生成时使用。
词法分析输出举例
• 例3.1 对于语句if (r>=2.0) C=2*pi*r,经词 法分析后的输出为:
(9, ―if‖) (46, ―(‖) (34, ―r‖) (31, ―>=‖) (36, ―2.0‖) (47, ―)‖) (34, ―C‖) (39, ―=‖) (35, ―2‖) (26, ―*‖) (34, ―pi‖) (26, ―*‖) (34, ―r‖)
首先对程序语言的 单词按类构造出相 应的状态转换图。 对各类状态转换图 合并(如左图)。 根据状态转画图编 写识别该类单词的 函数(使用一个 switch case 语句: 每条分支对应一个 case语句段),最 终输出单词的 token表(单词种 别码,单词值)。
字母或数字
*
2
• 例:识别表达式“x2=56;”中的整数56
数字
* 0
数字
1
其它
2
图3.6(b) 识别无符号整数的状态转换图
• Sample语言中识别无符号实数的状态转换图 (不带正 负号,可表示整数、可表示小数,可带指数部分) • 如:下面几个数应该是符合规则的数: 3,3.51,34E3,34.5E2,34.5E+2,34.5E-2
3.2.1 词法分析程序的接口
• 词法分析程序的主要任务
– 扫描源程序 – 识别单词,转换并输出token串 – 输出相应的错误信息 – 查填符号表 符号表
源程序
二元形式 (种别码, 单词值)
词法分析程序
token文件 源程序清单 和错误信息
图3.2 词法分析程序的输入/输出接口(顶层数据流图)
3.2.2 词法分析程序的总体设计
– 识别数值型常数(加工1.6):当读入的单词首 字符是数字时,开始识别整数或实数。 – 处理注释和除号(加工1.7):当读入的单词首 字符是“/”时,开始识别注释和除号。 – 识别文字常数(加工1.8):当读入的单词首字 符是单引号时,忽略单引号,开始拼写字符常 数,直到下一个单引号结束,最后返回种别码 – 识别其他界符和运算符(加工1.9): – 查填符号表(加工2):对标识符和常数识别 后,要查填符号表(若表中没有,则加入表并 填写属性等信息)。符号表的格式见3.2.5节的 表3.2。
例:识别表达式“x2=56;”中的标识符x2
字母或数字
*
0
字母
1
其它
2
图3.6(a) 识别标识符的状态转换图
字母或数字
*
0 字母 1
其它
2
识别过程是:从初始状态0开始,读取一个字符,若是字母, 读入它,转入状态1,否则(不是字母)识别失败。在状 态1,读取下一个字符,若为字母或数字,则读入它,仍 处于状态1;在状态1读入的字符不是字母或数字,则转向 状态2,结束一个标识符的识别过程。状态上的*表示多读 入一个符号,指针应回退一个字符。
• 对“输入/输出接口”(图3.2)按照软件工程自 顶向下逐层分解→图3.3和图3.4
– 图3.3第一层数据流图:主要工作是“识别单词”和 “查填符号表”
token文件 源程序 识别 单词1 标识符 常数 源程序清单 和错误信息
图3.3 第一层数据流图(圆圈:表示“加工”)
查填符 号表2
符号表
– 图3.4更详细的数据流图:对图3.3(第一层数 据流图)再进一步展开。
第 3章
词法分析
本章要求
• 主要内容:词法分析的任务,手工实现 词法分析程序,正规式与有穷自动机, 词法分析程序的自动生成 • 重点掌握:词法分析器的功能和接口, 用状态转换图设计和实现词法分析程序, 正规文法、正规式和有穷自动机的概念 及相互转换
词法分析 程序所处 的位置:
to 词法 取下一个 ke 语法 分析 单词 分析 n 符号 器
表3.1 Sample语言单词的编码
类 别 var integer 单词 program 种别码 1 2 3 类 别 关 键 字 单词 write true false 种别码 18 19 20 标识 符 id 34 类别 单词 种别码
bool
real char const 关 键 字
4
5 6 7
值 常

除号/

运 算 符

常 字

识别界 符和运 算符1.9
图3.4 更详细的数据流图
其 它


其 它 界
符 和 运 算 符
token文件
符号表
• 详解“图3.4详细数据流图”
– 读入一行(加工1.1):从源程序文件读入一行, 存入缓冲区(字符型数组),行计数器加1。 – 读一非空字符(加工1.2):从缓冲区读一个字符 ,列计数器加1,直到读取一个非空字符为止.若缓 冲区已空,则再读一行到缓冲区,此时列计数器 置0、行计数器加1. – 字符分类(加工1.3):据单词首字符。 – 输出token串(加工1.4):对所有识别出的单词 按二元形式输出(种别码,单词值) – 识别标识符/关键字(加工1.5):当读入的单词首 字符是字母时,开始识别标识符或关键字。形成 单词后查关键字表。
3.2.4 使用状态转换图来识别单词
状态转换图是描述单词构成规则的一种很好的工具。
利用转换图可识别(或接受)按某种规则构成的单词。 状态转换图是一张有限方向图。有限个状态,用结点(圆 圈)表示状态,其中有一个初态(初态用箭头指出),至少 有一个终态(终态用双圈表示)。状态之间用带箭头的弧线 连结,称为边,由状态s到状态r的边上标记的字符表示使 状态s转换到状态r的输入字符或字符类。
E/e 数字 数字 数字 E/e
=>
0
数字
1
.
2
数字
3
4
+或 -
5
数字
数字
6
其他
7
其他 其他
图3.6(c) 无符号实数的状态转换图
• 对图3.6(c)—无符号实数状态转换图改进:
– 使用不同的终态来表示不同单词的识别,不仅可靠性 高,而且可据此来确定该数的属性,便于填入符号表
• • • • 终态7:识别出错处理的终态 终态8:识别带指数的实数的终态 终态9:识别带小数的实数的终态 终态10:识别整数的终态
语法 树


编译 程序 的后 续部 分
3.1 词法分析的任务和功能
• 功能:
源程序 词法分析程序 Token串 语法分析程序 – 逐个读入源程序字符并按照构词规则切分成一系列单词 – 对识别过程中发现的词法错误,输出错误信息
• 主要任务:
– 读入源程序,从左至右逐个字符地扫描,识别出各个单 词符号,并输出(形式:单词符号串——token串)
源程序 识别标 识符/关 键字1.5
说明:圆圈 代表“加工” 或“处理”

读入一 行1.1

源程序清单 读一非 空字符 1.2
缓冲区 buffer 字符 首字符 分类1.3


/ ‘
识别数 值常数 1.6 处理注 释和除 号1.7 识别文 字常数 1.8

符 /关


字 键
输出 标识符 token串 常数 1.4 查填符 号表2
识别单词
是最复杂的工作
超前搜索技术:如在读取/* */时,当读到/ 时,如何判别是注释还是除法运算?
识别单词:掌握单词的构成规则很重要
• 主要包括如下几种单词的识别:
– 标识符的识别:字母+(字母/数字) – 关键字的识别:与标识符相同,最后查关键 字表 – 常数的识别 – 界符和算符的识别
其他 (为小数) (出错)
数字
7 10 8
* *
其他
其他
数字
=> 0
数字
1

2
数字
3
数字
E/e
4
+/-
5
数字
数字
6
其他
(为指数)
*
E/e 其他(为整数)
9
*

习 1
• 画出识别标识符和整常数(可带正负号)的状 态转换图
练 习 2
• 以下状态转换图接受的字符集合是什么?
0 X 0 Y 1
词法分析程序 实现方法总结
初始化 打开源文件
3.2.3 词法分析程序 的详细设计
Y
源程序结束? N 读入一行到string中 get_line() 缓冲区空? N 读取单词的第1个字 符get_nextchar() 根据第1 个字符进行分类 sort()
Y
符号表和token 表写入文件 write_sym() write_token()
单词的种别码
• 一个单词的输出形式(二元形式):
(种别码,单词的值) 如:(14,"for")、(39,"=")
• 单词的种别码:表示单词的种类,通常用整数编码 – 单词如何分类、如何编码,没有统一的规定,主 要取决于处理上的方便。 – 分种编码原则:不同的单词能彼此区别且有唯一 的表示
• • • • • 标识符一般统一为一种、一个编号 常数按类型分别编码:整数、实数、布尔、字符 关键字一般一字一种 运算符一般一符一种 界符一般一符一种
• 词法分析程序有两种实现方式
– 可以作为独立的一遍,即一个独立的功能程序 – 可以和语法分析结合在一起作为一遍
• 将词法分析程序设计成一个子程序,每当语法分析程序需 要一个单词时,就调用该子程序。
3.2 词法分析程序的设计
本节主要介绍手工构造方式 按软件工程的观点介绍设计方法
画数据流图 总体设计 详细设计 程序实现(编程)
• 其他任务:
– 滤掉程序中的无用成分,如空格、注释、换行符 – 调用出错处理程序,指出源程序出错的行列位置 – 调用符号管理程序,对识别出的单词进行管理 • 关键:找出单词的分隔符
单词的类型
• 单词:是语言中具有独立意义的最小单位,常用 单词分5类: – 保留字(关键字):具有固定意义的标识符 – 标识符:表示各种名字(变量名、函数名等) – 常数:整型、实型、布尔型、字符型等 – 运算符:算术运算符(+、-、*、/)、逻辑 运算符(not、and、or)和关系运算符(<、 >、<=、>=、==) – 界符:类似自然语言的标点符号,分:单界 符(;、’等)、双界符(/*等)
not
and or +
21
22 23 24 常 数
整常数
实常数 字符常数 布尔常数
35
36 37 38
begin
if then
8
9 10 运 算 符
* /
25
26 27
=
; ,
39
40 41
else
while do
11
12 13
<
> <=
28
29 30 界 符
'
/* */
42
43 44
for
to end
关闭所有文件 结束
数字 识别数值常数 recog_dig()
Hale Waihona Puke Baidu

识别字符常数 recog_str()
字母 识别标识符/关 键字recog_id() 是关键字? iskeyword(s) N 在符号表中? isexist_sym(s) N 插入符号表 ins_sym(s,token)
/ 处理注释和除 号hand_com() 除 号 Y Y
其它特 殊符号 识别界符 recog_del()
在界符表中? isdelimete(s) N
Y
出错处理 error()
插入token表 ins_token(s,token)
• 识别单词前作如下假定:
– 关键字就是保留字 – 单词中间不能有分界符(如空格、空白、界符和 算符等) – 单词中间不能有注释 – 单词必须在一行内写完,换行后认为是另一个 单词 – 一个单词不能超过规定长度
识别过程中,若能到达终点,表示单词正确,否 则单词不正确(如标识符“$x”)。
写成C语言的函数形式: recog_id(char ch) { 0 1 其它 char state = '0'; 字母 while (state != '2') { switch(state) { case '0': ch=get_nextchar(); if (isletter(ch)) state ='1' else error(); break; case '1': ch=get_nextchar(); if (isletter(ch)||isdigit(ch)) state ='1' else state = '2'; break; } } return (gettoken()); //返回识别的单词的token值(查表3.1) }
14
15 16
>=
== <>
31
32 33
:
( )
45
46 47
read
17
.
48
• 单词的值:
可用多种方式给出: – 对于“一字(一符)一种”单词:单词值可不 给出(因单词的种别码唯一代表该单词) – 一个类别有多个单词(标识符、常数):必须 给出每个单词值,单词值可为单词符号串本身 ,也可为一个指针值(在符号表和常数表中的 入口位置),常数的单词值也可以是自身常数 的二进制数。
相关文档
最新文档