文档供参考,可复制、编制,期待您的好评与关注! 黄冈师范学院提高型实验报告实验课题 简易C语言编译器(实验类型:□综合性 □设计性 □应用性)实验课程编译原理实验时间 2010 年12 月 19 日学生姓名 夏涛 专业班级网络200801学 号200826340124目 录一 、 设计题目 - 1 -二 、 运行环境 - 1 -三 、 算法设计的思想 - 1 -四 、 算法的流程图 - 3 -五 、 算法设计分析 - 6 -六 、 源代码 - 11 -七 、 运行结果分析 - 30 -八 、 收获及体会 - 32 -- 15 - / 17一 、 设计题目 简易C语言编译器二 、 运行环境Ø 硬件环境:奔腾Ⅳ处理器,主频2.0GHz;内存512M;硬盘80G以上;1024×768显示分辨率Ø 软件环境:Windows XP2;Visual C++6.0三 、 算法设计的思想编译程序的工作过程一般可以分为五个阶段:词法分析、语法分析、语义分析与中间代码产生、优化、目标代码生成每一个阶段在功能上是相对独立的,它一方面从上一个阶段获取分析的结果来进行分析,另一方面由将结果传递给下一个阶段。
由编译程序的五个阶段就对应了编译系统的结构其中词法分析器利用超前搜索、状态转换等方法,将源程序转化成为一个一个的单词符号二元式一般程序语言的单词符号包括关键字、运算符、常数、标识符和界符语法分析器将这些单词符号作为输入,对它进行语法分析语法分析分为两种方法:自上而下分析法和自下而上分析法针对不同程序语言的语法规则可以采取不同的分析方法,当然两种方法也可以同时使用语法分析器把语法单元作为输入供语义分析器使用一般的语义分析器主要采用的是语法制导方法,即在语法分析的同时进行语法分析,并产生一定的语义动作,来生成中间代码上面三个过程可以与硬件无关,而接下来的优化器和目标代码生成器是针对某一种处理器而言的代码优化是将语义分析生成的中间代码进行优化,产生执行效率更高的代码目标代码生成器最终生成可以在某种机器上运行的机器语言或者汇编语言在整个编译过程中还包括对表格的操作和对错误的处理,这些也都是非常重要的环节源程序下图给出了编译系统的结构框图:表格管理出错处理单词符号语法单元中间代码中间代码目标代码语法分析器语义分析与中间代码生成器优化器目标代码生成器词法分析器四 、 算法的流程图1、 词法分析:2、 语法分析:开始从词法输出中读入token序列,放入input初始化堆栈,并将’#’和’S’放入堆栈栈顶不为’#”是栈顶=get()是栈顶为终结符否是出栈get=getch()Get=getch()getch查分析表是否需要错误恢复否是错误恢复否否出栈,产生式逆序入栈,并输出产生式,结束3、 语义分析:五 、 算法设计分析1、 使用的数据结构和关键变量struct Stack { // 栈结构体: 序号、内容、连接下一结点指针 int num; char name; struct Stack *next;};struct Guiyue { // 规则集结构体:序号、规则长度、符号、连接下一结点指针 int num; int count; char name; struct Guiyue *next;};struct Relation { // 分析表结构体:状态序号、对应符号列、操作类型的对应序号、操作类型、连接下一结点指针 int line_States ; char rank_Letter; int relationship; char name; struct Relation *next;};struct Sign { // 符号表结构体: 自变量名、标识类型、连接下一结点指针 char name[20]; char kind; struct Sign *next;};struct Word { // 单词表结构体: 单词名字、标识类型、状态、序号、行号、连接符号表指针、连接下一结点指针 char name[20]; char mark_name; int state; int num; int line; struct Sign *link; struct Word *next;};FILE *fp1, fp2; // 文件指针int row = 1; // 字符行变量int line[10000], Lin[300]; // 字符行int w_num; // 单词所在行、字符数char buffer[10000]; // 字符串缓冲区struct Word *head,*find; // 单词表结构体头指针struct Relation *r_head; // 分析表结构体头指针struct Guiyue *g_head; // 规约集结构体头指针struct Stack *s_head; // 栈结构体头指针2、 用到的LR文法[Terminator] m v ( ) { } i = ; f e w a b c d , & | < > # @ + - * / n[NonTerminator] B Q S A C X Y Z E H G L I K T F[Starter] B[Precept]00、B->Q01、Q->v m ( ) { A }02、S->C ; S03、A->S A04、A->S05、C->C ; X06、C->X07、X->Y Z08、Y->a09、Y->b10、Y->c11、Y->d12、Z->i , i13、Z->i14、S->f ( E ) { A } e { A }15、S->w ( E ) { A }16、S->i = L ;17、E->E & H18、E->H19、H->H | G20、H->G21、G->i < i22、G->i > i23、G->i # i24、G->i @ i25、G->( E )26、G->! E27、G->i28、L->L + I29、L->I30、I->I - K31、I->K32、K->K / T33、K->K34、T->T * F35、T->F36、F->( L )37、F->n38、F->i3、 主要功能函数简述以下是实现的主要功能函数的信息简述,具体实现请参看六、源代码int judge(char ch) 功能:接收ch判断字符,变量flag返回字符类别void scan() 功能:扫描输入源文件,并生成单词种别码struct Word *InitWord()功能:包括分割单词、标识单词、生成变量符号表、完善单词属性表int ResultAnely(Relation* r_head,Stack *s_head, char str[], Guiyue *g_head, int cal)功能:词法分析函数int ResultAnely(Relation *r_head,Stack *s_head,char str[],Guiyue *g_head,int cal)功能:语法分析函数void ProduceStyle(char str[], int order_num)功能:算术表达式四元式函数void BoolStyle(char str[], int order_num)功能:布尔表达式四元式函数void FourStyle(int goon, Word *head)功能:显示四元式函数Stack *MarkPush(Stack *ip,char mark,int I_i)功能:进栈void MarkPop(Stack *ip)功能:出栈void FindWordDeclare(Word *head)功能:正确性检测函数,查找保留字是否被声名和符号是否对称Relation *FirstRelation()功能:初始化分析表函数Guiyue *FirstGuiyue()功能:初始化规则表函数六 、 源代码(部分)由于此次实验中所用全部代码量太多,在此只列出主要的功能模块(函数)的代码以做基本概要的说明:int judge(char ch)// 接收ch判断字符,变量flag返回字符类别{ int flag; if(ch=='!'||ch=='$'||ch=='&'||ch=='*'||ch=='('||ch==')'||ch=='-'||ch=='_'|| ch=='+'||ch=='='||ch=='|'||ch=='{'||ch=='}'||ch=='['||ch==']'||ch==';'|| ch==':'||ch=='"'||ch=='<'||ch==','||ch=='>'||ch=='.'||ch=='/'||ch=='\'') flag=1; else if('0'<=ch&&ch<='9') flag=2; else if(('a'<=ch&&ch<='z')||('A'<=ch&&ch<='Z')) flag=3; else if(ch==' ') flag=4; else if(ch=='\n') flag=5; else if(ch=='?') flag=6; else if(feof(fp1)) flag=7;//结束 else flag=0; //illegal character return(flag);}void scan(){ char ch; int flag,j=0,i=-1; while(!feof(fp1)) { ch=fgetc(fp1); flag=judge(ch); printf("%c",ch);//显示打开的文件 if(flag==1||flag==2||flag==3) {i++;buffer[i]=ch;line[i]=row;} else if(flag==4) {i++;buffer[i]='?';line[i]=row;} else if(flag==5) {i++;buffer[i]='~';row++;} else if(flag==7) continue; else cout<<"\n请注意,第"<mark_name=='i'){ w_name[cal]=find; cal++; } if(find->next!=NULL){ if((find->mark_name==find->next->mark_name)&&(find->mark_name!='{')&& (find->mark_name!='}')&&(find->mark_name!='(')&&(find->mark_name!=')')) cout<<"第 "<line<<" 行,‘ "<mark_name<<" ’存在字符重复错误 !"<mark_name=='i'&&find->next->mark_name=='}')||(find->mark_name==','&&find->next->mark_name=='}')|| (find->mark_name==','&&find->next->mark_name==';')||(find->mark_name==';'&&find->next->mark_name==',')|| (find->mark_name=='('&&find->next->mark_name==',')||(find->mark_name==','&&find->next->mark_name=='(')|| (find->mark_name==')'&&find->next->mark_name==';')||(find->mark_name==')'&&find->next->mark_name==',')|| (find->mark_name==')'&&find->next->mark_name=='}')){ cout<<"第 "<line<<" 行,"<name<<" 处存在符号连接错误 !"<mark_name=='a'||find->mark_name=='b'||find->mark_name=='c'||find->mark_name=='d')&& (find->next->mark_name=='}'||find->next->mark_name=='{'||find->next->mark_name==','|| find->next->mark_name==';'||find->next->mark_name=='('||find->next->mark_name==')'|| find->next->mark_name=='+'||find->next->mark_name=='-'||find->next->mark_name=='*'|| find->next->mark_name=='/'||find->next->mark_name=='&'||find->next->mark_name=='>'|| find->next->mark_name=='<'||find->next->mark_name=='='||find->next->mark_name=='!'|| find->next->mark_name=='@'||find->next->mark_name=='n')) cout<<"第 "<line<<" 行,‘ "<mark_name<<" ’存在自变量声明搭配错误 !"<mark_name=='('||find->mark_name==')'||find->mark_name=='{'||find->mark_name=='}'){ word_fu[ca]=find; ca++; } if(find->name[0]>='0'&&find->name[0]<='9'&&find->name[1]>='a'&&find->name[1]<='z') cout<<"第 "<line<<" 行, "<name<<" 存在变量声明错误 !"<next; } int j=0; for(i=0;ilink; end=1; while(s_first&&end){ if(strcmp(s_first->name,w_name[i]->name)==0) end=0; else s_first=s_first->next; } if(end==1&&i!=cal-1) cout<<"错误 ! 第 "<line<<" 行,变量 "<name<<" 没有被声明 !"<name='$'; for(i=0;imark_name=='(')||(word_fu[i]->mark_name=='{')) ip=MarkPush(ip,word_fu[i]->mark_name,i); else if((ip->name=='('&&word_fu[i]->mark_name==')')||(ip->name=='{'&&word_fu[i]->mark_name=='}')) MarkPop(ip); else cout<<"错误 ! 第 "<line<<" 行,“ "<name<<" ” 存在符号匹配错误 ! "<name!='$') cout<<"错误 ! 第 "<line<<" 行,“ "<name<<" ” 存在符号匹配错误 !"<
到今天为止,作为实验主体的程序已经做的差不多了中间虽然有所困难,有所艰辛,但终究突破重重阻拦,有了一个结果,还是有那么一点欣慰通过这次课程设计,不但加深了我对课本知识的理解和掌握,明白了编译程序的基本实现过程,而且也训练我们分析问题,解决问题的能力以及对程序设计环境的进一步的熟悉。