语法制导翻译与生成中间代码附代码
- 格式:doc
- 大小:163.50 KB
- 文档页数:13
编译方法实验报告2011年10月一、实验目的熟悉算术表达式的语法分析与中间代码生成原理。
二、实验内容(1)设计语法制导翻译生成表达式的四元式的算法;(2)编写代码并上机调试运行通过。
输入——算术表达式;输出——语法分析结果;相应的四元式序列。
(3)设计LL(1)分析法或LR(0)分析法的属性翻译文法, 并根据这些属性翻译文法, 使用扩展的语法分析器实现语法制导翻译。
三、实验原理及基本步骤●算术表达式文法:G(E): E ( E ω0 T | TT →T ω1 F | FF → i | (E)●文法变换:G’(E) E →T {ω0 T}T →F {ω1 F}F → i | (E)●属性翻译文法:E →T {ω0“push(SYN, w)” T “QUAT”}T →F {ω1“push(SYN, w)” F “QUAT”}F →i “push(SEM, entry(w))” | (E)其中:push(SYN, w) —当前单词w入算符栈SYN;push(SEM, entry(w)) —当前w在符号表中的入口值压入语义栈SEM;QUAT —生成四元式函数i. T = newtemp;ii. QT[j] =( SYN[k], SEM[s-1], SEM[s], T);j++;iii. pop( SYN, _ ); pop( SEM, _ ); pop( SEM, _ );push( SEM, T );●递归下降子程序:数据结构: SYN —算符栈;SEM —语义栈;四、数据结构设计使用递归的结构进行四元式的设计, 同时, 运用堆栈结构将四元式的输出序列打印出来while ( exp[i]=='+' || exp[i]=='-'){syn[++i_syn]=exp[i]; //push(SYN,w)i++; //read(w)T();quat();}while ( exp[i]=='*' || exp[i]=='/'){syn[++i_syn]=exp[i]; //push(SYN,w)i++; //read(w)F();quat();}void quat(){strcpy(qt[j],"(, , , )"); //QT[j]:=(SYN[k],SEM[s-1],SEM[s],temp);qt[j][1]=syn[i_syn];qt[j][3]=sem[i_sem-1];qt[j][5]=sem[i_sem];qt[j][7]=temp;j++;i_syn--; //pop(SYN);i_sem--; //pop(SEM);i_sem--; //pop(SEM);sem[++i_sem]=temp; //push(SEM,temp);temp++;}五、关键代码分析(带注释)及运行结果#include <iostream>#include "string.h"#include "stdio.h"using namespace std;char syn[10]; //文法符号栈int i_syn;char sem[10]; //运算对象栈int i_sem;char exp[50]; //算术表达式区int i;char qt[30][15]; //四元式区int j=0;char temp='q'; //临时变量, 取值为r--zint E();int T();int F();void quat(); //生成四元式函数int main(int argc, char* argv[]){printf("please input your expression:");scanf("%s",exp); //输入四元式i=0; //read(w)E();if (exp[i]=='\0')for (i=0;i<j;i++) //输出四元式序列printf("%s\n",qt[i]);elseprintf("err");return 0;}int E(){T();while ( exp[i]=='+' || exp[i]=='-'){syn[++i_syn]=exp[i]; //push(SYN,w)i++; //read(w)T();quat();}return 1;}int T(){F();while ( exp[i]=='*' || exp[i]=='/'){syn[++i_syn]=exp[i]; //push(SYN,w)i++; //read(w)F();quat();}return 1;}int F(){if ( exp[i]=='('){i++; //read(w)E();if ( exp[i]!=')'){printf("err");return 0;}}else if ((exp[i]>='a' && exp[i]<='p')||(exp[i]>='0' && exp[i]<='9')){ sem[++i_sem]=exp[i]; } //push(SEM,w) else{printf("err");return 0;}i++; //read(w)return 1;}void quat(){strcpy(qt[j],"( , , , )"); //QT[j]:=(SYN[k],SEM[s-1],SEM[s],temp);qt[j][1]=syn[i_syn];qt[j][3]=sem[i_sem-1];qt[j][5]=sem[i_sem];qt[j][7]=temp;j++;i_syn--; //pop(SYN);i_sem--; //pop(SEM);i_sem--; //pop(SEM);sem[++i_sem]=temp; //push(SEM,temp);temp++;}六、总结与分析我们知道, 定义一种语言除了要求定义语法外, 还要求定义语义, 即对语言的各种语法单位赋予具体的意义。
《编译系统设计实践》实验项目三:语法制导翻译与生成中间代码学号:姓名:年级:学院: 数计学院专业: 计算机本组其它成员:学号姓名学号姓名实验时间:2016-2017学年第一学期任课教师:一、实验目的通过语法制导或翻译模式生成中间代码。
二、实验内容在自底向上语法分析基础上设计语义规则(语法制导翻译),将源程序翻译为四元式输出,若有错误将错误信息输出。
三、设计思路1.分析过程主函数,读取文件,存入字符串数组,调用语义分析,判断关键字,调用相应的语义规则(这里只有if与while与赋值语句),赋值语句调用表达式处理,if语句调用条件表达式处理,while也就是调用表达式处理,然后就是一个递归过程,不断的递归调用,按序输出三地址语句。
在本例程序中选用expr及num作为运算数。
2.主要函数string link() //字符串与数字的连接string element() //获取表达式中的元素对象string expression() //处理表达式string expression_1() //处理表达式string biaodashi() //处理表达式,转为三地址输出string biaodashi_1() //递归---处理表达式,转为三地址输出string getOperator() //判断并获取运算符void condition(int L1,int L2) //输出if语句的条件的三地址代码void yuyifenxi_list() //生成并输出条件返回地址void yuyifenxi_list_1() //递归---生成并输出条件返回地址void yuyifenxi(int next,int &flag) //判断关键字,调用相应的产生式分析void readfile() //文件读入四、测试报告1.第一组测试:图1-1 输入待翻译代码图1-2 中间代码生成2.第二组测试:图2-1 输入待翻译代码图2-2 中间代码生成3、第三组测试:错误待翻译代码图3-1 输入待翻译代码图3-2 中间代码生成五、实验总结实验三的重点在于判断关键字,调用相应的产生式分析及处理表达式,转为三地址输出部分,也就是很费时间的难点部分,但通过查阅书本及网上资料,还就是将其以多个处理函数的递归调用实现了,虽然最后实现结果对错误的分析还不够精确有些差强人意,但毕竟还算有些收获了。
另外,通过三次实验下来,对于一个简易编译器的实现已经有了一个整体的构架了,相信在通过自己以后的深入学习,一定能写出属于自己的编译器。
六、附录代码#include <iostream>#include <algorithm>#include<conio、h>using namespace std;int address=100; //每条分析语句的地址int LID=0; //表示过程执行到相应位置的地址符号int tID=0; //用于替换表达式的标识符int ip=0;string shuru[666]; //存放从文件读入的字符串int maxsize; //设置存放数组的长度string biaodashi();/*****字符串与数字的连接*****/string link(string a,int b){string t="";do{t+=b%10+'0';b/=10;}while(b);reverse(t、begin(),t、end());return a+t;}/*****获取表达式中的元素对象*****/string element(){if(shuru[ip]=="expr"||shuru[ip]=="num"){ip++;return shuru[ip-1];}else if(shuru[ip]=="("){ip++;string result=biaodashi();if(shuru[ip]==")")ip++;else puts("Lack)");return result;}else puts("error");return "";}/*****处理表达式*****/string expression_1(string &op){if(shuru[ip]=="*"||shuru[ip]=="/"){op=shuru[ip];ip++;string arg1=element();string op_1="",result=link("t",tID++);string arg2=expression_1(op_1);if(op_1=="")op_1="=";if(arg2=="") cout<<address++<<":"<<" "<<result<<" = "<<arg1<<endl;else cout<<address++<<":"<<" "<<result<<" = "<<arg1<<" "<<op_1<<" "<<arg2<<endl;return result;}return "";}/*****处理表达式*****/string expression(){string op="",result=link("t",tID++);string arg1=element();string arg2=expression_1(op);if(op==""){op="=";}if(arg2==""){cout<<address++<<":"<<" "<<result<<" = "<<arg1<<endl;}else{cout<<address++<<":"<<" "<<result<<" = "<<arg1<<" "<<op<<" "<<arg2<<endl;}return result;}/*****递归---处理表达式,转为三地址输出*****/string biaodashi_1(string &op){string result="";if(shuru[ip]=="+"||shuru[ip]=="-"){op=shuru[ip];ip++;string arg1=expression();string op_1="";string arg2=biaodashi_1(op_1);result=link("t",tID++);if(op_1==""){op_1="=";}if(arg2==""){cout<<address++<<":"<<" "<<result<<" = "<<arg1<<endl;}else{cout<<address++<<":"<<" "<<result<<" = "<<arg1<<" "<<op_1<<" "<<arg2<<endl;}}return result;}/*****处理表达式,转为三地址输出*****/string biaodashi(){string arg1="",op="";if(shuru[ip]=="+"||shuru[ip]=="-"){arg1=shuru[ip];ip++;}arg1+=expression();string arg2=biaodashi_1(op);string result=link("t",tID++);if(op==""){op="=";}if(arg2==""){cout<<address++<<":"<<" "<<result<<" = "<<arg1<<endl;}else{cout<<address++<<":"<<" "<<result<<" = "<<arg1<<" "<<op<<" "<<arg2<<endl;}return result;}/*****判断并获取运算符*****/string getOperator(){if(shuru[ip]=="="||shuru[ip]=="<>"||shuru[ip]=="<"||shuru[ip]==">"||shuru[ip]=="<="||shuru[ip]==">="){ip++;return shuru[ip-1];}else{puts("error");}return "";}/*****输出if语句的条件的三地址代码*****/void condition(int L1,int L2) //L1,L2分别为if条件为true与false时候的跳转地址{string result=link("t",tID++);string arg1=biaodashi(); //获得表达式的运算符的左边内容string op=getOperator(); //获得表达式的运算符string arg2=biaodashi(); //获得表达式的运算符的右边内容if(arg2==""){cout<<" "<<result<<" = "<<arg1<<endl;}else{cout<<address++<<":"<<" "<<result<<" = "<<arg1<<" "<<op<<" "<<arg2<<endl;}cout<<address++<<":"<<" if true "<<result<<" goto "<<"L"<<L1<<endl;cout<<address++<<":"<<" if false "<<result<<" goto "<<"L"<<L2<<endl;}/*****判断关键字,调用相应的产生式分析*****/void yuyifenxi(int next,int &flag){if(shuru[ip]=="expr"){ip++;if(shuru[ip]=="=") //赋值语句转化为四元式{ip++;string arg1=biaodashi();string arg2="";if(arg2 == "") cout<<address++<<":"<<" expr = "<<arg1<<endl;}else puts("error");}else if(shuru[ip]=="if") //if的语义子程序{ip++;int L1=LID++;int L2=LID++;if(shuru[ip]=="("){ip++;condition(L1,L2);}else{puts("Lack(");return;}if(shuru[ip]==")") ip++;else {puts("Lack)");return;}printf("L%d:\n",L1);yuyifenxi(next,flag);ip++;if(shuru[ip]=="else"){printf("L%d:\n",L2);ip++;yuyifenxi(next,flag);}}else if(shuru[ip]=="while") //while的语义子程序{ip++;int L1=LID++;int L2=LID++;if(shuru[ip]=="("){ip++;printf("L%d:\n",L1);condition(L2,next);}else{puts("Lack(");return;}if(shuru[ip]==")") ip++;else {puts("Lack)");return;}printf("L%d:\n",L2);yuyifenxi(next,flag);printf("goto L%d\n",L1);flag=1;}}/*****递归---生成并输出条件返回地址*****/void yuyifenxi_list_1(){if(shuru[ip]==";"){ip++;int next=LID++;int flag=0;yuyifenxi(next,flag);if(flag)printf("L%d:\n",next);yuyifenxi_list_1();}}/*****生成并输出条件返回地址*****/void yuyifenxi_list(){int next=LID++;int flag=0;yuyifenxi(next,flag);if(flag)printf("L%d:\n",next);yuyifenxi_list_1();}void Modular(){int next=LID++;int flag=0;yuyifenxi_list();if(flag)printf("L%d:\n",next);}/*****文件读入*****/void readfile() //将字符串输入到shuru中{maxsize=0;while(cin>>shuru[maxsize])maxsize++;}/*****主函数*****/int main(){freopen("input、txt","r",stdin);cout<<"语义分析如下:"<<endl;readfile();Modular();return 0; }。