当前位置:网站首页 > 公文范文 > 主题教育 > 《编译原理》课程实验报告

《编译原理》课程实验报告

时间:2022-04-09 14:24:59 浏览次数:

《编译原理》课程实验报告 题 目:
词法分析器实验 专 业:
计算机科学与技术 班 级:
1班 学 号:
* * * ***** 姓 名:
* * * 一、实验目的 通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地运用。

二、实验内容及要求 用VC++/VB/JAVA语言实现对C语言子集的源程序进行词法分析。通过输入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的内部编码及单词符号自身值;
若遇到错误则显示“Error”,然后跳过错误部分继续显示 ;
同时进行标识符登记符号表的管理。

以下是实现词法分析设计的主要工作:
(1)从源程序文件中读入字符。

(2)统计行数和列数用于错误单词的定位。

(3)删除空格类字符,包括回车、制表符空格。

(4)按拼写单词,并用(内码,属性)二元式表示。(属性值——token的机内表示) (5)如果发现错误则报告出错 (6)根据需要是否填写标识符表供以后各阶段使用。

单词的基本分类:
u 关键字:由程序语言定义的具有固定意义的标识符。也称为保留字例如 if、 for、while、printf ;

单词种别码为1。

u 标识符:用以表示各种名字,如变量名、数组名、函数名;

u 常数:
任何数值常数。如 125, 1,0.5,3.1416;

u 运算符:+、-、*、/;

u 关系运算符:
<、<=、= 、>、>=、<>;

u 分界符:

、,、(、)、[、];

三、实验程序设计说明 1.实验方案设计 1、主程序设计考虑:
u 程序的说明部分为各种表格和变量安排空间。

在具体实现时,将各类单词设计成结构和长度均相同的形式,较短的关键字后面补空。

k数组------关键字表,每个数组元素存放一个关键字(事先构造好关键字表)。

s 数组------存放分界符表(可事先构造好分界符表)。为了简单起见,分界符、算术运算符和关系运算符都放在s表中(编程时,应建立算术运算符表和关系运算符表,并且各有类号),合并成一类。

id 和ci 数组分别存放标识符和常数。

instring 数组为输入源程序的单词缓存。

outtoken 记录为输出内部表示缓存。

还有一些为造表填表设置的变量。

u 主程序开始后,先以人工方式输入关键字,造k表;
再输入分界符等造 p 表。

u 主程序的工作部分设计成便于调试的循环结构。每个循环处理一个单词;
接收键盘上送来的一个单词;
调用词法分析过程;
输出每个单词的内部码。

例如,把每一单词设计成如下形式: (type,pointer) 其中type指明单词的种类,例如:Pointer指向本单词存放处的开始位置。

还有一些为造表填表设置的变量。

u 主程序开始后,先以人工方式输入关键字,造k表;
再输入分界符等造 p 表。

u 主程序的工作部分设计成便于调试的循环结构。每个循环处理一个单词;
接收键盘上送来的一个单词;
调用词法分析过程;
输出每个单词的内部码。

例如,把每一单词设计成如下形式: (type,pointer) 其中type指明单词的种类,例如:Pointer指向本单词存放处的开始位置。

词法分析设计流程图 2、词法分析过程考虑 u 根据输入单词的第一个字符(有时还需读第二个字符), 判断单词类,产生类号:以字符k表示关键字;
id表示标识符;

ci表示常数;
s 表示分界符。

u 对于标识符和常数,需分别与标识符表和常数表中已登记的元素相比较,如表中已有该元素,则记录其在表中的位置,如未出现过,将标识符按顺序填入数组 id 中,将常数变为二进制形式存入数组中 ci 中,并记录其在表中的位置。

lexical 过程中嵌有两个小过程:一个名为 getchar,其功能为从 instring 中按顺序取出一个字符,并将其指针 pint 加 1 ;
另一个名为 error,当出现错误时,调用这个过程,输出错误编号。

u 要求:所有识别出的单词都用两个字节的等长表示,称为内部码。第一个字节为 t ,第二个字节为 i 。

t 为单词的种类。关键字的 t=1;
分界符的 t=2;
算术运算符的 t=3;
关系运算符的 t=4;
无符号数的 t=5;
标识符的 t=6。i 为该单词在各自表中的指针或内部码值。表 1 为关键字表;
表 2 为分界符表;
表 3 为算术运算符的 i 值;
表 4 为关系运算符的 i 值。

