第一篇:《编译原理》课程(词法分析)实验报告
一.实验序号:《编译原理》第一次实验
二.实验题目:词法分析
三.实验日期:2010.10
四.实验环境(操作系统,开发语言)
操作系统:Windows
开发语言:C
五.实验内容(实验要求)
a)将标识符的词法改为“以大写字母或小写字母开头,后面可以跟大写字
母或小写字母或数字或下划线”。
b)将<条件>中的表示相等关系的单词“=”改为“= =”
c)将原来的无小数的数改为可以有小数的数
六.实验步骤
a)打开VC++,找到getsym()项目。
int getsym()
{...}
在getsym()函数中设置断点,F10逐过程调试
根据要求a修改为
if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')
往后面看,修改while(ch>='a' && ch<='z' || ch>='0' && ch<='9' ||ch>='A' && ch<='Z' || ch=='_');
b)在检测赋值符号的程序段中找到等号 = 的判断代码,改变成为 = = 即
可。
c)在获取整数数字的值的程序段后面添加判断小数点的代码。如果是,即
读取符号并且按照小数的要求将其缩小并且累加到总的符号串中。
七.实验体会(包括收获、心得体会、存在的问题及解决问题的方法、建议等)
通过实验,如果要修改代码的话,首先应该读懂源码,在修改之前了解到程序段的功能是什么,然后再在相应的行进行修改添加,再进行合理的调试。如果问题太过困难可以查询资料或与同学进行讨论
八.实验结果(关键源程序)
a)
int getsym()
{
int i,j,k;
while(ch==' '||ch==10||ch==9)/*忽略空格,换行和TAB*/{
getchdo;
}
if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')/*名字或保留字以a..zA。Z开头*/{
k=0;
do{
if(k { a[k]=ch; k++; } getchdo; }while(ch>='a' && ch<='z' || ch>='0' && ch<='9' || ch>='A' && ch<='Z' || ch=='_');// if(ch>='0'&&ch<='9')/*检测是否为数字,以0..9开头*/{ k=0; num=0; sym=number; do{ //435 num=10*num+ch-'0'; k++; getchdo; }while(ch>='0' && ch<='9'); if(ch=='.') { k++; sym=period; getchdo; sym=number; int div=10; do{num=num+(ch-'0')/div; k++; getchdo; div=div*10; }while(ch>='0'&&ch<='9'); } b) else { if(ch=='>')//检测大于或大于等于符号{ getchdo; if(ch=='=')//add by M { sym=geq;//构成>= getchdo; } else { sym=gtr;//否则就是一个单独的>号} } else { if(ch=='=') { getchdo; if(ch=='=') { sym=deq; getchdo; } else { sym=eql; } } c)else {if(ch == ’.’) {k=10; getchdo; do{num=num+(ch-'0')/k; k=k*10; getchdo; }while(ch>='0'&&ch<='9');} } 编译原理实验报告 报告完成日期 2018.5.30 一. 组内分工与贡献介绍 二. 系统功能概述; 我们使用了自动生成系统来完成我们的实验内容。我们设计的系统在完成了实验基本要求的前提下,进行了一部分的扩展。增加了声明变量类型、类型赋值判定和声明的变量被引用时作用域的判断。从而使得我们的实验结果呈现的更加清晰和易懂。 三. 分系统报告; 一、词法分析子系统 词法的正规式: 标识符 <字母>(<字母>|<数字字符>)* 十进制整数 0 |(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)* 八进制整数 0(1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)* 十六进制整数 0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)* 运算符和分隔符 +| * | / | > | < | = |(|)| <=|>=|==; 对于标识符和关键字: A5—〉 B5C5 B5—〉a | b |⋯⋯| y | z C5—〉(a | b |⋯⋯| y | z |0|1|2|3|4|5|6|7|8|9)C5|ε 综上正规文法为: S—〉I1|I2|I3|A4|A5 I1—〉0|A1 A1—〉B1C1|ε C1—〉E1D1|ε D1—〉E1C1|ε E1—〉0|1|2|3|4|5|6|7|8|9 B1—〉1|2|3|4|5|6|7|8|9 I2—〉0A2 A2—〉0|B2 B2—〉C2D2 D2—〉F2E2|ε E2—〉F2D2|ε C2—〉1|2|3|4|5|6|7 F2—〉0|1|2|3|4|5|6|7 I3—〉0xA3 A3—〉B3C3 B3—〉0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f C3—〉(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)|C3|ε A4—〉+ |-| * | / | > | < | = |(|)| <=|>=|==; A5—〉 B5C5 B5—〉a | b |⋯⋯| y | z C5—〉(a | b |⋯⋯| y | z |0|1|2|3|4|5|6|7|8|9)C5|ε 状态图 流程图: 词法分析程序的主要数据结构与算法 考虑到报告的整洁性和整体观感,此处我们仅展示主要的程序代码和算法,具体的全部代码将在整体的压缩包中一并呈现 另外我们考虑到后续实验中,如果在bison语法树生成的时候推不出目标的产生式时,我们设计了报错提示,在这个词的位置出现错误提示,将记录切割出来的词在code.txt中保存,并记录他们的位置。 以下是我们的主要代码: 进制的识别: 结果展示: 二、语法分析子系统 根据选择的语法分析方法进行描述 我们使用了递归子程序发,并且对原有的产生式进行了改写,改写后的结果如下: P→LP1|L L→S S→id=E|{P}|if C then S | if C then S 1else S2 | while C do S1 C→E1C’ C’→>E2| E→int8E’| int10E’| int16E’| idE’|T E’→+T|-T||+TE’|-TE’ T→int8T’| int10T’| int16T’| idT’|F T’→*F|/F|*FT’|/FT’ F→(E)|int8|int10|int16|id 简化的语法图: S的语法图: C的语法图: E的语法图: T的语法图: F的语法图: 流程图: 语法分析子系统的主要数据结构与算法 我们采用了自动生成技术,同样在这里也是展示主要的核心功能代码,全部的代码展示在压缩包中: 我们在设计时,实现了产生式对应的字符串同时标识产生式定义的int值 辅助程序: 生成语法树的程序: 1.树节点: 2.创建新节点 3.创建实数类型新节点 4.创建标识符类型新节点 5.输出语法树 三、三地址码生成器 算法的基本思想: 我们增加了声明变量类型、类型赋值判定和声明的变量被引用时作用域的判断。从而使得我们的实验结果呈现的更加清晰和易懂。 在报错的时候,我们会呈现类型、作用域和赋值三种的问题的报错信息。 流程图: 算法展示: 四、实验体会 这次实验其实总的来说是让我们更加清晰的理解到了我们所学的内容。有时候我们上课听讲,课下复习写作业的时候,其实看似掌握了所学内容,但实际上并没有亲身体会的操作很难让我们深刻的理解其中的相关意义。通过这次实验,我们能够从根源处了解到了我们所学的内容,并且基于我们理解之后的输出。比如词法分析不能采用空格来区分单词,因为存在加减乘除等运算符和分隔符,使用空格来区分可能会造成错误的分解。又比如我们再在程序设计中,常常体会到效率的重要性。影响词法分析的效率的主要因素是各个状态的分支如何规划。如果每个进来的单词都能在最短的时间和最少的匹配次数内找到其入口,则效率将得到很大程度上的提高。所以由此我们产生了声明变量类型、赋值和作用域的想法,将其放在最后来进行判断,这样可以提高整体的执行效率。 另外,这次小组成员彼此不在一个班级,这样从某一方面来说,也加强了我们互相快速熟识并团结协作的能力,有了这种体验,我想我们在今后的生活中,面对这种情况的时候,将会变得更加有经验。 五、源程序 词法分析器: 输入结果: 输出结果: 语义分析结果: 输入: 第二组数据的输入: 输出: 三地址码的输入: 第二组数据的输入: 输出: 201X-201X学年第x学期 《编译原理》课程设计报告 院 系: 计算机科学与技术 班 级: XX级XX 班 学生姓名: XXXXXX 学 号: XXXXXXXX 指导老师: XXXXXX 计算机科学与技术学院监制 20XX年X月 目录 1.课程设计的目的 2.课程设计的内容和要求 3.问题分析和相关知识介绍 4.设计思路和关键问题及其解决方案 5.测试和结果分析 6.总结和心得体会 附件1:参考文献 附件2:核心源代码 1.课程设计的目的(1)编写词法分析器 (2)加深对词法分析器工作原理的了解和认识 2.课程设计的内容和要求 编写词法分析器,词法分析器能够识别关系算符,词法分析器能够识别标识符和关键字,词法分析器能够识别无符号数。 3.问题分析和相关知识介绍 构成词法分析器的一种简单方法是用状态转换图来描述源语言词法记号的结构,然后手工把这种状态转换图翻译成为识别词法记号的程序。词法分析器的任务是把构成源程序的字符流翻译成词法记号流。 4.设计思路和关键问题及其解决方案 把自然语言构造成正规式,把正规式构造成有限自动机NFA,然后根据子集构造法把有限自动机构造成无限自动机DFA,根据极小化DFA状态数算法把DFA构造成最简DFA,其次根据最简DFA画出转换表,根据转换表画出装换图,最后根据装换图就可以编写词法分析器。 5.测试和结果分析 6.总结和心得体会 通过本次试验,不仅仅是我学会了C#基础知识,而且还是我对词法分析器有了更深入的认识,虽然在编写词法分析器过程中遇到了很多困难,例如:C#语言不熟悉,对此法分析器的工作原理分析的不透彻,但在老师和同学的帮助下,我有了很大的提高,通过不断的努力最终顺利的完成了课程设计,很感谢帮助我的XX同学和XX老师。附件1:参考文献 《编译原理(第2版)》 高等教育出版社; 《C#程序设计及应用教程(第2版)》 人民教育出版社。附件2: 1.Code文档截图 2.程序源代码 using System;using System.Collections.Generic;using System.Text;using System.IO; namespace LexicalAnalysis { class Program { static string[] keys = { “static”, “true”, “return”, “string”, “Length”, “break”, “Console”, “WriteLine”, “bool”, “false”, “ture”, “void”, “if”, “else”, “while”, “int”, “float”, “for”, “enum”, “default”, “case”, “double”, “do” }; static List static List static List static List static List //数字,标识符,空白,关系符,运算符 static void Main(string[] args){ string[] date = File.ReadAllLines(@“d:code.txt”);//路径,并存入data for(int i = 0;i < date.Length;i++){ Console.WriteLine(“第” +(i + 1)+ “行code: ” + date.GetValue(i));analysisByLine(date[i]); } //分别输出存储在四个List中的String Console.WriteLine(“关键字,输入回车”);//输出所有的关键字 Console.ReadLine(); foreach(string id in key){ Console.WriteLine(id); } Console.WriteLine(“标识符,输入回车”);//输出所有的标识符 Console.ReadLine();foreach(string id in bsf){ Console.WriteLine(id); } Console.WriteLine(“数字,输入回车”);Console.ReadLine();foreach(string id in sz){ Console.WriteLine(id); } Console.WriteLine(“关系运算符,输入回车”);Console.ReadLine();foreach(string id in gx){ Console.WriteLine(id); } Console.WriteLine(“算数运算符,输入回车”);Console.ReadLine();foreach(string id in ys){ Console.WriteLine(id); } Console.WriteLine(“输入回车退出”); Console.ReadLine(); } static void analysisByLine(string code) //输出所有的数字 //输出所有的关系运算符//输出所有的算数运算符 { char a = ' ';string temp = “";int j = 0;while(j < code.Length){ a = code[j];temp = ”“;if(Char.IsLetter(a)|| a == '_')//是否为标识符 { temp = temp + a.ToString();j++;a = code[j];while(Char.IsLetterOrDigit(a)){ temp = temp + a.ToString();j++;a = code[j];} if(isKey(temp)){ //Console.WriteLine(”保留字:“+temp); if(!key.Contains(temp)){ // Console.WriteLine(”添加成功“);key.Add(temp);} } else { //Console.WriteLine(”标识符:“+temp); if(!bsf.Contains(temp)){ //Console.WriteLine(”添加成功标识符==“);bsf.Add(temp);} } } else if(Char.IsDigit(a)){ temp = temp + a.ToString();j++;a = code[j];while(Char.IsDigit(a)){ temp = temp + a.ToString();j++;a = code[j]; } //判断是否是小数 if(a.Equals('.')){ temp = temp + a.ToString();j++;a = code[j];while(Char.IsDigit(a)){ temp = temp + a.ToString();j++;a = code[j];} //判读是否是科学记数法 if(a.Equals('E')|| a.Equals('e')){ temp = temp + a.ToString();j++;a = code[j];while(Char.IsDigit(a)){ temp = temp + a.ToString();j++;a = code[j];} } } // Console.WriteLine(”数字:“+temp);if(!sz.Contains(temp)){ //Console.WriteLine(”添加成功标识符==“);sz.Add(temp);} } else if(a == '<'){ temp = temp + a.ToString();j++;a = code[j];if(a == '='){ temp = temp + a.ToString();j++;a = code[j];} else if(a == '>'){ temp = temp + a.ToString();j++;a = code[j];} //Console.WriteLine(”关系符“+temp);if(!gx.Contains(temp)){ //Console.WriteLine(”添加成功标识符==“);gx.Add(temp);} } else if(a == '='){ temp = temp + a.ToString();j++; a = code[j];// Console.WriteLine(”关系符“+temp);if(!gx.Contains(temp)){ //Console.WriteLine(”添加成功关系==“);gx.Add(temp);} } else if(a == '>'){ temp = temp + a.ToString();j++;a = code[j];if(a == '='){ temp = temp + a.ToString();j++;a = code[j];} // Console.WriteLine(”关系符“+temp);if(!gx.Contains(temp)){ //Console.WriteLine(”添加成功标识符==“);gx.Add(temp);} } else { if(a == '+' || a == '-' || a == '/' || a == '*'){ temp = temp + a.ToString();j++;a = code[j];//Console.WriteLine(”运算符“+temp);if(!ys.Contains(temp)){ //Console.WriteLine(”添加成功标识符==“);ys.Add(temp);} } else { j++;} } } } //判断是不是保留字的IsKey方法 static bool isKey(string key){ bool flag = false;for(int i = 0;i < keys.Length;i++) if(keys[i] == key){ flag = true;//Console.WriteLine(key+”是不是key“+flag);break;} else { flag = false; } //Console.WriteLine(key+”是不是key“);// Console.WriteLine(flag+”是不是key");return flag; } } } 实验2:语法分析 1.实验题目和要求 题目:语法分析程序的设计与实现。 实验内容:编写语法分析程序,实现对算术表达式的语法分析。要求所分析算术表达式由如下的文法产生。 EET|ET|TTT*F|T/F|F Fid|(E)|num实验要求:在对输入表达式进行分析的过程中,输出所采用的产生式。方法1:编写递归调用程序实现自顶向下的分析。方法2:编写LL(1)语法分析程序,要求如下。 (1)编程实现算法4.2,为给定文法自动构造预测分析表。(2)编程实现算法4.1,构造LL(1)预测分析程序。 方法3:编写语法分析程序实现自底向上的分析,要求如下。(1)构造识别所有活前缀的DFA。(2)构造LR分析表。 (3)编程实现算法4.3,构造LR分析程序。 方法4:利用YACC自动生成语法分析程序,调用LEX自动生成的词法分析程序。实现(采用方法1) 1.1.步骤: 1)对文法消除左递归 ETE'E'TE'|TE'|TFT'T'*FT'|/FT'|Fid|(E)|num 2)画出状态转换图 化简得: 3)源程序 在程序中I表示id N表示num 1.2.例子: a)例子1 输入:I+(N*N)输出: b)例子2 输入:I-NN 输出: 编译原理教学大纲2001,9 周次课内学时课内安排(讲授内容)建议课外安排备注 12编译原理概述阅读PL/0程序文本 24介绍PL/0编译程序阅读PL/0程序文本 32词法分析程序自动构造阅读PL/0程序文本 (正规式,有穷自动机) 44(2)词法分析程序自动构造练习题 Lex(Flex)介绍,布置PP1实践题一PP1 52文法和语言练习题 64自顶向下语法分析练习题提交PP1LL(1)文法 72自底向上语法分析练习题 LR文法 84LR分析练习题 期中考试 92Yacc介绍,布置PP2实践题一PP2 104习题课 语法分析方法比较提交PP2 112语法制导翻译,布置PP3实践题一PP3 124语法制导翻译 运行时存储组织提交PP3 132运行时存储组织练习题144代码优化, 布置PP4实践题一PP4 152代码生成164实践题目总结答辩 习题课 附1 实践题目(从中选一) 实践题一 Deacf编译程序的设计和实现.实践题二Pl/0编译程序扩充,用Lex和 Yacc实现一个小解释器.实践题三 java实现的Mini-Triangle编译程序.(限少数同学选,在第四周作选题报告)附2 课程评分 1课堂小测验,作业抽查 10%期中考试20% 3实践题一 40% 实践题二20% 实践题三 50% 4期末考试 完成实践题一 30% 完成实践题二50% 完成实践题三 20%第二篇:编译原理实验报告
第三篇:《编译原理》课程设计报告--词法分析器
第四篇:编译原理语法分析实验报告
第五篇:编译原理课程-教学计划