版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、编译原理实验姓 名:朱彦荣学 号:专 业:软件工程 2 实验题目:词法分析 完成语言: C/C+ 上级系统: VC+6.0日 期: 2015/11/7词法分析设计题目: 手工设计 c 语言的词法分析器(可以是 c 语言的子集 )设计内容:处理 c 语言源程序, 过滤掉无用符号 ,判断源程序中 单词的合法性 ,并 分解出 正确的单词 ,以 二元组形式存放在文件 中。设计目的: 了解高级语言单词的分类,了解状态图以及如何表示并识别单词规则, 掌握状态图到识别程序的编程。结果要求: 课程设计报告。完成日期: 第十五周提交报告一 分析要想 手工设计词法分析器,实现 C 语言子集的识别,就要明白 什么是
2、词法分析器 ,它的 功能是什么。词法分析是编译程序进行编译时 第一个要进行的任务主要是对源程序进行编译预处理 (去除注释、 无用的回车换行找到包含的文件等) 之后, 对整个源程序进行分解 ,分解成 一个个单词 ,这些单词有且 只有五类 ,分别是 标识符、保留字、常数、运算符、界符 。以便为下面的语法分析和语义分析要定义好这五种符号的集合 。下做准备。可以说词法分析面向的对象是 单个的字符 ,目的是把它们 组成有效的单 词(字符串);而 语法的分析 则是利用词法分析的结果作为输入来分析是否符合语 法规则并且进行 语法制导 下的语义分析,最后产生 四元组 (中间代码 ),进行优化 (可有可无)之后
3、最终生成 目标代码 。可见词法分析是所有 后续工作的基础 ,如 果这一步出错,比如明明是 <='却被拆分成 <'和 ='就会对下文造成不可面是我构造的一个 C 语言子集 。第一类:标识符 letter(letter | digit)*无穷集第二类:常数 (digit)+ 无穷集第三类:保留字 (32)autobreakcase charconstcontinuedefaultdodouble elseenumexternfloatforgoto ifintlongregisterreturnshort signedsizeofstaticstructswit
4、chtypedef unionunsignedvoidvolatilewhile第四类:界符 /*'、/ '、 () " " ' 等第五类:运算符 <、<=、 >、 >=、 =、 +、-、*、/、八、等挽回的影响。因此,在进行词法分析的时候一定对所有可数符号进行编码:<$,0><auto,1> <while,32><+,33> <-,34> <*,35> </,36> <<,37> <<=,38> <&
5、gt;,39> <>=,40> <=,41><=,42><!=,43><,44><(,45><),46><八,47><,48><",49><',50><#,51><&,52><&&,53><|,54><|,55><%,56><,57><<<,58>左移<>>,59>右移<,6
6、0><,61><,62><,63><,64><.,65><?,66><:,67><!,68>"","","",""<常数 99 ,数值 ><标识符 100 ,标识符指针 >上述二元组中左边是单词的符号,右边为其 种别码 ,其中常数和标识符有点特别,因为是无穷集合,因此常数用自身来表示,种别码为99,标识符用标识符符号表的指针表示(当然也可用自身显示,比较容易观察) ,种别码 100。根据上述
7、约定,一旦见到了种别码syn=63就唯一确定了 '这个单词。下面是一些变量的约定:/ 全局变量,保留字表static char reserveWord3220 = "auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", "enum", "e
8、xtern", "float", "for", "goto", "if", "int", "long","register", "return", "short", "signed", "sizeof", "static","struct", "switch", "typedef", &q
9、uot;union", "unsigned", "void", "volatile", "while"/ 界符运算符表 ,根据需要可以自行增加static char operatorOrDelimiter3610= "+","-","*","/","<","<=",">",">=","=","=
10、","!=",";","(",")","A",",",""","'","#","&","","",".","?",":","!";static char IDentifierTbl100050="";/ 标识符表char r
11、esourceProject10000;/ 输入的源程序存放处,最大可以存放 10000个字符。char token20=0;每次扫描的时候存储已经扫描的结果。int syn=-1;/syn即为种别码,约定$'的种别码为0,为整个源程序的结束符号一旦扫描到这个字符代表扫描结束int pProject = 0;/源程序指针,始终指向当前源程序待扫描位置。几个重要函数:/ 查找保留字,若成功查找,则返回种别码/ 否则返回 -1,代表查找不成功,即为标识符 int searchReserve(char reserveWord 20, char s)/* 判断是否为字母 */ bool IsL
12、etter(char letter)/* 判断是否为数字 */bool IsDigit(char digit)/* 编译预处理,取出无用的字符和注释 */ void filterResource(char r,int pProject)/*分析子程序,算法核心 */void Scanner(int &syn,char resourceProject,char token,int &pProject)面说一下整个程序的流程:1. 词法分析程序 打开源文件, 读取文件内容, 直至遇上 '$'文件结束符, 然后读取结束。2. 对读取的文件进行预处理,从头到尾进行扫描,
13、 去除/和/*/的内容 ,以及一些无用的、影响程序执行的符号如换行符、回车符、制表符等。但是 千万注意不要在这个时候去除空格,因为空格在词法分析中有用,比如说int i=3;这个语句,如果去除空格就变成了 “ inti=3”,这样就失去了程序的本意,因此不能在这个时候去除空格。3. 选下面就要对 源文件从头到尾进行扫描 了,从头开始扫描, 这个时候扫描程序首先要 询问当前的字符 是不是空格 ,若是空格,则继续扫描下一个字符,直至不是空格,然后询问这个字符 是不是字母 ,若是则进行标识符和保留字的识别; 若这个 字符为数字 ,则进行数字的判断。 否则, 依次对这个 字符可能的情况进行判断, 若是
14、将所有可能都 走了一遍还是没有知道它是谁,则认定为 错误符号,输出该错误符号 ,然后结束。每 次成功识别了一个单词后,单词都会存在 token 中。然后确定这个单词的 种别码 , 最后进行下一个单词的识别。 这就是扫描程序进行的工作, 可以说这个程序彻底实现 了 确定有限自动机 的某些功能,比如说 识别标识符,识别数字 等。为了简单起见,这 里的数字只是 整数 。4. 主控程序主要负责对每次识别的种别码 syn进行判断,对于不同的单词种别做出不同 的反应, 如对于标识符则将其插入标识符表中。 对于保留字则输出该保留字的种别码 和助记符,等等吧。直至遇到 syn=0程序结束。二流程图下面是程序的
15、流程图:三运行与测试比如说,就拿这个源程序的一部分进行测试:运行程序后结果为: 同样单词也写入了文件如下: 。综上分析,达到了预期的结果。四实验体会每做一次比较大的实验, 都应该写一下实验体会, 来加深自己对知识的认识。其实这次的实验,算法部分并不难,只要知道了 DFA这个模块很好写,比较麻烦的就是五种 类型的字符个数越多程序就越长。 但为了能识别大部分程序, 我还是用了比较大的子集, 结果花了一下午的功夫才写完,虽然很累吧,但看着这个词法分析器的处理能力,觉得 还是值得的。同时也加深了对字符的认识。程序的可读性还算不错。程序没有实现的是对所有复合运算的分离,但原理是相同的,比如“+=“,只需
16、在” +“的逻辑之后向前扫描就行了, 因此就没有再加上了。 感受最深的是学习编译原理必须要做实验, 写程序, 这样才会提高自己的动手能力,加深自己对难点的理解,对于以后的求 first,follow,fisrtVT,lastVT5 是应该如此。五源程序/ Lexical_Analysis.cpp : 定义控制台应用程序的入口点。/#include "stdio.h"#include "stdlib.h"#include "string.h"#include "iostream"using namespace std
17、;/ 词法分析程序/ 首先定义种别码/*第一类:标识符letter(letter | digit)*无穷集第二类:常数(digit)+ 无穷集第三类:保留字 (32)autobreakcasecharconstcontinuedefaultdodoubleelseenumexternfloatforgotoifintlongregister returnshortsignedsizeofstaticstructswitchtypedefunionunsignedvoidvolatilewhile第四类:界符 /*'、 / '、() "II1第五类:运算符 <、&
18、lt;=、>、>=、=、+、-、*、/、八、对所有可数符号进行编码:<$,0><auto,1><while,32><+,33><-,34><*,35></,36><<,37><<=,38><>,39><>=,40><=,41><=,42><!=,43><,44><(,45><),46><八,47><,48><",49&
19、gt;<',50><#,51><&,52><&&,53><|,54><|,55><%,56><,57><<<,58>左移<>>,59>右移<,60><,61><,62><,63><,64><.,65><?,66><:,67><!,68>"","","",&
20、quot;"<常数 99 ,数值 ><标识符 100 ,标识符指针 > */*/*/*查找保留字 */ 全局变量,保留字表static char reserveWord3220 = "auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", &qu
21、ot;enum", "extern", "float", "for", "goto", "if", "int", "long", "register", "return", "short", "signed", "sizeof", "static", "struct", "switch",
22、 "typedef", "union", "unsigned", "void", "volatile", "while"/ 界符运算符表 ,根据需要可以自行增加 static char operatorOrDelimiter3610 = +", "-", "*", "/", "<", "<=", ">", ">=&
23、quot;, "=", "=","!=", ";", "(", ")", "A", ",", """, "'", "#", "&","&&", "|", "|", "%", "", "<<&quo
24、t;, ">>", "", "", "", "", "", ".", "?", ":", "!"static char IDentifierTbl100050 = "" ;/ 标识符表*int searchReserve(char reserveWord20, char s) for (int i = 0; i < 32; i+)if (strcmp(rese
25、rveWordi, s) = 0)/ 若成功查找,则返回种别码return i + 1;/ 返回种别码return -1;/ 否则返回 -1,代表查找不成功,即为标识符*查找保留字 *判断是否为字母*bool IsLetter(char letter)/ 若为多行注释“ /*0 0 0*/ ”则去除该内容/ 注意 C 语言允许下划线也为标识符的一部分可以放在首部或其他地方if (letter >= 'a'&&letter <= 'z' | letter >= 'A'&&letter <= &
26、#39;Z'| letter='_') return true;elsereturn false;*判断是否为字母*判断是否为数字*bool IsDigit(char digit)if (digit >= '0'&&digit <= '9')return true;elsereturn false;*判断是否为数字*编译预处理,取出无用的字符和注释*void filterResource(char r, int pProject)char tempString10000;int count = 0;for (i
27、nt i = 0; i <= pProject; i+) if (ri = '/'&&ri + 1 = '/')/ 若为单行注释“ / ” ,则去除注释后面的东西,直至遇到回车换行while (ri != 'n')i+;/ 向后扫描if (ri = '/'&&ri + 1 = '*')i += 2;while (ri != '*' | ri + 1 != '/')i+;/ 继续扫描if (ri = '$')printf("
28、;注释出错,没有找到*/,程序结束! ! n");exit(0);i += 2;/ 跨过“ */ ”if (ri != 'n'&&ri != 't'&&ri != 'v'&&ri != 'r')/ 若出现无用字符,则过滤;否则加载 tempStringcount+ = ri;tempStringcount = '0'strcpy(r, tempString);/产生净化之后的源程序编译预处理,取出无用的字符和注释*/*分析子程序,算法核心 */void Sc
29、anner(int &syn, char resourceProject, char token, int &pProject) /根据DFA的状态转换图设计int i, count = 0;/count用来做token的指示器,收集有用字符char ch;/作为判断使用ch = resourceProjectpProject; while (ch = ' ')/ 过滤空格,防止程序因识别不了空格而结束pProject+;ch = resourceProjectpProject;for (i = 0; i<20; i+)/ 每次收集前先清零tokeni =
30、 '0'if (IsLetter(resourceProjectpProject)/ 开头为字母tokencount+ = resourceProjectpProject;/收集pProject+;/ 下移while (IsLetter(resourceProjectpProject) | IsDigit(resourceProjectpProject)/ 后跟字母或数字tokencount+ = resourceProjectpProject;/|攵集pProject+; 下移/ 多读了一个字符既是下次将要开始的指针位置tokencount = '0'syn
31、= searchReserve(reserveWord, token);/查表找至 U种别码if (syn = -1)/ 若不是保留字则是标识符syn = 100;/标识符种别码return;else if (IsDigit(resourceProjectpProject)/ 首字符为数字while (IsDigit(resourceProjectpProject)/ 后跟数字tokencount+ = resourceProjectpProject;/|攵集pProject+;/ 多读了一个字符既是下次将要开始的指针位置tokencount = '0'syn = 99;/常数
32、种别码else if (ch = '+' | ch = '-' | ch = '*' | ch = '/' | ch = '' | ch = '(' | ch = ')' | ch = 'A'| ch = ',' | ch = '"' | ch = ''' | ch = '' | ch = '#' | ch = '%' | ch = ''|
33、 ch = '' | ch = '' | ch = '' | ch = '' | ch = '.' | ch = '?' | ch = ':')/ 若为运算符或者界符,查表得到结果 token0 = resourceProjectpProject; token1 = '0'/ 形成单字符串 for (i = 0; i<36; i+) / 查运算符界符表if (strcmp(token, operatorOrDelimiteri) = 0)syn = 33 + i
34、;获得种别码,使用了一点技巧,使之呈线性映射break;/ 查到即推出pProject+;指针下移,为下一扫描做准备return;else if (resourceProjectpProject = '<')/<,<=,<<pProject+;后移,超前搜索if (resourceProjectpProject = '=')syn = 38;else if (resourceProjectpProject = '<')/ 左移pProject-; syn = 58;elsepProject-;syn = 37;
35、pProject+;指针下移 return;else if (resourceProjectpProject = '>') />,>=,>>pProject+;if (resourceProjectpProject = '=') syn = 40;else if (resourceProjectpProject = '>') syn = 59;else pProject-; syn = 39;pProject+; return;else if (resourceProjectpProject = '=&
36、#39;) /=.=pProject+;if (resourceProjectpProject = '=') syn = 42;else pProject-; syn = 41;pProject+; return;else if (resourceProjectpProject = '!') /!,!=pProject+;if (resourceProjectpProject = '=') syn = 43;else syn = 68; pProject-;pProject+;return;else if (resourceProjectpPro
37、ject = '&')/&,&&pProject+;if (resourceProjectpProject = '&')syn = 53;elsepProject-; syn = 52;pProject+;return;else if (resourceProjectpProject = '|')/|,|pProject+;if (resourceProjectpProject = '|')syn = 55;elsepProject-; syn = 54;pProject+;return;e
38、lse if (resourceProjectpProject = '$')/ 结束符syn = 0;/ 种别码为 0 else/ 不能被以上词法分析识别,则出错printf("error: there is no exist %c n", ch); exit(0);int main()/ 打开一个文件,读取其中的源程序char resourceProject10000;char token20 = 0 ;int syn = -1, i;/ 初始化int pProject = 0;/ 源程序指针FILE *fp, *fp1;if (fp = fopen(&q
39、uot;D:zyr_rc.txt", "r") = NULL)/ 打开源程序cout << "can't open this file" exit(0); resourceProjectpProject = fgetc(fp);while (resourceProjectpProject != '$')将源程序读入 resourceProject数组 pProject+;resourceProjectpProject = fgetc(fp); resourceProject+pProject = '0'fclose(fp);cout << endl << "源程序为 :" <<
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025版学校游泳池儿童游乐区设计与施工承包合同示范3篇
- 2025版土地使用权出让居间合同(新型合作模式)3篇
- 2025版城市住宅小区全面灭蟑螂服务合同4篇
- 2025版土地测绘保密协议:保密项目合作与技术支持合同3篇
- 乳粉产品质量法律规制与合规考核试卷
- 会展产业与数字经济的创新结合考核试卷
- 2025版十五年商业地产租赁合同范本15篇
- 2025版城市庆典活动委托演出合同3篇
- 2025年水土保持设施验收技术服务与生态修复实施合同3篇
- 2025年医疗设备使用及维护管理协议
- 南通市2025届高三第一次调研测试(一模)地理试卷(含答案 )
- 2025年上海市闵行区中考数学一模试卷
- 2025中国人民保险集团校园招聘高频重点提升(共500题)附带答案详解
- 重症患者家属沟通管理制度
- 碳排放管理员 (碳排放核查员) 理论知识考核要素细目表三级
- 2024年河北省中考数学试题(含答案解析)
- 小学二年级数学口算练习题1000道
- 纳布啡在产科及分娩镇痛的应用
- DZ/T 0462.4-2023 矿产资源“三率”指标要求 第4部分:铜等12种有色金属矿产(正式版)
- 化学-福建省龙岩市2024届高三下学期三月教学质量检测(一模)试题和答案
- 凸优化在经济学与金融学中的应用
评论
0/150
提交评论