取字符和统计字符行列位置子程序 2.程序源代码 #include<iostream> #include<iomanip> #include<fstream> #include<string> using namespace std; #define MAX 50 char ch =' '; string keyword[50]={“bool“,“break“,“case“,“include“,“char“,“const“, “continue“, “default“, “do“,“double“,“else“,“false“, “float“,“for“,“if“,“int“,“long“, “namespace“,“new“,“return“, “short“,“signed“,“struct“,“switch“,“true“,“using“,“void“,“while“ ,“then“ }; int gjz(string c){ int i; for(i=0;i<MAX;i++) { if(keyword[i].compare(c)==0) return 1; } return 0; } int zm(char c) { if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1; else return 0; } int num(char c){ if(c>='0'&&c<='9') return 1; else return 0; } void caculate(FILE *fpin){ ofstream out(“mytest.txt“,ios::out); string arr=““; while((ch=fgetc(fpin))!=EOF) { arr=““; if(ch==' '||ch=='\t'||ch=='\n'){} else if(zm(ch)){ while(zm(ch)||num(ch)) { arr=arr+ch; ch=fgetc(fpin); } fseek(fpin,-1L,SEEK_CUR); if (gjz(arr)){out<<arr<<“\t1“<<“\t关键字“<<endl; } else out<<arr<<“\t2“<<“\t标识符“<<endl; } else if(num(ch)){ while(num(ch)||ch=='.'&&num(fgetc(fpin))||fgetc(fpin)=='e'||ch=='e') { if(ch=='.') fseek(fpin,-1L,SEEK_CUR); arr=arr+ch; if(ch=='e') { ch=fgetc(fpin); if( ch=='+') arr+='+'; else {arr+='-', fseek(fpin,-1L,SEEK_CUR);}; } ch=fgetc(fpin); } fseek(fpin,-3L,SEEK_CUR); out<<arr<<“\t3“<<“\t无符号数“<<endl; } else switch(ch){ case'+': case'-' : case'*' : case'=' : case'/' :out<<ch<<“ \t4“<<“\t运算符“<<endl;break; case'(' : case')' : case'[' : case']' : case';' : case'#' : case'.' : case',' : case'{' : case'}' :out<<ch<<“ \t5“<<“\t界限符“<<endl;break; case '“':{ string string1=““; do { string1+=ch; ch=fgetc(fpin); } while (ch!='“'); string1+=ch; out<<string1<<“\t6“<<“\t字符串“<<endl; }break; case':' :{ch=fgetc(fpin); if(ch=='=') out<<“:=“<<“ \t4“<<“\t运算符“<<endl; else {out<<“=“<<“ \t4“<<“\t运算符“<<endl;; fseek(fpin,-1L,SEEK_CUR);} }break; case'<' :{ch=fgetc(fpin); if(ch=='=')out<<“<=“<<“ \t4“<<“\t运算符“<<endl; if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))) { fseek(fpin,-1L,SEEK_CUR); out<<“<“<<“ \t5“<<“\t界限符“<<endl;} else if(ch=='<')out<<“<<“<<“ \t7“<<“\t控制符“<<endl; else if(ch=='>') out<<“<>“<<“ \t4“<<“\t运算符“<<endl; else{out<<“<“<<“ \t4“<<“\t运算符“<<endl; fseek(fpin,-1L,SEEK_CUR);} }break; case'>' :{ch=fgetc(fpin); if(ch=='=') out<<“>=“<<“ \t4“<<“\t运算符“<<endl; if(ch=='>')out<<“>>“<<“ \t7“<<“\t控制符“<<endl; if(ch=='\n'){fseek(fpin,-1L,SEEK_CUR); out<<“>“<<“ \t5“<<“\t界限符“<<endl;} else {out<<“>“<<“ \t4“<<“\t运算符“<<endl; fseek(fpin,-1L,SEEK_CUR);} }break; default : out<<ch<<“ \t无法识别字符“<<endl; } } } void read(){ ifstream in(“mytest.txt“,ios::out); string x; while(in) {in>>x;cout<<x<<'\t';in>>x; cout.width(20);cout<<x<<'\t';in>>x; cout.width(20);cout<<x<<endl;} } void main(){ char in_fn[30]; FILE * fpin; cout<<“请输入源文件名(包括路径和后缀名):“; for(;;){ cin>>in_fn; if((fpin=fopen(in_fn,“r“))!=NULL) break; else cout<<“文件路径错误!请输入源文件名(包括路径和后缀名):“; } cout<<“\n********************词法分析工作如下*********************“<<endl; caculate(fpin); fclose(fpin); cout<<endl; read(); cout<<“\n********************参看本目录下的mytest.txt*********************“<<endl; system(“pause“); } 3.程序的执行结果 图 1 程序输入文件内容 图 2 输出结果 4.实验程序的优点和特色 本程序特色:
出错处理能力强,任何非法字符输入,将会报错。比如:31fd 此字符串可定为错误,并将之输出警告;
当/*出现时,后必跟*/,当无此收尾时,自/*以下全部按错误处理,并警告。

四、实验中出现的问题及解决方法 /*注释符后,不跟*/,发生了死循环,后经检查修改,将错误去除;
/*后跟不连续的*/,即12*34/56*/时,出现了后面从3处再次读取判断的情况,经修改改正 五、体会、意见或建议 C语言好学但学好难!同时,了解了词法分析程序的设计方法,以及编译程序,编译时第一步要做的内容及方法。

华dong交大理工学院

推荐访问:

猜你喜欢