算术表达式到四元式翻译的编译程序设计
编译原理语义分析实验报告

实验3 语义分析实验报告一、实验目的二、通过上机实习, 加深对语法制导翻译原理的理解, 掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法。
三、实验要求四、采用递归下降语法制导翻译法, 对算术表达式、赋值语句进行语义分析并生成四元式序列。
五、算法思想1.设置语义过程。
(1)emit(char *result,char *ag1,char *op,char *ag2)该函数的功能是生成一个三地址语句送到四元式表中。
四元式表的结构如下:struct{ char result[8];char ag1[8];char op[8];char ag2[8];}quad[20];(2) char *newtemp()该函数回送一个新的临时变量名, 临时变量名产生的顺序为T1, T2, …char *newtemp(void){ char *p;char m[8];p=(char *)malloc(8);k++;itoa(k,m,10);strcpy(p+1,m);p[0]=’t’;return(p);}六、 2.函数lrparser 在原来语法分析的基础上插入相应的语义动作: 将输入串翻译成四元式序列。
在实验中我们只对表达式、赋值语句进行翻译。
源程序代码:#include<stdio.h>#include<string.h>#include<iostream.h>#include<stdlib.h>struct{char result[12];char ag1[12];char op[12];char ag2[12];}quad;char prog[80],token[12];char ch;int syn,p,m=0,n,sum=0,kk; //p是缓冲区prog的指针, m是token的指针char *rwtab[6]={"begin","if","then","while","do","end"};void scaner();char *factor(void);char *term(void);char *expression(void);int yucu();void emit(char *result,char *ag1,char *op,char *ag2);char *newtemp();int statement();int k=0;void emit(char *result,char *ag1,char *op,char *ag2){strcpy(quad.result,result);strcpy(quad.ag1,ag1);strcpy(quad.op,op);strcpy(quad.ag2,ag2);cout<<quad.result<<"="<<quad.ag1<<quad.op<<quad.ag2<<endl;}char *newtemp(){char *p;char m[12];p=(char *)malloc(12);k++;itoa(k,m,10);strcpy(p+1,m);p[0]='t';return (p);}void scaner(){for(n=0;n<8;n++) token[n]=NULL;ch=prog[p++];while(ch==' '){ch=prog[p];p++;}if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){m=0;while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){token[m++]=ch;ch=prog[p++];}token[m++]='\0';p--;syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}else if((ch>='0'&&ch<='9')){{sum=0;while((ch>='0'&&ch<='9')){sum=sum*10+ch-'0';ch=prog[p++];}}p--;syn=11;if(sum>32767)syn=-1;}else switch(ch){case'<':m=0;token[m++]=ch;ch=prog[p++];if(ch=='>'){syn=21;token[m++]=ch;}else if(ch=='='){syn=22;token[m++]=ch;}else{syn=23;p--;}break;case'>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=24;token[m++]=ch;}else{syn=20;p--;}break;case':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;p--;}break;case'*':syn=13;token[0]=ch;break; case'/':syn=14;token[0]=ch;break; case'+':syn=15;token[0]=ch;break; case'-':syn=16;token[0]=ch;break; case'=':syn=25;token[0]=ch;break; case';':syn=26;token[0]=ch;break; case'(':syn=27;token[0]=ch;break; case')':syn=28;token[0]=ch;break; case'#':syn=0;token[0]=ch;break; default: syn=-1;break;}}int lrparser(){//cout<<"调用lrparser"<<endl;int schain=0;kk=0;if(syn==1){scaner();schain=yucu();if(syn==6){scaner();if(syn==0 && (kk==0))cout<<"success!"<<endl;}else{if(kk!=1)cout<<"缺end!"<<endl;kk=1;}}else{cout<<"缺begin!"<<endl;kk=1;}return(schain);}int yucu(){// cout<<"调用yucu"<<endl;int schain=0;schain=statement();while(syn==26){scaner();schain=statement();}return(schain);}int statement(){//cout<<"调用statement"<<endl;char *eplace,*tt;eplace=(char *)malloc(12);tt=(char *)malloc(12);int schain=0;switch(syn){case 10:strcpy(tt,token);scaner();if(syn==18){scaner();strcpy(eplace,expression());emit(tt,eplace,"","");schain=0;}else{cout<<"缺少赋值符!"<<endl;kk=1;}return(schain);break;}return(schain);}char *expression(void){char *tp,*ep2,*eplace,*tt;tp=(char *)malloc(12);ep2=(char *)malloc(12);eplace=(char *)malloc(12);tt =(char *)malloc(12);strcpy(eplace,term ()); //调用term分析产生表达式计算的第一项eplacewhile((syn==15)||(syn==16)){if(syn==15)strcpy(tt,"+");else strcpy(tt,"-");scaner();strcpy(ep2,term()); //调用term分析产生表达式计算的第二项ep2strcpy(tp,newtemp()); //调用newtemp产生临时变量tp存储计算结果emit(tp,eplace,tt,ep2); //生成四元式送入四元式表strcpy(eplace,tp);}return(eplace);}char *term(void){// cout<<"调用term"<<endl;char *tp,*ep2,*eplace,*tt;tp=(char *)malloc(12);ep2=(char *)malloc(12);eplace=(char *)malloc(12);tt=(char *)malloc(12);strcpy(eplace,factor());while((syn==13)||(syn==14)){if(syn==13)strcpy(tt,"*");else strcpy(tt,"/");scaner();strcpy(ep2,factor()); //调用factor分析产生表达式计算的第二项ep2strcpy(tp,newtemp()); //调用newtemp产生临时变量tp存储计算结果emit(tp,eplace,tt,ep2); //生成四元式送入四元式表strcpy(eplace,tp);}return(eplace);}char *factor(void){char *fplace;fplace=(char *)malloc(12);strcpy(fplace,"");if(syn==10){strcpy(fplace,token); //将标识符token的值赋给fplacescaner();}else if(syn==11){itoa(sum,fplace,10);scaner();}else if(syn==27){scaner();fplace=expression(); //调用expression分析返回表达式的值if(syn==28)scaner();else{cout<<"缺)错误!"<<endl;kk=1;}}else{cout<<"缺(错误!"<<endl;kk=1;}return(fplace);}void main(){p=0;cout<<"**********语义分析程序**********"<<endl;cout<<"Please input string:"<<endl;do{cin.get(ch);prog[p++]=ch;}while(ch!='#');p=0;scaner();lrparser();}七、结果验证1、给定源程序begin a:=2+3*4; x:=(a+b)/c end#输出结果2、源程序begin a:=9; x:=2*3-1; b:=(a+x)/2 end#输出结果八、收获(体会)与建议通过此次实验, 让我了解到如何设计、编制并调试语义分析程序, 加深了对语法制导翻译原理的理解, 掌握了将语法分析所识别的语法成分变换为中间代码的语义翻译方法。
编译方法实验报告(中间代码生成器)

编译方法实验报告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++;}六、总结与分析我们知道, 定义一种语言除了要求定义语法外, 还要求定义语义, 即对语言的各种语法单位赋予具体的意义。
编译原理报告三四元式

四元式生成一、目的和要求1、目的通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法范畴变换为某种中间代码的语义翻译方法。
2、要求(1)选用目前世界上普遍采用的语义分析方法──语法制导翻译技术。
(2)语义分析对象重点考虑经过语法分析后已是正确的语法范畴,实习重点是语义子程序。
(3)中间代码选用比较常见的形式,例如四元式。
二、背景知识属性文法:A=(G,V,F),其中:G:一个CFG, 属性文法的基础。
V:有穷的属性集:每个属性与一个文法符号相关联,这些属性代表与文法符号相关的语义信息,如:类型、地址、值、代码、符号表内容等等。
属性与变量一样,可以进行计算和传递,属性加工的过程即是语义处理的过程。
属性加工与语法分析同时进行。
属性的表示:标始符(或数),写在相应文法的下边,点记法:E.Val,E.Place,E.Type…。
F:关于属性的属性断言或一组属性的计算规则(称为语义规则)。
断言或语义规则与一个产生式相联,只引用该产生式左端或右端的终结符或非终结符相联的属性。
属性有两类:综合属性:归约型属性,用于“自下而上”传递信息。
继承属性:推导型属性,用于“自上而下”传递信息。
综合属性的例子:非终结符E、T及F都有一个综合属性val,符号digit有一个综合属性,它的值由词法分析器提供。
与产生式L→E对应的语义规则仅仅是打印由E产生的算术表达式的值的一个过程,我们可认为这条规则定义了L的一个虚属性。
某些非终结符加上标是为了区分一个产生式中同一非终结符多次出现。
设表达式为3*5+4,则语义动作打印数值19。
L-属性文法:一个属性文法称为L-属性文法,如果对于每个产生式A→X1X2…Xn,满足:1、Xj(1≤j≤n)的继承属性仅依赖于下述属性值中的一种:A的继承属性或产生式右部位v于Xj左边的符号X1,X2,…,Xj-1的属性。
2、A的综合属性,仅依赖于下述属性值中的一种:A的继承属性或产生式右部符号Xj(除自身外)的任意属性。
4、语法制导四元式(算术表达式)生成器

辽宁师范大学计算机与信息技术学院综合性实验报告课程名称:编译技术实验题目:语法制导四元式(算术表达式)生成器学生姓名:专业:计算机科学与技术学号:实验日期:2015.06.05【实验目的】1.理解语法分析器原理、语法制导翻译的过程实质。
2.学会将语法分析所识别的语法成分变换为中间代码形式中的逆波兰记号形式的语义分析方法,编程实现在对一个算术表达式进行语法分析过程的基础上进行语义分析。
【实验内容】1.输入算术表达式源语言形式,输出语法分析过程(输入流变化过程)和四元式序列。
2.对于一个给定的算术表达式,首先通过词法分析过程识别出各类语法成分输出至文件中,然后采用预测分析的方法对其进行分析和语法检查,并给出具体的分析过程,包括分析步骤、分析栈、剩余符号以及所用的产生式。
在此基础上,向文法中插入语义动作,在语法分析过程中遇到语义动作就做相应的翻译工作,最终将结果(算术表达式的逆波兰式)输出到源文件中。
【实验过程】一、判断文法是否为LL(1)文法(1)E->E+E(2)E->E*E(3)E->i|-E由于此文法含左递归,消除左递归,确定算法优先次序,使文法变为:(1)E->TG(2)G->+TG|^(3)T->FS(4)S->*FS|^(5)F->i|-E1.可推出^2.各非终结符的FIRST集合如下:FIRST(E)={(,i}FIRST(G)={+, ∅}FIRST(T)={(,i}FIRST(S)={*,∅}FIRST(F)={(,i}3.各非终结符的FOLLOW集合为:FOLLOW(E)={),#}FOLLOW(G)={),#}FOLLOW(T)={+,),#}FOLLOW(S)={+,),#}FOLLOW(F)={*,+,),#}4.各产生式的SELECT集合为:SELECT(E->TG)={(,i}SELECT(G->+TG)={+}SELECT(G->^)={),#}SELECT(T->FS)={(,i}SELECT(S->*FS)={*}SELECT(S->^)={+,),#}SELECT(F->-E)={(}SELECT(F->i)={i}5.因为:SELECT(G->+TG)∩SELECT(G->∅) = {+}∩{),#} = ∅SELECT(S->*FS)∩SELECT(S->∅) = {*}∩{+,),#} = ∅SELECT(F->-E)∩SELECT(F->i) = {i}∩{(} = ∅所以文法是LL(1)文法。
武汉理工大学编译原理实验报告

武汉理⼯⼤学编译原理实验报告武汉理⼯⼤学学⽣实验报告书实验课程名称编译原理课程实验开课学院计算机科学与技术学院指导⽼师姓名饶⽂碧学⽣姓名徐强国学⽣专业班级软件 16022018 —2019 学年第1 学期实验课程名称:编译原理依次输⼊关键字,⾃定义标识符 BBBJKJL KJKJ4234,整数 3432,特殊符号和其他符号:. {} []。
⼆、实验结果及分析(包括结果描述、实验现象分析、影响因素讨论、综合分析和结论等)输出为:三、实验⼩结、建议及体会通过这次的词法分析实验,我遇到了不少问题。
对于输⼊字符串的直接处理,⾸先是分类情况的不完整(起初忽略了对关键字的判断),造成输出结果与预想有很⼤偏差。
总结下:作为编译的第⼀步,词法分析将⾼级语⾔⼀步步分解,然后转化为⾃⼰的语⾔,这是⼀个严谨有⼗分有趣的过程。
核⼼代码:struct word //存储关键字,特殊符号{int code;char T[max];};word important[5]; //结构体变量存储关键字word num; //结构体变量存储数字word identifier; //结构体变量存储标识符word special_symbol[7]; //结构体变量存储特殊符号int function(word* a, word b, word c, word* d, char* input, int k){char getword[max];int j = 0;if (input[j] == ' ') // 判断空格{k = k + j + 1;function(a, b, c, d, input + j + 1, k);}else if (input[j] == '=' || input[j] == '+' || input[j] == ',' || input[j] == '(' || input[j] == ')') //判断特殊符号{if (input[j] == '*'){getword[j] = input[j];j = j + 1;if (input[j] == '*'){} else { }else{}getword[j] = input[j];cout << '(' << d[3].code << ',' << d[3].T << ')' << endl; j = j - 1;cout << '(' << d[2].code << ',' << d[2].T << ')' << endl; getword[j] = input[j];for (int i = 0; i < 7; i++){if (i == 3)continue;elseif (d[i].T[0] == getword[0]){cout << '(' << d[i].code << ',' << d[i].T << ')' << endl; break;}}}k = k + j + 1;function(a, b, c, d, input + j + 1, k);}else if (input[j] >= '0' && input[j] <= '9') //判断数字{getword[j] = input[j];j = j + 1;while (input[j] >= '0' && input[j] <= '9'){getword[j] = input[j];j = j + 1;}j = j - 1;getword[j + 1] = '\0';cout << "(" << b.code << ',' << getword << ')' << endl;k = k + j + 1;function(a, b, c, d, input + j + 1, k);}else if (input[j] >= 'A' && input[j] <= 'Z' || input[j] >= 'a' && input[j] <= 'z') //判断字符{getword[j] = input[j];j = j + 1;while (input[j] >= 'A' && input[j] <= 'Z' || input[j] >= 'a'&&input[j] <= 'z' || input[j] >= '0' && input[j] <= '9') {getword[j] = input[j];j = j + 1;}j = j - 1;getword[j + 1] = '\0';if (!strncmp(getword, a[0].T, 3))cout << '(' << a[0].code << ',' << a[0].T << ')' << endl;else if (!strncmp(getword, a[1].T, 2))cout << '(' << a[1].code << "," << a[1].T << ')' << endl;else if (!strncmp(getword, a[2].T, 2))cout << '(' << a[2].code << "," << a[2].T << ')' << endl;else if (!strncmp(getword, a[3].T, 4))cout << '(' << a[3].code << "," << a[3].T << ')' << endl;else if (!strncmp(getword, a[4].T, 3))cout << '(' << a[4].code << "," << a[4].T << ')' << endl;elsecout << '(' << c.code << ',' << getword << ')' << endl;k = k + j + 1; function(a, b, c, d, input + j + 1, k);}else if (input[j] == '\0') //判断是否为结束符return 0;else //出错处理{cout << "第" << k + 1 << "个字符出错" << endl;k = k + j + 1;function(a, b, c, d, input + j + 1, k);}}第⼆部分:实验调试与结果分析(可加页)⼀、调试过程(包括调试⽅法描述、实验数据记录,实验现象记录,实验过程发现的问题等)算法流程截图:输⼊⼀个正确句⼦:i+i*i# 输⼊⼀个错误句⼦:i*i*(i+#输⼊⼀个⽆#结束的错误句⼦:i*i*i⼆、实验结果及分析(包括结果描述、实验现象分析、影响因素讨论、综合分析和结论等)正确结束:错误句⼦:⽆#:三、实验⼩结、建议及体会通过本次实验,我收获了很多,⾸先对 LL(1)⽂法分析的原理和过程理解更进⼀步巩固,算是做到了学以致⽤。
WHILE循环语句的翻译程序设计(递归下降法,输出四元式)

课内实践陈述课程名称编译道理设计标题WHILE轮回语句的翻译程序设计(递归降低法,输出四元式)学院盘算机科学与技巧专业班级盘算机1203班姓名闵丹枫指点教师林泓课程设计义务书学生姓名:闵丹枫专业班级:盘算机1203班指点教师:林泓工作单位:盘算机科学与技巧学院标题: WHILE轮回语句的翻译程序设计(递归降低法.输出四元式)初始前提:理论:学完编译课程,控制一种盘算机高等说话的应用.实践:盘算机试验室供给盘算机及软件情形.假如本身有盘算机可以在其长进行设计.请求完成的重要义务: (包含课程设计工作量及其技巧请求,以及解释书撰写等具体请求)(1)写出相符给定的语法剖析办法的文法及属性文法.(2)完成标题请求的中央代码四元式的描写.(3)写出给定的语法剖析办法的思惟,完成语法剖析和语义剖析程序设计.(4)编制好剖析程序后,设计若干用例,上机测试并经由过程所设计的剖析程序.(5)设计陈述格局按附件请求书写.课程设计陈述书正文的内容应包含:1 体系描写(问题域描写);2 文法及属性文法的描写;3 语法剖析办法描写及语法剖析表设计;4 按给定的标题给出中央代码情势的描写及中央代码序列的构造设计;5 编译体系的概要设计;6 具体的算法描写(流程图或伪代码);7 软件的测试办法和测试成果;8 研制陈述(研制进程,本设计的评价.特色.缺少.收成与领会等);9 参考文献(按公开揭橥的规范书写).时光安插:设计安插一周:周1.周2:完成体系剖析及设计.周3.周4:完成程序调试及测试.周5:撰写课程设计陈述.设计验收安插:设计周的礼拜五第1节课开端到试验室进行上机验收.设计陈述书收取时光:设计周的次周礼拜一上午10点.指点教师签名: 9月 1日系主任(或义务教师)签名:月日WHILE轮回语句的翻译程序设计(递归降低法.输出四元式)一.体系描写设计一个WHILE〈布尔表达式〉DO〈赋值语句〉轮回语句的词法﹑语法及语义剖析程序,语法剖析选择递归降低法,采取用语法制导翻译输出中央代码四元式.设计一个能辨认while轮回语句的文法,清除左递归,使文法相符LL(1)文法.应用递归降低法编写一个集词法剖析,语法剖析和语义剖析为一体的程序.该程序起首可以检讨输入语句是否相符词法请求,若相符则持续辨认输入的语句是否相符while语句的文法,若相符则进行语义剖析,输出用四地址代码暗示的中央代码.二.文法及属性文法的描写2.1 文法的描写扩充巴科斯瑙尔范式(EBNF):<while语句> ::= while (<前提语句>) do{ <赋值语句> }<前提语句> ::= <表达式><前提运算符> <表达式><表达式> ::= <表达式> + <表达式2> | <表达式> <表达式2> | <表达式2><表达式2>::=<表达式2> * <表达式3> |<表达式2> / <表达式3> | <表达式3><表达式3>::=(<表达式>) | <标识符>|<数字><赋值语句>::=<标识符>=<表达式>;依据以上写出来的While轮回语句的文法暗示如下:1.S > while (A) do {B}2.A > CDC3.D > > | = | < | >= |<=4.C > C+E | CE | E5.E > E*F | E/F | E6.F > (C) | i | n对以上文法清除左递归,最后得到的文法为:1.S>while (A) do {B}2.A>CDC3.D> > | = | < | >= | <=4.C>EG5.G>+EG | EG | ε6.E>FH7.H>*FH | / FH | ε8.F>(C) | i | n9.B>i=C;(1)任一非终结符B都不是左递归的,不然会产逝世活轮回.(2)对A的随意率性两个右部βi , βj ,有:first(βi)∩first(βj)=φ, First(βi)表βi所能导出串的第一个符号的聚集.显然,每个βi的first(βi)是互不雷同的,不然则无法断定应履行哪个ζ(βi ).三.语法剖析办法描写3.1语法剖析办法描写递归降低法是一种比较简略直不雅,易于构造的语法剖析办法.他请求文法知足LL(1)文法,他的设计思惟是对应文法中每个非终结符编写一个递归进程,每个进程的功效是辨认由该非终结符推出的单词(或串),当某非终结符的产生式有多个候选时,可以或许按LL(1)情势可独一地肯定选择某个候选进行推导.它的长处是简略直不雅,易于构造,许多编译体系所实现缺陷是对文法请求很高,因为递归挪用多,影响剖析器的效力.递归降低程序是由一组子程序构成,每个子程序对应于一个非终结(S,A,B,C,D,E,F,G,H).每个子程序处理响应句型中相对于此非终结符号的产生式.在界说文法时,是递归界说的,所以这些子程序也是递归的.当一个子程序挪用另一个子程序时,原子程序次序履行语句,即老是先履行被挪用的子程序,然后再履行后继的程序.程序中9个子程序,个中S 是开端符号,也是递归降低剖析的进口,经由过程挪用词法剖析器进行单词剖析,并经由过程word=l.Yufa_Queue.front()来得到当前所剖析到的单词,然后在递归语法剖析中依据这个单词剖析下一步要履行的子程序.个中要留意的是,当子程序G()和H()中消失匹配的是空字符串时,不做单词处理,该所取得的单词,应当为下一个匹配产生做预备.3.2递归降低法实现的道理设A是一个非终结符:A→β1A→β2┊A→βn则写ζ(A) if char∈first(β1 ) thenζ(β1 )else if char∈first(β2 ) then ζ(β2 )else…if char∈first(βn ) then ζ(βn)else ERROR个中ζ(βi)暗示挪用途理符号串βi的子程序.对A的任一右部i 设为:βi = y1 y2 … yn则界说ζ( βi) beginζ(y1);ζ(y2);…;ζ(yn) end个中yj可分为下列两种情形(j=1,…,n):1) yj∈VT,则ζ( yj) if char≠ yj then ERROR else READ(char)2) yj∈VN,则ζ(yj)暗示挪用关于yj的递归子程序.四.中央代码情势的描写及中央代码序列的构造设计中央代码为四元式,按照请求,要输出四元式一个四元式是一个带有四个域的记载构造,这四个域分离称为op﹑arg1﹑arg2及result.域op包含一个代表运算符的内部码.语句while a<b do a=a+b的四元式输出:1 ( <, a , b , 3 )2 ( j , _ , _ ,6 )3 ( + , a , b , n )4 ( = , n , _ , a )5 ( j , _ , _ , 1)6五.编译体系的概要设计递归降低剖析技巧就是经由过程对每个非终结符编写一个子程序来实现它的操纵,然后经由过程递归的挪用来实现对输入字符串的剖析,这个中还包含对输入字符串的词法剖析.在词法剖析的时,得到的字符单词要和症结字比较,看是否是症结字,依据比较成果进行返回响应的单词类型.单词类型重要包含界线符,症结字,常量,标识符,运算符等,每种符号都是一种类型.在语法剖析程序中,依据词法得到的成果,进行断定是否是当前须要的单词类型,假如不是就解释输入字符串不克不及由该文法推导出来;假如是当前须要的类型,就响应得做该单词类型分支程序.依据文法可以得到这个递归降低程序可以剖析while语句,在文法的开端符号S开端进行递归挪用,是以这个文法的递归中就要斟酌到挪用以及递归.在递归子程序中,在嵌套挪用其他子程序时都是有必定前提的,当知足这个前提的时刻该程序可以按照知足的前提履行下去,当没有知足程序中的前提时就会显示语法错误.词法剖析程序的义务是:从左至右逐个字符地对源程序进行扫描,产生一个个的单词符号,把作为字符串的源程序改革成为单词符号的中央程序.词法剖析检讨的错误主如果挑出源程序中消失的不法符号.所谓不法符号是指不是程序设计说话中许可消失的符号,就像天然语句中的错字.对每个非终结符A构造一个函数进程,对A的每个持续属性设置一个情势参数,函数的返回值为A的分解属性,A对应的函数进程中,为出如今A的产生式中的每一个文法符号的每一个属性都设置一个局部变量.非终结符A对应的函数进程中,依据当前的输入符号决议应用哪个产生式候选.每个产生式对应的程序代码中,按照从左到右的次序,对于单词符号,非3:终结符和语义动作分离做以下工作.1.对于带有分解属性x的终结符X,把x的值存入为X,x设置的变量中.然后产生一个匹配X的挪用,并持续读入一个输入符号.2.对于每个非终结符号B,产生一个右边带有函数挪用的赋值语句c=B(b1,b2,…,bk)3.对于语义动作,把动作的代码抄进剖析器中,用代表属性的变量来代替对应属性的每一次引用.在语法剖析进程中,跟着剖析的步步进展,依据每个产生式所对应的语义子程序(或语义规矩描写的语义动作)进行翻译.属性文法的每个符号有属性,所以每个符号入栈时,必须连属性一路入栈,如许,栈符号就由文法符号及存放该符号属性的域所构成.因为属性类型不合,属性域存放的内容就要依据属性的类型来定.有的可能直接存放属性值,也有的存放的是指向属性值的指针.对于分解属性,其属性域不存放其属性值,而是存放一个指针,指向存贮该属性值的单元.对于持续属性,其属性域直接保管其属性值.持续属性的属性域刚入栈时为空,但是在该栈符号变成栈顶符号之前的某一时刻,它们必须接收响应的属性值,即在成为栈顶时,持续属性的属性域必须有值.六.具体的算法描写S()W()E F()D()G()R()T()办法和变量的界说做W():做E():做F()F > < | = | > | <= | >=做Do_G G> c=R对赋值语句进行四元式输出:七.软件的测试办法和测试成果输入 while(a>b){z=x+y;}测试成果如下:输入while(a>b){z=x+y*c;} 测试成果如下输入wh(a>b){z=y;} 成果为:输入while(a>b){z=z+y} 成果为:八.研制陈述(研制进程,本设计的评价.特色.缺少.收成与领会等)在做本次试验之前我对LL(1)文法的构成,递归降低道理不是很懂得,在查阅了相干材料后,对此有了深刻懂得.将词法剖析,语法剖析,中央说话翻译联合到一路.8.2 设计的评价.特色.缺少设计的程序根本上实现了用递归降低剖析法实现了while语句的翻译,并可以或许用四元式将其输出,使人一目了然.程序还可以或许精确提醒词法和语法错误.同时程序运行时简略清楚明了,易于应用.深刻懂得盘算机说话编译和运行的进程,对编译道理有了深刻的熟悉,控制了递归降低法,闇练地应用四元式中央代码,明确了对于编写程序,解题的思绪为重要.在编写程序之前,假如没有比较清楚的思绪,根本不成能编出好的程序.就算马纰漏虎的编出来,程序的逻辑性.硬朗性.完美性.合理性也不会很强.在编程之前,我们应重复研讨标题请求,对标题涉及的情形进行比较充分的剖析,以便编写出加倍相符题意的程序;其次要充分斟酌各类临界情形,对一些错误的输入进行处理.是以在我们编程序之前必定要做好充分的预备,起首要理清本身的思绪,然后再将思绪分划成几个模块,逐块的写好算法,最后再将所有的模块有机的接洽起来,构成一个完全的程序.在成功经由过程编译的情形下,对程序运行的成果进行体系的剖析,磨练其精确性,假如有错误,应立刻去剖析源程序的逻辑错误,直到得到精确的成果.九.参考文献《编译道理第2版》清华大学出版社张素琴等著本科生课程设计成绩评定表序号评分项目满分实得分注:最终成绩以五级分制记.优(90100分).良(8089分).中(7079分).合格(6069分).60分以下为不合格指点教师签名:201 年月日。
IF-ELSE条件语句的翻译程序设计(简单优先法、输出四元式)

#include <fstream>#include <iostream>#include <string>#include<iomanip>#include<cmath>#include<stdio.h>#include<stdlib.h>#include<assert.h>using namespace std;#define STACK_INIT_SIZE 50#define STACKINCREMENT 30#define OK 1#define ERROR -1#define FAILURE -1///////////////////////////////////////*(1)S->if E then B else B(2)E->(A>A)(3)E->(A<A)(4)E->(A)(5)A->d(6)A->num(7)B->{d=C}(8)C->A+A(9)C->A-A(10)C->A*A(11)C->A/A(12)C->A*////////////////////////////////////////int lineno = 1;char ch ;int anltable[22][22]={/*S*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2}, /*if*/ {0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*E*/ {0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*then*/{0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0},/*B*/ {0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2}, /*else*/{0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0},/*(*/ {0,0,0,0,0,0,0,0,0,0,0,3,1,1,0,0,0,0,0,0,0,0},/*)*/ {0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},/*>*/ {0,0,0,0,0,0,0,0,0,0,0,3,1,1,0,0,0,0,0,0,0,0}, /*<*/ {0,0,0,0,0,0,0,0,0,0,0,3,1,1,0,0,0,0,0,0,0,0},/*=*/ {0,0,0,0,0,0,0,0,0,0,0,1,1,1,3,0,0,0,0,0,0,0},/*A*/ {0,0,0,0,0,0,0,3,3,3,0,0,0,0,0,0,2,3,3,3,3,0},/*d*/ {0,0,0,0,0,0,0,2,2,2,3,0,0,0,0,0,2,2,2,2,2,0},/*num*/ {0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,2,2,2,2,2,0},/*C*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0},/*{*/ {0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0},/*}*/ {0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2},/*+*/ {0,0,0,0,0,0,0,0,0,0,0,3,1,1,0,0,0,0,0,0,0,0},/*_*/ {0,0,0,0,0,0,0,0,0,0,0,3,1,1,0,0,0,0,0,0,0,0},/***/ {0,0,0,0,0,0,0,0,0,0,0,3,1,1,0,0,0,0,0,0,0,0},/*/*/ {0,0,0,0,0,0,0,0,0,0,0,3,1,1,0,0,0,0,0,0,0,0},/*#*/ {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},};//0-error ,1=<, 2=> ,3==char allname[30][30];//单词全名char out[30][30];//保存单词简称int length;struct att{//名字表类型string sname;char select;char addre;};att attname[40];//名字表typedef struct SqStack{char *base;char *top;int stacksize;}SqStack;//栈定义void InitStack (SqStack &S){//栈初始化S.base=(char*)malloc(STACK_INIT_SIZE*sizeof(char));//分配存储空间if(!S.base)exit(OVERFLOW); //为栈S分配存储空间失败S.top=S.base;S.stacksize=STACK_INIT_SIZE;}int push(SqStack &S,char ch) // 将元素e插入到栈S中,成为新的栈顶元素{if(S.top-S.base >S.stacksize) //判定栈是否满{S.base=(char*)realloc(S.base,(S.stacksize+STACKINCREMENT *sizeof(char)));if(!S.base){printf("分配存储单元失败.\n"); //存储单元分配失败exit(OVERFLOW);}S.top=S.base+S.stacksize; //指明栈顶指针的基址S.stacksize+=STACKINCREMENT; //指明栈的空间大小} // end of if*S.top++=ch; //先将e送入栈顶指针所指向的单元,再将栈顶指针加1return(OK);} //end of Push() subfunctionint pop(SqStack &S,char &ch){//栈顶元素出栈if(S.top==S.base){printf("溢出");return (ERROR);}ch=*--S.top;return(OK);}char gettop(SqStack S){ //返回栈顶元素if(S.top==S.base) cout<<"栈空,出错"<<endl;char e;e = *(S.top-1);return e;}int getnum(char cc){//返回元素在优先表中的位置switch(cc){case 'S':return 0;break; case 'i':return 1;break; case 'E':return 2;break; case 't':return 3;break; case 'B':return 4;break; case 'e':return 5;break; case '(':return 6;break; case ')':return 7;break; case '>':return 8;break; case '<':return 9;break; case '=':return 10;break; case 'A':return 11;break; case 'd':return 12;break; case 'n':return 13;break; case 'C':return 14;break; case '{':return 15;break; case '}':return 16;break; case '+':return 17;break; case '-':return 18;break; case '*':return 19;break; case '/':return 20;break; case '#':return 21;break;default:return 88;}}int judge(char *string){//判断是否是关键字char *keywords[1000]={"if","then","else"};for(int i = 0;i <= 2;i++){if (!strcmp(string,*(keywords+i))){return 1;}}return 0;}int analysis(ifstream &fin,ofstream &fout) //词法分析程序,用引用传递参数{char temp[10]; // 临时存放已读入但无法判断类型的字符int j=0;int ou=0;int na=0;while (fin.get(ch)){if (ch == '\n') {lineno += 1; }else if (ch == '\t'||ch == ' ') {} //排除制表、空格字符else if (isalpha(ch)) //当前输入符为字母{while (isalpha(ch)||isdigit(ch)){temp[j] = ch;j++;fin.get(ch);}temp[j] = '\0'; //标志字符串结束j = 0;if(judge(temp)) // 判断是否为关键字{memcpy(allname[na],temp,10);attname[na].sname=allname[na];attname[na].select=allname[na][0];memcpy(out[ou],temp,10);ou++;fout<<"("<<attname[na].sname<<",关键字)"<<endl;na++;}else{memcpy(allname[na],temp,10);attname[na].sname=allname[na];attname[na].select='d';memcpy(out[ou],temp,10);ou++;fout<<"("<<attname[na].sname<<",变量)"<<endl;na++;}fin.seekg(-1,ios::cur); //回退1个字符}else if (isdigit(ch)){while (isdigit(ch)){temp[j] = ch;j++;fin.get(ch);}temp[j] = '\0'; //标志字符串结束j = 0;memcpy(allname[na],temp,10);attname[na].sname=allname[na];attname[na].select='n';memcpy(out[ou],temp,10);ou++;fout<<"("<<attname[na].sname<<",常量)"<<endl;na++;fin.seekg(-1,ios::cur); //回退一个字符}else if (ch == '='){allname[na][0]=ch;attname[na].sname=allname[na];attname[na].select=ch;memcpy(out[ou],"=",10);ou++;fout<<"("<<attname[na].sname<<",算符)"<<endl;na++;}else if (ch == '+'){allname[na][0]=ch;attname[na].sname=allname[na];attname[na].select=ch;memcpy(out[ou],"+",10);ou++;fout<<"("<<attname[na].sname<<",算符)"<<endl;na++;}else if (ch == '-'){allname[na][0]=ch;attname[na].sname=allname[na];attname[na].select=ch;memcpy(out[ou],"-",10);ou++;fout<<"("<<attname[na].sname<<",算符)"<<endl;na++;}else if (ch == '*'){allname[na][0]=ch;attname[na].sname=allname[na];attname[na].select=ch;memcpy(out[ou],"*",10);ou++;fout<<"("<<attname[na].sname<<",算符)"<<endl;na++;}else if (ch == '/'){allname[na][0]=ch;attname[na].sname=allname[na];attname[na].select=ch;memcpy(out[ou],"/",10);ou++;fout<<"("<<attname[na].sname<<",算符)"<<endl;na++;}else if (ch == '('){allname[na][0]=ch;attname[na].sname=allname[na];attname[na].select=ch;fout<<"("<<attna me[na].sname<<",界限符)"<<endl;na++;}else if (ch == ')'){allname[na][0]=ch;attname[na].sname=allname[na];attname[na].select=ch;fout<<"("<<attna me[na].sname<<",界限符)"<<endl;na++;}else if (ch == '{'){allname[na][0]=ch;attname[na].sname=allname[na];attname[na].select=ch;fout<<"("<<attna me[na].sname<<",界限符)"<<endl;na++;}else if (ch == '}'){allname[na][0]=ch;attname[na].sname=allname[na];attname[na].select=ch;fout<<"("<<attname[na].sname<<",界限符)"<<endl;na++;}else if (ch == '<'){allname[na][0]=ch;attname[na].sname=allname[na];attname[na].select=ch;memcpy(out[ou],"<",10);ou++;fout<<"("<<attname[na].sname<<",逻辑运算符)"<<endl;na++;}else if (ch == '>'){allname[na][0]=ch;attname[na].sname=allname[na];attname[na].select=ch;memcpy(out[ou],">",10);ou++;fout<<"("<<attname[na].sname<<",逻辑运算符)"<<endl;na++;}else if (ch == '#'){out[ou][0]='#';ou++;}else{fout<<"无法识别字符"<<"\" "<<ch<<" \""<<endl;return 0;}}ch = '\0';attname[na].select='#';out[ou][0]='#';ou++;length=na;return 1;}void printstack(SqStack &S,int naa,int ty,ofstream &fout) {char temp[40][20];for(int k=0;k<40;k++){for(int t=0;t<20;t++)temp[k][t]=NULL;}int te=0;int i=0,j=0;int nu=0;char *ku;ku=S.base;i=naa+1;char *contrl;contrl=S.base;while(contrl!=S.top){if(*contrl!='1'){if(*contrl=='i'){fout<<"if";nu=nu+2;}else if(*contrl=='t'){fout<<"then";nu=nu+4;}else if(*contrl=='e'){fout<<"else";nu=nu+4;}else{fout<<*contrl;nu++;}}contrl++;}fout<<"\t\t\t";for(i;i<=length;i++){if(gettop(S)=='S')fout<<"#";elsefout<<attname[i].select;}if(gettop(S)=='S')fout<<"#";elsefout<<temp[te];te++;fout<<endl;}int laynax(ofstream &f){SqStack S;InitStack(S);push(S,'#');char cch,tempch;int naa=0,over=1,go;int front=0,last=0,choose=0;while(over){//getchar();front=getnum(gettop(S));last=getnum(attname[naa].select);go=naa;//cout<<front<<" "<<last<<endl;choose=anltable[front][last];if(choose==1){push(S,'1');push(S,attname[naa].select);printstack(S,go,1,f);naa++;}else if(choose==3){push(S,attname[naa].select);printstack(S,go,1,f);naa++;}else if(choose==2){int a=0;l1: pop(S,cch);if(cch=='1'){if(tempch=='i'){push(S,'S');printstack(S,go,3,f);over=0;}else if(tempch=='('){push(S,'E');printstack(S,naa-1,3,f);}else if(tempch=='d'){front=getnum(gettop(S));last=getnum('A');choose=anltable[front][last];if(choose==1){push(S,'1');}push(S,'A');a=1;printstack(S,naa-1,3,f);}//cout<<"归约了A"<<endl;else if(tempch=='n'){front=getnum(gettop(S));last=getnum('A');choose=anltable[front][last];if(choose==1){push(S,'1');}push(S,'A');a=1;printstack(S,naa-1,3,f);}//cout<<"归约了A"<<endl;else if(tempch=='{'){push(S,'B');a=1;printstack(S,go-1,3,f);}//cout<<"归约了B"<<endl;naa++;else if(tempch=='A'){push(S,'C');a=1;printstack(S,go-1,3,f);}//cout<<"归约了C"<<endl;}else{tempch=cch;goto l1;}}else{cout<<"进行移入归约时有误,该串不符合文法...";cout<<gettop(S)<<"和"<<attname[naa].sname<<"之间无优先关系"<<endl;return 0;}}return 1;}int printfou(){cout<<"生成的中间代码四元式,结果如下:"<<endl;int ta=0;string temp[20];while(out[ta]!="#"){//getchar();if(!strcmp(out[ta],"if")){if(!strcmp(out[ta+2],">")||!strcmp(out[ta+2],"<")){cout<<"(1)"<<"("<<out[ta+2]<<","<<out[ta+1]<<","<<out[ta+3]<<",(6))"<<endl;ta=ta+4;}else{cout<<"(1) if "<<out[ta+1]<<" goto 3"<<endl;ta=ta+2;}}else if(!strcmp(out[ta],"then")){ta++;for(int i=0;i<5;i++){temp[i]=out[ta];ta++;}}else if(!strcmp(out[ta],"else")){ta++;cout<<"(3)"<<"("<<out[ta+3]<<","<<out[ta+2]<<","<<out[ta+4]<<",t1)"<<endl;cout<<"(4) "<<"("<<out[ta+1]<<",t1,_,"<<out[ta]<<")"<<endl;cout<<"(5) (jump,_,_,(8))"<<endl;break;}else{cout<<"四元式产生错误......"<<endl;return 0;}}cout<<"(6) "<<"("<<temp[3]<<","<<temp[2]<<","<<temp[4]<<","<<"t2"<<")"<<endl;cout<<"(7) "<<"("<<temp[1]<<","<<"t2"<<",_,"<<temp[0]<<")"<<endl;cout<<"(8) "<<"("<<"jump,_,_,_)"<<endl;return 1;}int main(){int test=0;cout<<"============================================================ ==================="<<endl;cout<<"= IF-ELSE条件语句的翻译程序设计(简单优先法、输出四元式)="<<endl;cout<<"============================================================ ==================="<<endl;char inFile[100],wordOutFile[100],stackFile[100];ifstream *fin;ofstream *wordOut,*stackOut;while(true){printf("输入源文件名(包括路径):");cin>>inFile;fin=new ifstream(inFile);if(fin==NULL){printf("输入源文件名错误!\n");continue;}break;}while(true){printf("输入单词输出文件(包括路径):");cin>>wordOutFile;wordOut=new ofstream(wordOutFile);if(wordOut==NULL){printf("输入文件名错误!\n");continue;}break;}while(true){printf("输入栈情况输出文件(包括路径):");cin>>stackFile;stackOut=new ofstream(stackFile);if(stackOut==NULL){printf("输入文件名错误!\n");continue;}break;}getchar();test=analysis(*fin ,*wordOut);if(test==1){test=laynax(*stackOut);}elsereturn 0;if(test==1){printfou();}return 0;}。
编译原理课程设计_算术表达式、for、while语句转换为四元式

计算机与信息学院《操作系统与编译原理联合课程设计报告》专题:编译原理部分学生姓名:学号:专业班级:指导教师:2014 年 7 月一、设计目标设计一个语法制导翻译器,将算术表达式、for语句、while语句翻译成四元式。
要求先确定一个定义算术表达式、for语句、while语句的文法,为其设计一个语法分析程序,为每条产生式配备一个语义子程序,按照一遍扫描的语法制导翻译方法,实现翻译程序。
对用户输入的任意一个正确的表达式,程序将其转换成四元式输出。
二、设计思路开发平台:Visual C++ MFC解决这个问题的方案分为以下几个步骤:1.将算数表达式、for语句、while语句转换为四元式的第一步为对读入的表达式进行处理,即删除不必要的空格、回车、换行等,保证之后的步骤能够顺利进行。
2.分析算术表达式、for语句、while语句的文法。
3.通过词法分析判断语句中的每个字符的类型,如:数字、字母、符号等。
4.建立每种文法的LR(0)分析表,通过每个文法的LR(0)分析表对相应的表达式进行语法分析。
5.在语法分析正确的情况下,通过语法分析的中间过程的符号栈输出四元式,四元式的形式为:(op arg1 arg2 result)。
(一)算术表达式转换为四元式将算术表达式转换为四元式首先考虑了括号的问题,对于不同的算术表达式第一步进行词法分析,即确定各种符号的位置。
而括号中的式子是优先级最高的,应该最先进行处理。
我使用了一个数组记录算术表达式中括号的位置,并且定义了first_cc和first_jj函数对括号的乘除法和加减法分别进行处理。
后将括号的式子以四元式的形式输出。
通过以上转换,已将原算术表达式中的括号中的容使用大写字母’A’、’B’……等代替(其中定义声明了change函数,用来将括号部分替换为大写字母)。
新的式子中,只含有加减乘除以及赋值这四种运算,后根据优先级的不同,逐步生成四元式。
其算法流程图如右图所示。
FOR循环语句的翻译程序设计LL(1)法、输出四元式(含代码和实验报告册)毕业设计(论文)

FOR循环语句的翻译程序设计——LL(1)法、输出四元式1.系统描述1.1问题描述用LL(1)法设计、编制、调试一个FOR(表达式1;表达式2;表达式3)〈赋值语句〉的语法及语义分析程序,输出四元式。
1.2功能描述(1)能够识别出单词、单词类型、单词位置(2)能够用LL(1)方法识别单词序列是否符合FOR循环文法(3)能够完成对FOR循环中3个表达式的翻译(4)能够完成对FOR循环中赋值语句(含复杂表达式)的翻译(5)能够对FOR循环3个表达式中有表达式1或3缺少时翻译(6)能够用标准化的四元式进行翻译结果输出(7)能够用四元式清晰、正确地反映FOR循环的执行流程(8)能够用文本输入FOR语句循环,再用txt文本输出分析结果2 文法及属性文法的描述2.1文法的语言描述A->for(条件){赋值语句}条件->语句1 语句2 语句3语句1->i = 表达式; //i表示标识符语句1->;语句2->i > 表达式;语句2->i < 表达式;语句3->i = 表达式;语句3->ε赋值语句->m = 表达式 //m表示标识符,作为左值出现赋值语句->ε表达式->表达式+表达式表达式->表达式-表达式表达式->表达式*表达式表达式->表达式/表达式表达式->(表达式)表达式->i //i 表示标识符、常数、字符、或字符串2.2属性文法描述2.2.1 FOR 语句FOR(C D G)n Cn+1 if D==true goto Y.startn+2 goto Y.end+3Y.start ...................//赋值语句的开始...... ...................Y.end ...................//赋值语句结束Y.end+1 GY.end+2 goto n+1Y.end+3 //跳出循环体后第一条语句2.2.2 赋值语句Y->m=E; { m.value=E.Value }E->E1 op E2 (op: +,-,*,/,>或<){E.place = newtemp; //生成新的变量E.value =E1.value op E2.value}N->(E) { N.value=E.value }N->i { N.value=i.value }3.语法分析方法描述及语法分析表设计3.1 对LL(1)分析的描述LL(1):第1个L表明自顶向下分析是从左向右扫描输入串,第2个L表明分析过程中将用最左推导,1表明只需向右看一个符号便可决定如何推导即选择哪个产生式(规则)进行推导。
编译原理E课内实践报告:WHILE循环语句的翻译程序设计与实现,递归下降法,输出四元式

文法及属性文法的描述 ............................................................................................... 2 2.1 2.2 文法描述 ............................................................................................................. 2 属性文法描述 ..................................................................................................... 3
2.2 属性文法描述
形式上讲,属性文法是一个三元组 :A=(G,V,F), 其中: ➢ G:是一个上下文无关文法; ➢ V:有穷的属性集,每个属性与文法的一个终结符或非终结符相连 ,这些属性代表与 文法符号相关信息; ➢ F:关于属性的属性断言或一组属性的计算规则(称为语义规则) 。 断言或语义规则 与一个产生式相联,只引用该产生式左端或右端的终结符或非终结符相联的属性。 属性文法中的属性分成两类:继承属性和综合属性。 ➢ 综合属性(synthesized attribute) :如果 b 是 A 的属性,c1 , c2 , …, ck 是产生式右 部文法符号的属性或 A 的其它属性,则称 b 是文法符号 A 的综合属性。 ➢ 继承属性(inherited attribute):如果 b 是产生式右部某个文法符号 X 的属性,并且 c1,c2,…,ck 是 A 或产生式右部文法符号的属性, 则称 b 是文法符号 X 的继承属性。
3
计算机编译原理实验生成四元式序列

西北师大学计算机科学与工程学院学生实验报告
}
实验结果:
实验总结:
通过本次实验我完成生成四元式的语法分析程序,掌握的结合语法分析实现翻译方案的思路和方法。
本次实验还是遇到许多困难,通过上网查看以及查看许多书籍,最终还是完成了本次试验,还是收获挺大的。
但是实验中还存在着许多不足,如规则的顺序,first集合的求解等,还需不断完善。
实验评语:
该学生在本次试验中完成生成四元式的语法分析程序,基本掌握的结合语法分析实现翻译方案的思路和方法,但是程序在一些细节及特殊文法的处理上还需要进一步完善,如编程时注意编程风格:空行的使用、注释的使用、缩进的使用,如果遇到错误的表达式,应输出错误提示信息等。
编译原理课程设计-翻译成四元式

编译原理课程设计一、课程设计题目:第(20)题:写一程序,演示对给定下标变量赋值语句文法,且已知建立内情向量,对给定的下标变量赋值语句翻译成四元式。
二、编程环境:在Turboc下编程运行,可随意输入数组维数,对输入的给定下标变量赋值语句翻译成四元式。
三、设计原理:一个含数组元素的赋值语句的文法模式可为下所示:A->V:=E V->i[elist]|i elist->elist,E|E E->E+E|(E)|V 即一个赋值语句A是一个V(指变量)后跟赋值号:=和一个算术表达式E。
为了计算数组元素的VARPART,需要把关于变量V的文法改写成:V->elist]|i elist->elist,E|i[E 把数组名i和最左的下标式写在一起的目的是使在整个下标串elist的翻译过程中随时都能知道数组名i的符号表入口,从而随时能够了解登记在符号表中的有关数i的全部信息。
为了计算VARPART的四元式序列,需要知道数组名的符号表入口,下标式的个数,将VARPART的中间结果单元名字在符号表中的位置等。
还要根据含有数组元素的赋值句的翻译规则进行翻译。
四、设计过程:数组元素a[i1,i2,…,in]地址D的计算公式为: D=CONSPART+VARPARTCONSPART=a-c ,其中c是常数(d2d3…dn+d3…dn+…+dn+1).由题目已知建立了内情向量表,但是为了方便起见还是要输入数组的维数以及是几乘几的数组。
为了计算常数c编了一个专门的函数Conspart(int a[],DIM);其核心是:for(j=1;j<DIM;j++)c=c*a[j]+1;为了将四元式的计算VARPART 的过程演示出来,知道其值为(i1d2d3…dn +i2d3d4…dn+…+in-1dn+in),即可通过一个循环来计算VARPART的值,如下VARPART:=VARPART*dk+1+ik+1因此也可通过循环来演示计算四元式VARPART的过程。
编译原理四元式

编译原理四元式
编译原理中的四元式是一种中间代码形式,用于表示源程序在编译过程中的中间结果。
四元式由四个部分组成,分别是操作符(operator)、操作数1(operand1)、操作数2(operand2)和结果(result)。
在编译原理中,四元式通常用于表示程序的中间代码,可以通过一系列的四元式来表达源程序的语义。
四元式的优点是可以简化编译器的实现,同时也可以方便地进行优化和代码生成等操作。
在实际的编译器实现中,四元式的具体形式和表示方法可能有所不同,但通常都包含上述四个部分。
例如,在编译器中,可以通过使用类似以下的四元式来表示一个简单的赋值语句:
代码
t1 = add(a, b)
t2 = sub(c, d)
t3 = eq(t1, t2)
其中,add和sub是操作符,a和b、c和d是操作数1和操作数2,t1、t2和t3是结果。
这个四元式组表示了以下代码:
代码
if (a + b == c - d) {
// do something
}
在编译器的后续处理中,四元式可以被进一步优化和转换,最终生成目标代码。
因此,四元式在编译器的实现中起着重要的作用。
一个语法分析程序并生成四元式中间代码

一个语法分析程序并生成四元式中间代码编写一个语法分析程序并生成四元式中间代码班级学号姓名:指导老师:一、实验目的:1、学习编译的基本原理;2、巩固课堂学习的知识;3、会对最基本的语句进行分析,转换成四元式;二、实验内容:编制一个大型程序,可以对小型的EL语言程序进行翻译,可以处理最基本的语句如:if语句,while语句等;三、实验硬件和软件平台:INTEL C433MHz Cpu128Mb SDRAMTPWMicrosoft Windows XP SP1四、步骤和算法描述:1、先对输入的语句进行词法分析,建立各种表格;2、对程序进行语法分析,建立四元式;对部分程序语句进行翻译,生成相应的四元式,及出错处理五.源程序:program elcompiler(input,output,f);const reser=20;type alfa=packed array[1..9] of char;opr=(jmp,prt,jeq,jne,jgt,jlt,jge,jle,add,sub,mul,did,ass,umi,jsr,ret,inp,out,xxx);{中间代码的操作码符号}instruction=record{四元式} op:opr;arg1,arg2,result:integer;symset=set of 0..45;obj=1..45;var reserve:array[0..reser] of alfa; {保留字表} token,id:alfa;line:array[1..80] of char; {输入缓冲区}ch,ch1:char;quad:array[0..300] of instruction; {四元式表} table:array[0..100] of {符号表} recordname:alfa; level:integer;case cat:obj of2 : (val:integer);18,7: (addr:integer)end;mnemonic:array[opr] of array[1..3] of char; cp,tp,new,nxq:integer;cc,ii,i,j,k,num:integer;kind,l,err:integer;filename:string;{外部文件名}f:text;procedure getchar; {从扫描缓冲区取一字符} beginif cc=ii then {如果已取到缓冲区的最后,则从外部} {文件再读一行}beginif eof(f) thenbeginwriteln('program incomplete!');close(f); exitcc:=0; ii:=0; { cc is input to buffer pointer; { ii is output pointer from buffer;}while not eoln(f) dobegin cc:=cc+1;read(f,line[cc]);write(line[cc])end;readln(f); writeln;cc:=cc+1; line[cc]:=' ';end;ii:=ii+1; ch:=line[ii]end;procedure getnbc; {读取非空字符}label l;beginl:getchar;while ch='' do getchar;if ch='{' thenbegin repeat getchar until ch='}';goto l end {跳过注解}end;procedure retract; {退回一字符}beginii:=ii-1end;procedure scanner; {词法分析过程}begingetnbc;if ch in ['a'..'z'] then {symbol is id or reserve}beginrepeatif k<10 thenbegin k:=k+1; token[k]:=ch end;getcharuntil not(ch in['a'..'z','0'..'9']);retract;if k<10 thenrepeatk:=k+1;token[k]:=' 'until k=10;id:=token; i:=0; j:=reser;repeat k:=(i+j) div 2; {对半查找保留字表}if id<=reserve[k] then j:=k-1;if id>=reserve[k] then i:=k+1until i>j;if i-1>j then kind:=k else kind:=21 {变量的类别} end elseif ch in ['0'..'9'] thenbegin{整数}k:=0; num:=0; kind:=22;repeatnum:=10*num+(ord(ch)-ord('0'));k:=k+1; getnbc;until not(ch in ['0'..'9']); retractend elsebegincase ch of'+','-':beginch1:=ch; retract; retract; getchar;if (ch='=') or (ch='(') then {区分单目双目算符} if ch1='+' then kind:=32 else kind:=33else if ch1='+' then kind:=34 else kind:=35; getcharend;'*':kind:=36;'/':kind:=37;',':kind:=23;'.':kind:=26;';':begin writeln; kind:=24 end;'(':kind:=27;')':kind:=28;'[':kind:=29;']':kind:=30;'=':kind:=38;':': begingetnbc;if ch='=' then kind:=44else begin retract; kind:=25 endend;'#':kind:=47;'{':kind:=45;'}':kind:=46;'>':begingetnbc;if ch='=' then kind:=43else begin retract; kind:=40 endend;'<':begingetnbc;if ch='=' then kind:=42else if ch='>' then kind:=41else begin kind:=39; retract end end;else;end;endend;procedure error(n:integer); {出错处理} beginwrite('*',' ',ii-2,'^',n:2); err:=err+1; case n of0:writeln('lack ''program''');1:writeln('ought to''='' ');2:writeln('lack''=''');3:writeln('expected indent');4:writeln('expected factor');5:writeln('expeced '','''';''');6:writeln('expected ''begin or functin'''); 7:writeln('expected statement') ;8:writeln('expected''begin''');9:writeln('expect '',''');10:writeln('num is too big');11:writeln('indent isnt specify');12:writeln('cant assign to const');13:writeln('expeced '':=''');14:writeln('expected ''(''');16:writeln('ought to ''then''');17:writeln('expected ''end''or'';''');18:writeln('ought to ''do''');19:writeln('expected '';''on''.');20:writeln('expeced ''rop''');22:writeln('expected '')''');23:writeln('may be to lack''*''');25:writeln('to lack type specify');26:writeln('indent double define')else ;endend;procedure test(s1,s2:symset;m:integer); { 测试单词的合法} beginif not(kind in s1) thenbeginerror(m); s1:=s1+s2;while not (kind in s1) do scannerendend;procedure gen(op:opr;ag1,ag2,result:integer); {生成中间代码} beginquad[cp].op:=op;quad[cp].arg1:=ag1;quad[cp].arg2:=ag2;quad[cp].result:=result;cp:=cp+1;nxq:=cp;end;procedure blk(lev,tp:integer;sys:symset);var tp0,cp0,dp:integer;chain:integer;function entry(iden:alfa):integer;var i:integer;i:=tp;table[0].name:=iden;while table[i].name<>iden do i:=i+1;entry:=iend;procedure fill(k:obj);{填写符号表}var i:integer;beginfor i:=tp0 to tp do {tp0 本分程序符号表首址}if table[i].name=id thenbegin error(26); exit end;tp:=tp+1;with table[tp] dobegin name:=id; cat:=k; level:=lev;case k of2: begin if num>22767 then{const 说明} begin error(10); num:=22767 end; val:=num; end;18:begin addr:=dp; dp:=dp+1 end; {var 说明}7:addr:=0;{function 说明}endendend;procedure constdec; {说明处理}beginif kind=21 then {变量}beginscanner if kind in [38,44] then {=,:=}if kind=44 then error(1);scanner;if kind=22 thenbeginfill(2); scannerendelse error(4)endelse error(2)endelse error(3)end;procedure vardec; {var说明处理}beginif kind=21 thenbegin fill(18); scanner endelse error(4);end;procedure listquad; {显示中间代码结果}var i:integer;beginfor i:=cp0 to cp-1 dowith quad[i] do writeln(i:3,mnemonic[op]:6,arg1:6,arg2:6,resul t:6);end;procedure listtable; {显示符号表}var i:integer;beginfor i:=1 to tp dowith table[i] dowriteln(name:5,cat:5,level:5,val:5,addr:5); end;function newtemp:integer; {取一临时变量序号}beginnew:=new+1;newtemp:=newend;procedure bp(p,t:integer); {回填四元式链}var q:integer;beginq:=p;while q<>0 dobeginp:=quad[q].result;quad[q].result:=t;q:=pendend;function merg(p1,p2:integer):integer; {并链}var p:integer;beginif p2=0 then merg:=p1else beginp:=p2;while quad[p].result <> 0 dop:=quad[p].result;quad[p].result:=p1;endend;procedure statement(var schain:integer; sys :symset); {语句分析处理}var i,j,k,q,place:integer;ttc,ffc,slchain,s2chain:integer; function exp(sys:symset):integer; {表达式处理}var addop,e1place,e2place,t:integer;function term(sys:symset):integer; {项处理}var mulop,t1place,t2place,t:integer;function fact(sys:symset):integer; {因子处理}var i,j,k,f,f1,t1:integer;queue:array[1..5] of integer; {存实参队列}begintest([27,21,22],sys,6);if kind=21 then {变量}begini:=entry(id);if i=0 then begin error(11);scanner endelsewith table[i] docase cat of2:beginj:=val;fact:=j+10000;scanner end;{常数} 18:begin j:=lev-level; k:=addr; {lev当前层次} fact:=100*j+k;scanner; {变量地址}end;7: begin scanner;f:=1; {函数调用}if kind=27 then {'<'} beginscanner; k:=4; {k+1是形参开始单元} queue[f]:=exp([28,23]+sys);{')',','}while kind=23 do beginscanner; f:=f+1; queue[f]:=exp([28,23]+sys);end; if kind=28 then {')'} beginscanner;for f1:=1 to f do {传递实在参数} gen(ass,queue[f1],0,dp+k+f1) end else error(22) end; f:=lev-level; {f为相对当前的外层层次} gen(jsr,0,f,addr); {调函数} t1:=newtemp; gen(ass,dp,0,t1); {返回结果在dp单元} fact:=t1; {函数结果作为因子} end end {case} end elseif kind=22 then {数}begin fact:=10000+num;scanner end elseif kind=27 then {'(',表达式)beginscanner;j:=exp([28]+sys);if kind=28 then scanner else error(22);fact:=j;end;test(sys,[27],23);end;begin {项}t1place:=fact(sys+[3,36,37]);{div,*,/}while kind in [3,36,37] dobegin mulop:=kind;scanner;t2place:=fact(sys+[3,36,37]);t:=newtemp;if mulop=36 then gen(mul,t1place,t2place,t)else gen(did,t1place,t2place,t);t1place:=t;end;term:=t1place;end;begin {表达式}if kind in [32,33] then {单目+or-}begin addop:=kind;scanner;e1place:=term(sys+[34,35]);{ 双目+or-}if addop=33 thenbegin t:=newtemp;gen(umi,e1place,0,t);e1place:=t;endendelse e1place:=term(sys+[34,35]);while kind in [34,35] dobeginaddop:=kind;scanner;e2place:=term(sys+[34,35]);t:=newtemp;if addop=34 then gen(add,e1place,e2place,t)else gen(sub,e1place,e2place,t);e1place:=t;end;exp:=e1place;end;procedure condition(var tc,fc:integer;sys:symset); {条件表达式处理} var cond1,cond2,relop:integer;begincond1:=exp([38,43]+sys);if not(kind in [38,43]) thenbegin error(20);scanner endelse begin relop:=kind;scanner;cond2:=exp([38,43]+sys);tc:=cp;case relop of38:gen(jeq,cond1,cond2,0);39:gen(jlt,cond1,cond2,0);40:gen(jgt,cond1,cond2,0);41:gen(jne,cond1,cond2,0);42:gen(jle,cond1,cond2,0);43:gen(jge,cond1,cond2,0);end;fc:=cp;gen(jmp,0,0,0);endend;beginif kind=21 then {赋值语句}begin i:=entry(id);if i=0 then begin error(11);scanner end elseif table[i].cat <>18 thenif table[i].cat=7 then k:=0 elsebegin error(12);i:=0 end {把赋值给常量错}else begin j:=lev-table[i].level;k:=100*j+table[i].addrend;scanner;if kind=44 then {:=}begin scanner; place:=exp(sys);gen(ass,place,0,k); schain:=0; end else error(13);end elseif kind =8 thenbeginscanner;condition(ttc,ffc,sys+[16]);if kind=16 thenbegin scanner;bp(ttc,nxq);statement(slchain,sys);end else error (16);if kind=5 thenbegin scanner;q:=nxq;gen(jmp,0,0,0);bp(ffc,nxq); slchain:=merg(slchain,q);statement(s2chain,sys); end else schain:=merg(ffc,slchain);end elseif kind=19 thenbeginscanner;q:=nxq;condition(ttc,ffc,sys+[4]);if kind=4 then {'do'} begin scanner; bp(ttc,nxq); statement(slchain,sys);bp(slchain,q);gen(jmp,0,0,q);schain:=ffc;end else error(18);end elseif kind =1 thenbeginscanner;statement(schain,sys);while kind=24 do {';'} begin scanner;bp(schain,nxq);statement(schain,sys);end;if kind=6 then {'end'}beginscanner;bp(schain,nxq);schain:=0 endelse error(17); {expected end}end elseif kind=14 then {read 语句}begin scanner;if kind <>27 then error(14) elsebegin scanner;if kind=21 thenbegini:=entry(id);j:=table[i].level;k:=table[i].addr;q:=j*100+k;gen(inp,0,0,q);scanner;while kind=23 do {','} beginscanner; if kind =21 then begin i:=entry(id);j:=table[i].level; k:=table[i].addr;q:=j*100+k;gen(inp,0,0,q)end else error(4); scanner;end;if kind=28 then scanner else error(22) {')'}end else error(4);end;schain:=0;end elseif kind=20 then {write 语句}begin scanner;if kind<>27 then error(14) elserepeatscanner;place:=exp([28,23]+sys);gen(out,0,0,place);until kind<>23;if kind<>28 then error(22);scanner;schain:=0end;test(sys,[],19); {空语句自动匹配}end;begin {'blk' 分程序处理}dp:=5;tp0:=tp;table[tp].addr:=cp;cp0:=cp;gen(jmp,0,0,0); {跳过函数说明的语句体代码}if kind=27 then {'('} {处理形参说明}begin scanner;vardec;while kind=23 do {','}begin scanner;vardec; end;if kind=25 thenbegin scanner;if(kind=9) or (kind=15) then scanner else error(25); end;if kind=28 then scanner else error(22); {')'}end;if kind=25 then {':'}begin scanner;if(kind=9) or (kind=15) then scanner else error(25); end; {type is integer or real?}if kind=24 then scanner else error(5); {';'}if kind=2 then {'const'} {处理常量说明}begin scanner;repeat scanner;while kind=23 do {','}begin scanner;constdec end;if kind=24 then scanner else error(5) {';'}until kind<>21;end;if kind=18 then {'var'} {处理变量说明}begin scanner;repeat vardec;while kind=23 do {','}begin scanner;vardec end;if kind=25 then {':'}begin scanner;if(kind=9) or (kind=15) then scanner else error(25) end;{integer or real}if kind=24 then scanner else error(5)until kind<>21;end;while kind=7 do {'function'} {处理函数说明}begin scanner;if kind=21 thenbegin fill(7);scanner endelse error(4);blk(lev+1,tp,[24]+sys); {递归调用blk}if kind=24 then {';'}begin scanner;test([1,7],[8,19,21]+sys,6){s1=begin,function}endelse error(5);end;test([1],[8,19,21]+sys,7);{s2=if,while,indent,'.','.';'}bp(cp0,nxq);table[tp0].addr:=cp; {cp作为函数入口序号}cp0:=cp;gen(prt,0,0,dp);if kind =1 then {'begin'} {复合语句}beginstatement(chain,[24,6,5,1,8,19,21]+sys);{s=follow(s)+first(s)}if(kind=24) or (kind=26) then {';','.'}begin bp(chain,nxq);gen(ret,0,0,0);endelse error(5);endelse error(8);test(sys,[8,19,21,1,14,20],8);{s2=first(s)}listquad;{listtable} {调试用}end;{0uses wincrt,windos;}procedure interpret;{解释程序}const stacksize=300;cxmax=200;var m:instruction;s:array[0..stacksize]of integer;{data stack area} tp:array[0..10] of integer;{temp variable stack area} p,t,b,t1:INTEGER;K,K0,K1:INTEGER;term1,term2,term3,order:integer;f1,f2:boolean;f:text;function base(n:integer):integer;{找直系静态外层数据区首址} var b1:integer;beginb1:=b;while n>0 dobegin b1:=s[b1-1];n:=n-1 end;base:=b1end;procedure opd(k:integer;var opd1:integer;var flag:boolean); {分析操数作并转化成相应值}var k0,k1:integer;beginflag:=false;if k<1000 then {变量}begin k1:=k div 100;k0:=k mod 100;opd1:=s[base(k1)+k0]endelse if k<2000 then {临时变量}beginopd1:=tp[t1];t1:=t1-1;flag:=true end;opd1:=k-10000; {常量}end;{end; }begint:=0;b:=0;p:=1;t1:=1;s[0]:=0;s[1]:=0;s[2]:=0;s[3]:=0;s[4]:=0; repeatm:=quad[p];p:=p+1;f1:=false;f2:=false;with m dobegin if op=jmp then p:=resultelse if op=prt then t:=result {t 为当前数据区的top+1}else if (op=ass) or(op=umi) thenbegin opd(arg1,term1,f1);if op=umi then term1:=-term1;if result<1000 thens[base(result div 100)+result mod 100]:=term1else begin t1:=t1+1; tp[t1]:=term1 end;end elseif(op=add)or(op=sub)or(op=mul)or(op=did) thenbeginopd(arg1,term1,f1);opd(arg2,term2,f2);if (f1=true)and(f2=true)thenbeginterm3:=term1;term1:=term2;term2:=term3 end;if op=add then term3:=term1+term2else if op=sub then term3:=term1-term2else if op=mul then term3:=term1*term2else term3:=term1 div term2;if result<1000 then s[base(result div 100)+result mod 100]:=term3else begin t1:=t1+1;tp[t1]:=term3 end;end else if(op=jeq)or(op=jgt)or(op=jlt)or(op=jge)or(op =jle)or(op=jne)thenbeginopd(arg1,term1,f1);opd(arg2,term2,f2);if (f1=true)and(f2=true)thenbeginterm3:=term1;term1:=term2;term2:=term3 end;if op=jgt thenbegin if ord(term1>term2)=1 then p:=result endelse if op=jeq thenbegin if ord(term1=term2)=1 then p:=result endelse if op=jlt thenbegin if ord(term1<="" p="" p:="result" then="">else if op=jge thenbegin if ord(term1>=term2)=1 then p:=result endelse if op=jle thenbegin if ord(term1<=term2)=1 then p:=result endelse if ord(term1<>term2)=1 then p:=resultend elseif op=inp thenbegin writeln('input one number!');readln(s[base(result div 100)+(result mod 100)]);end elseif op=out thenbeginopd(result,term1,f1);writeln(term1);end elseif op=jsr thenbegins[t+1]:=base(arg2);s[t+2]:=b;s[t+3]:=p;b:=t;p:=result;{保存静态、动态链和返回地址,建立新数据区和pc}end elseif op=ret then begin t:=b;p:=s[t+3];b:=s[t+2] end{回到老数据区和老pc}end;until p=0;writeln('end');end;begin {main}reserve[0]:='and '; reserve[1]:='begin '; reserve[2]:='const '; reserve[3]:='div '; reserve[4]:='do '; reserve[5]:='else '; reserve[6]:='end '; reserve[7]:='function '; reserve[8]:='if '; reserve[9]:='integer '; reserve[10]:='not '; reserve[11]:='or '; reserve[12]:='procedure';reserve[13]:='program ';reserve[14]:='read '; reserve[15]:='real '; reserve[16]:='then '; reserve[17]:='type '; reserve[18]:='var '; reserve[19]:='while '; reserve[20]:='write ';mnemonic[jmp]:='jmp';mnemonic[prt]:='prt';mnemonic[jeq]:='jeq';mnemonic[jne]:='jne';mnemonic[jgt]:='jgt';mnemonic[jlt]:='jlt';mnemonic[jge]:='jge';mnemonic[jle]:='jle';mnemonic[add]:='add';mnemonic[sub]:='sub';mnemonic[mul]:='mul';mnemonic[did]:='did';mnemonic[ass]:='ass';mnemonic[umi]:='umi';mnemonic[jsr]:='jsr';mnemonic[ret]:='ret';new:=1000;write('Please input source program filename:'); readln(filename);assign(f,filename);reset(f);cc:=0; ii:=0;ch:=' ';scanner;while kind<>26 do {'.'}beginwrite(kind,' ');l:=l+1;{if(l mod 10)=0 then writeln;}scanner;end;{上面一段程序用语产生词法分析结果,分调用!}if kind=13 then scanner else error(0);{分析程序首部} if kind=21 then scanner else error(4);if kind=27 thenbeginrepeatscanner;until kind=28;if kind=28 then scanner else error(22)end;if kind<>24 then error(5);cp:=1;tp:=0;blk(0,0,[26]);{'.'}{分析分程序}if kind<>26 then error(9);close(f);if err=0 then interpret; end.。
IF-ELSE条件语句的翻译程序设计(LR方法、输出四元式)

I F-E L S E条件语句的翻译程序设计(L R方法、输出四元式) -CAL-FENGHAI-(2020YEAR-YICAI)_JINGBIAN目录1 系统描述(问题域描述) (3)2 文法及属性文法的描述 (3)2.1文法 (3)2.2 属性文法 (3)3 语法分析方法描述及语法分析表设计 (4)3.1语法分析方法描述 (4)3.1.1 LR方法的基本思想 (4)3.1.2 LR分析器模型 (5)3.2语法分析表设计 (6)4中间代码形式的描述及中间代码序列的结构设计 (7)4.1中间代码形式的描述 (7)4.2中间代码序列的结构设计 (7)5 编译系统的概要设计 (8)6 详细的算法描述 (10)6.1系统流程图 (10)6.2算法描述 (10)7 软件的测试方法和测试结果 (21)7.1软件的测试方法 (21)7.2测试结果 (21)8设计的特点、不足、收获与体会 (25)8.1特点与不足 (25)8.2收获与体会 (25)9 参考文献 (26)10本科生课程设计成绩评定表 (22)IF-ELSE条件语句的翻译程序设计(LR方法、输出四元式)1 系统描述(问题域描述)对条件语句: if 〈布尔表达式〉then〈赋值语句〉 else 〈赋值语句〉,进行词法,LR(1)语法分析,并根据语法制导翻译方法将条件语句翻译成四元式中间代码形式,最后输出翻译后的四元式代码。
2 文法及属性文法的描述2.1文法G[S]: S->CSS->TSS->AC->if E thenT->CS elseT->else其中,E代表布尔表达式,可由界符()括起来,A代表赋值表达式。
在这里E、A都代表终结符,具体的表达式在程序会判断其类型。
2.2 属性文法S->C S{S.clain:=merge(C.clain,S.clain)}S->T S{ S.clain:=merge(T.clain,S.clain)}S->A{S.clain:0/* 空链 */}C->if E then{backpatch(E.true,nextstat) C.clain:=E.false}T->C S else{ q:=nextstatEmit(‘GOTO’—)Backpatch(C.clain,nextstat)T.clain:=merge(S.clain,q)}3 语法分析方法描述及语法分析表设计3.1语法分析方法描述3.1.1 LR方法的基本思想一个LR分析器实质上是一个带先进后出存储器的确定有限状态自动机。
小型编译程序高级语言到四元式的编译

~小型编译程序:高级语言到四元式的编译#include "" /*如果使用TC的话,需要配置头文件路径*/#include ""#define ACC -2/************************/#define sy_if 0#define sy_then 1#define sy_else 2`#define sy_while 3#define sy_begin 4#define sy_do 5#define sy_end 6#define a 7#define semicolon 8#define e 9#define jinghao 10&#define S 11#define L 12#define tempsy 15#define EA 18 /*E and*/#define E0 19 /E or*/#define plus 34##define times 36#define becomes 38#define op_and 39#define op_or 40#define op_not 41#define rop 42#define lparent 48"#define rparent 49#define ident 56#define intconst 57/*********************************/char ch='\0'; /*从字符缓冲区读取当前字符*/int count=0; /*词法分析结果缓冲区计数器*/static char spelling[10]={""}; /*存放识别的字*/static char line[81]={""}; /*一行字符缓冲区,最多80个字符*/.char *pline; /*字符缓冲区指针*/static char ntab1[100][10]; /*变量名表,共100项,每项长度10*/struct ntab{int tc; /*真值*/int fc; /*假值*/}ntab2[200]; /*在布尔表达式E中保存有关布尔变量的真、假值*/、int label=0; /*指向ntab2的指针*/struct rwords{ /*存放临时变量的表的定义*/char sp[10];int sy;};/*(保留字表)匹配表的结构,用来与输入缓冲区中的单词进行匹配*/(/*匹配表初始化,大小为10*/struct rwords reswords[10]={{"if",sy_if},{"do",sy_do},{"else",sy_else},{"while",sy_while},{"then",sy_then},{"begin",sy_begin},{"end",sy_end},}{"and",op_and},{"or",op_or},{"not",op_not}};struct aa{int sy1; /*存放名字*/int pos; /*存放名字所对应的地址*/}buf[1000], /*词法分析结果缓冲区*/|n, /*读取二元式的当前字符*/n1, /*当前表达式中的字符*/E, /*非终结符*/sstack[100], /*算术或布尔表达式加工处理使用的符号栈*/ ibuf[100], /*算术或布尔表达式使用的缓冲区*/stack[1000]; /*语法分析加工处理使用的符号栈*/struct aa oth; /*四元式中空白位置*//struct fourexp{char op[10];struct aa arg1;struct aa arg2;int result;}fexp[200]; /*四元式的结构定义*/int ssp=0; /*指向sstack栈指针*/$struct aa *pbuf=buf; /*指向词法分析缓冲区的指针*/int nlength=0; /*词法分析中记录单词的长度*/int lnum=0; /*源程序行数记数,源程序长度*/int tt1=0; /*变量名表指针*/FILE *cfile; /*源程序文件,~为结束符*//*FILE *mfile;*/>int newt=0; /*临时变量计数器*/int nxq=100; /*nxq指向下一个形成的四元式的地址*//*每次执行gen()时,地址自动增1*/int lr; /*扫描LR分析表1过程中保存的当前状态值*/int lr1; /*扫描LR分析表2或表3所保存的当前状态值*/ int sp=0; /*查找LR分析表时状态栈的栈顶指针*/int stack1[100]; /*状态栈1的定义*/!int sp1=0; /*状态栈1的栈顶指针*/int num=0; /*算术或布尔表达式缓冲区指针*/struct ll{int nxq1; /*记录下一条四元式的地址*/int tc1; /*真值链*/int fc1; /*假值链*/}labelmark[10]; /*记录语句嵌套层次的数组,*//*即记录嵌套中每层的布尔表达式E的首地址*/ %int labeltemp[10]; /*记录语句嵌套层次的数组,*//*即记录每层else之前的四元式地址*/int pointmark=-1, /*labelmark数组指针*/pointtemp=-1; /*labeltemp数组指针*/int sign=0; /*sign=1,为赋值语句;sign=2,为布尔表达式。
DOWHILE循环语句的翻译程序设计(简单优先法输出四元式)

(二)DO-WHILE循环语句的翻译程序设计(简单优先法、输出四元式)一、1.简单优先法的基本思想根据优先关系的定义,将简单优先文法中各文法符号之间的这种关系用一个矩阵表示,称作简单优先矩阵。
PDA读入一个单词后,比较栈顶符号和该单词的优先级,若栈顶符号优先级低于该单词,继续读入;若栈顶符号优先级高于或等于读入符号,则找句柄进行归约,找不到句柄就继续读入。
直到最后栈内只剩下开始符号,输入串读到“#”为止。
此时识别正确。
可分点描述如下:(1)、对句型中相邻的文法符号规定优先关系,以寻找句型中的句柄;(2)、规定句柄内各相邻符号之间具有相同的优先级;(3)、规定句柄两端符号优先级要比位于句柄之外而又和句柄相邻的符号的优先级高,以先归约句柄;(4)、对于文法中所有符号,只要它们可能在某个句型中相邻,就要为它们规定相应的优先关系,若某两个符号永远不可能相邻,则它们之间就无关系.2.简单优先矩阵用于表示文法符号之间的简单优先关系的矩阵。
3.简单优先法的优缺点优点:技术简单,当做简单优先矩阵是要求较短。
缺点:适用范围小,分析表尺寸太大。
二、源代码实现:#include<iostream>#define MAX 35#include<list>#include<string>#include<fstream>using namespace std;#define TABLE_LEN 8#define STR_LEN 256int zhlen;char sTable[TABLE_LEN+1] = {"+-*/()i#"};//顺序索引int ShipTable[TABLE_LEN][TABLE_LEN] = //优先表{{ 1, 1,-1,-1,-1, 1,-1, 1},{ 1, 1,-1,-1,-1, 1,-1, 1},{ 1, 1, 1, 1,-1, 1,-1, 1},{ 1, 1, 1, 1,-1, 1,-1, 1},{-1,-1,-1,-1,-1, 0,-1,-2},{ 1, 1, 1, 1,-2, 1,-2, 1},{ 1, 1, 1, 1,-2, 1,-2, 1},{-1,-1,-1,-1,-1,-2,-1, 0}};char X,a;char VN[11]={'K','L','P','S','E','G','T','R','F','Q','\0'};char VT[15]={'i','=','<','>','+','-','*','/','(',')','d','w',';','#','\0'};charp[18][6]={"dLwS\0","SP\0",";SP\0","\0","iQE\0","TG\0","+TG\0","-TG\0","\0","FR\0","*FR\0","/FR\0","\0","(E)\0","i\0","=\0","<\0",">\0"};char stack[MAX];char queue[MAX];int sp,front;intM[10][14]={ {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,-1,-1,-1},{1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3,2,-1},{4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{5,-1,-1,-1,-1,-1,-1,-1,5,-1,-1,-1,-1,-1},{-1,-1,-1,-1,6,7,-1,-1,-1,-1,-1,8,8, 8},{9,-1,-1,-1,-1,-1,-1,-1,9,-1,-1,-1,-1,-1},{-1,-1,-1,-1,12,12,10,11,-1,-1,-1,12,12,12},{14,-1,-1,-1,-1,-1,-1,-1,13,-1,-1,-1,-1,-1},{-1,15,16,17,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},};int f=0; int count=0;int c=0;char arr_i[MAX];char var[MAX]; //表格管理int td[MAX]; int t=0;int opd=-1;int opr=-1;int id=0;int d=0;char arr[MAX][4];//存放待输出的四元式//char keyword[2][7]={"do\0","while\0"};bool IsCharInStr(char c,char s[]){for(int i=0;s[i]!='\0';i++){if(s[i]==c)return true;}return false;}int GetIndex(char s[],char c){for(int i=0;s[i]!='\0';i++){if(c==s[i])return i;}return -1;}//string GetSubString(char s[],int from,int to){string st;for(int i=from;i<to;i++){st+=s[i];}return st;}/*******************************************翻译赋值表达式********************************************/void translatefuzhi(char *sInput){//栈结构的初始化char Stack[STR_LEN]={0};int index = 0;int top = 1;Stack[0] = '#';list<char> rPolish;list<string> Num;int begin=0;while(sInput[begin]!='='){if(IsCharInStr(sInput[begin],sTable)){cout<<"Equal expression is illegal!"<<endl;return ;}begin++;}Num.push_back(GetSubString(sInput,0,begin));int now = begin+1;int before = begin;rPolish.push_back('i');while(sInput[now]!='\0'){if(IsCharInStr(sInput[now],sTable)){char temp[3]={0};if(now-before>1){temp[0] = 'i';temp[1] = sInput[now];Num.push_back(GetSubString(sInput,before+1,now));}else{temp[0] = sInput[now];}int i=0;while(temp[i]!=0){int left = GetIndex(sTable,Stack[index]);int right = GetIndex(sTable,temp[i]);switch(ShipTable[left][right]){case -1://移入Stack[top++] = temp[i];index = top-1;i++;break;case 0://脱括号if(Stack[index]=='('){Stack[top++] = ')';Stack[index] = 'E';top = index+1;index--;}else//规约{if(top!=2){return;}rPolish.push_back('=');list<char>::iterator iter;list<string>::iterator siter=Num.begin();string fuzhi[256];int d=0,m;for(iter=rPolish.begin();iter!=rPolish.end();iter++){if(*iter=='i'){fuzhi[d++]=*siter;siter++;}else{fuzhi[d++]=*iter;}}m=d;string op1,op2;int flag,xiabiao=0;for(d=0;d<m;d++)cout<<"("<<fuzhi[d]<<","<<op1<<","<<op2<<","<<"T"<<xiabiao<<")"<<endl;fuzhi[d] = "T";fuzhi[d]+=(xiabiao+'0');xiabiao++;}//cout<<fuzhi[d];}return;}i++;break;case 1://归约if(Stack[index]=='i'){rPolish.push_back('i');Stack[index] = 'E';index--;}else{rPolish.push_back(Stack[index]);Stack[index-1] = 'E';top = index;index-=2;}break;default:return;}}before=now;}now++;}}int len(char str[]){int i=0;while(str[i]!='\0')i++;return i;}int index(char ch,char str[]){int i=0;while(str[i]!='\0'){if(ch!=str[i])i++;else break;}if(str[i]=='\0')return -1;return i;}void err(int n){if(n==1)cout<<"字符不匹配"<<endl;else if(n==2)cout<<"字符没有出现在产生式中"<<endl;else if(n==3)cout<<"没有找到合适的¨选产式"<<endl;else cout<<"该句子是文法语言的句子"<<endl;}void print(){cout<<"(";if(count<10)cout<<'0';cout<<count<<")";int i;for(i=0;i<=sp;i++)cout<<stack[i];for(;i<=20;i++)cout<<" ";for(i=0;i<front;i++)cout<<" ";for(;queue[i]!='#';i++)cout<<queue[i];cout<<queue[i];for(;i<=20;i++)cout<<" ";}void semantic(){if(VT[opr]=='='){arr[d][0]='=';arr[d][1]=arr_i[opd];arr[d][2]=id;arr[d][3] ='--';id++;}elseif(opr==-2){arr[d][0]='=';arr[d][1]=id-1;arr[d][2]=arr_i[opd];arr[d][3]='--';} else {arr[d][0]=VT[opr];arr[d][1]=arr_i[opd];arr[d][2]=id;if(VT[opr]!='<'&&VT[opr]!='>')arr[d][3]=id-1;else arr[d][3]=id+1;id++;} d++;}void syntax(){//语法分析int n;count++;print();X=stack[sp];a=queue[front];if(X=='#'&&a=='#')f=4;if(X<'A'||X>'Z'){if(X==a){sp--;front++;if(a!='i'){if(a!='d'&&a!='w'&&a!=';'&&a!='#'){opr=index(a,VT);semantic();}else if(a==';'||a=='w'||a=='#'){opr=-2;semantic();}cout<<'\t'<<'\''<<a<<"'匹配"<<endl;}else {opd=c;cout<<'\t'<<'\''<<arr_i[c++]<<"'匹配"<<endl;}}else f=1;}else {int tx=index(X,VN);int ta=index(a,VT);n=M[tx][ta];td[t++]=M[tx][ta];if(ta==-1){f=2;cout<<a<<endl;}else if(n==-1)f=3;else {sp--;cout<<'\t'<<X<<"->";if(len(p[n])!=0){for(inti=len(p[n])-1;i>=0;i--){stack[++sp]=p[n][i];cout<<p[n][len(p[n])-1-i];} cout<<endl;}else cout<<"空串"<<endl;}}if(f==0)syntax();else {td[t]='-1';err(f);}}void lexical(){ //词法分析int i,j,d;char ch;j=d=0;for(i=0;var[i]!='#';i++){ch=var[i];if(ch=='d'&&var[i+1]=='o'){cout<<"do"<<'\t'<<"keword"<<endl;queue[j++]='d' ;i+=1;}else if(ch=='w'){ch=var[i+1];if(ch=='h'){ch=var[i+2];if(ch=='i'){ch=var[i+3];if(ch=='l'){ch=var[i+4];if(ch=='e'){ch=var[i+5];}}}}cout<<"while"<<'\t'<<"keyword"<<endl;queue[j++]='w';i+=4;}else if(index(ch,VT)<=0){if(ch!='{'&&ch!='}'&&ch!='('&&ch!=')'){cout<<ch<<'\t'<<"variable:i["<<d++< <"]"<<endl;arr_i[d-1]=ch;queue[j++]='i';}else cout<<ch<<'\t'<<"bound"<<endl;}elseif(index(ch,VT)>0){cout<<ch<<'\t'<<"operator"<<endl;queue[j++]=ch;} }queue[j]='#';for(i=0;queue[i]!='#';i++)cout<<queue[i];cout<<endl;}int main(){int i=0,j=0;int len,length;char temp;char S='K';sp=front=0;stack[0]='#';sp++;stack[1]='K';cout<<" ****************************"<<endl;cout<<" * DO-WHILE循环语句 *"<<endl;cout<<" * (简单优先法输出四元式) *"<<endl;cout<<" ****************************"<<endl;ifstream table;table.open("dowhile.txt");if(!table){cout<<"error!";}table.seekg(0,ios::end);length = table.tellg();table.seekg(0,ios::beg);while(length!=table.tellg()){table.read((char*)&temp,1);var[i]=temp;i++;if(var[i]==' ')i--;if(var[i]=='#')break;}table.close();len=i;var[i]='\0';cout<<"词法分析"<<endl;lexical();char fuzhi[20];int flag1,fuzhilen;int s=0; for(i=0;i<len;i++){if(var[i]==';'){flag1=i;}}fuzhilen=flag1-2;for(i=3;i<flag1;i++){fuzhi[s++]=var[i];}fuzhi[s]='#';char shuru;char zh[100];int kaishi=0;zh[0]='d';for(kaishi=1;kaishi<s+1;kaishi++){zh[kaishi]=fuzhi[kaishi-1];}zh[kaishi++]=';';zh[kaishi++]='W';for(i=flag1+8;i<len;i++){if(var[i]=='}')break;else{zh[kaishi++]=var[i];}}zh[kaishi++]='#';zhlen=kaishi;cout<<"输出四元式"<<endl;cout<<"do"<<endl;translatefuzhi(fuzhi);cout<<"("<<var[flag1+9]<<","<<var[flag1+8]<<","<<var[flag1+10]<<","<<"T2"< <")"<<endl;cout<<"if T2=true goto T0"<<endl;return 0;}三、测试结果:词法分析部分:输出四元式:四、课程小结:这次编译原理课程设计的题目是用简单优先分析法进行DO-WHILE循环语句的语法分析,并输出四元式.设计的特点是利用定义每个终极符和非终极符之间优先关系,来进行符号的移进与规约,如果栈顶符号优先级低于该单词,继续读入;若栈顶符号优先级高于或等于读入符号,则找句柄进行归约,找不到句柄就继续读入。
(完整)编译原理实验报告(词法分析器 语法分析器)

编译原理实验报告实验一一、实验名称:词法分析器的设计二、实验目的:1,词法分析器能够识别简单语言的单词符号2,识别出并输出简单语言的基本字。
标示符。
无符号整数.运算符.和界符。
三、实验要求:给出一个简单语言单词符号的种别编码词法分析器四、实验原理:1、词法分析程序的算法思想算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号.2、程序流程图(1)主程序(2)扫描子程序3、各种单词符号对应的种别码五、实验内容:1、实验分析编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符.字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。
2 实验词法分析器源程序:#include 〈stdio.h〉#include <math.h>#include <string。
h>int i,j,k;char c,s,a[20],token[20]={’0’};int letter(char s){if((s〉=97)&&(s〈=122)) return(1);else return(0);}int digit(char s){if((s〉=48)&&(s<=57)) return(1);else return(0);}void get(){s=a[i];i=i+1;}void retract(){i=i-1;}int lookup(char token[20]){if(strcmp(token,"while")==0) return(1);else if(strcmp(token,"if")==0) return(2);else if(strcmp(token,"else”)==0) return(3);else if(strcmp(token,"switch”)==0) return(4);else if(strcmp(token,"case")==0) return(5);else return(0);}void main(){printf(”please input string :\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!=’#’);i=1;j=0;get();while(s!=’#'){ memset(token,0,20);switch(s){case 'a':case ’b':case ’c':case ’d':case ’e’:case ’f’:case 'g’:case ’h':case 'i':case ’j':case 'k’:case ’l':case 'm’:case 'n':case ’o':case ’p':case ’q’:case 'r’:case 's’:case 't’:case ’u’:case ’v’:case ’w’:case ’x':case ’y':case ’z’:while(letter(s)||digit(s)){token[j]=s;j=j+1;get();}retract();k=lookup(token);if(k==0)printf("(%d,%s)”,6,token);else printf("(%d,—)",k);break;case ’0':case ’1’:case ’2':case ’3':case '4’:case '5’:case ’6':case ’7’:case ’8’:case '9’:while(digit(s)){token[j]=s;j=j+1;get();}retract();printf(”%d,%s",7,token);break;case '+':printf(”(’+',NULL)”);break;case ’-':printf("(’-',null)");break;case ’*':printf(”('*’,null)");break;case '<':get();if(s=='=’) printf(”(relop,LE)”);else{retract();printf("(relop,LT)");}break;case ’=':get();if(s=='=’)printf("(relop,EQ)");else{retract();printf(”('=',null)”);}break;case ’;':printf(”(;,null)");break;case ' ’:break;default:printf("!\n”);}j=0;get();} }六:实验结果:实验二一、实验名称:语法分析器的设计二、实验目的:用C语言编写对一个算术表达式实现语法分析的语法分析程序,并以四元式的形式输出,以加深对语法语义分析原理的理解,掌握语法分析程序的实现方法和技术.三、实验原理:1、算术表达式语法分析程序的算法思想首先通过关系图法构造出终结符间的左右优先函数f(a),g(a)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《编译原理》实验报告
班级学号
姓名
成绩
指导教师
2012 年 7 月
实验一
1实验时间: 2012-07-07
2实验地点: 6#503
3实验题目:算术表达式到四元式翻译的编译程序设计
4实验目的:
该实验的目的是让学生掌握程序设计语言编译程序构造的一般原理、基本设计方法、主要实现技术和一些自动构造的工具。
通过该实验的学习,使我们较好的掌握编译原理的基本原理和基础技术、编译原理中涉及的基本算法、基本构造和主要实现技术,从而让我们了解将高级程序设计语言源程序编译成计算机能处理的目标代码语言的整个过程,基本掌握计算机系统软件之一编译程序的构造原理及相关技术,同时,还可以提高我们计算机专业素质,培养我们的抽象思维能力。
5实验内容:
设计内容及要求:设计一个语法制导翻译器,将算术表达式翻译成四元式。
要求:先确定一个定义算术表达式的文法,为其设计一个语法分析程序,为每条产生式配备一个语义子程序,按照一遍扫描的语法制导翻译方法,实现翻译程序。
对用户输入的任意一个正确的算术表达式,程序将其转换成三.四元式输出(可按一定格式输出到指定文件中)。
6实验预习:
四元式是一种更接近目标代码的中间代码形式。
由于这种形式的中间代码便于优化处理,因此,在目前许多编译程序中得到了广泛的应用。
具体的形式犹如:(1)(op,arg1,arg2,result)
例如,语句a=b+(c-d)*e+f/g*(h-i+j/(k+l*m-n))的四元式表示如
1).检查输入的元素;
2).如果是一个操作数,则进栈;
3).如果是操作符,则
i). 如果符号栈不为空或者此操作符的优先级大于符号栈栈顶的优先级,则将此运算符压栈;
ii).如果符号栈不为空或者此操作符的优先级小于符号栈栈顶的优先级,栈顶操作符出栈并进行相应的操作;
4).假定输入完毕,栈中剩余的所有操作符出栈并进行相应操作。
7总体设计描述:
按照顺序将任意一个正确的算术表达式拆分成操作符和操作数部分并入栈,如后比较优先级按照优先级高低出栈,执行操作
将算术表达式转换成四元式输出。
本程序共有两个函数,一个将算术表达式翻译成四元式的函数int translate(string s),是本程序的主要函数;另一个是主函数,负责调用翻译函数和输入输出处理
运行步骤与结果:
程序清单:
#include "string.h"
#include "stdio.h"
char w;
int j=1;
struct TOKEN
{
char t;
int i;
} ;
struct TOKEN word, sem[10];
int i_sem;
struct QT
{
char w;
struct TOKEN word1; struct TOKEN word2; struct TOKEN temp; } ;
char exp[50];
int i=0;
struct QT qt[30];
int q=0;
int D();
int E();
int T();
int F();
void next();
void newt();
void quat(char);
int main()
{
clrscr();
printf("please input your expression: "); scanf(" %s",exp);
next();
D();
if (w=='\0')
{
printf("\n");
for (i=0;i<q;i++)
{
printf(" (%d) ",i+1);
if(qt[i].w!='='){
printf(" ( %c",qt[i].w);
if (qt[i].word1.t!='t')
printf(" , %c",qt[i].word1.t);
else
printf(" , %c%d",qt[i].word1.t,qt[i].word1.i);
if (qt[i].word2.t!='t')
printf(" , %c",qt[i].word2.t);
else
printf(" , %c%d",qt[i].word2.t,qt[i].word2.i);
printf(" , %c%d )\n",qt[i].temp.t,qt[i].temp.i); }
else
{
printf(" ( %c",qt[i].w);
printf(" , %c%d ",qt[i-1].temp.t,qt[i-1].temp.i);
printf(" , _");
printf(" , %c)",qt[i].word1.t); }
}
getch();
}
else printf("err");
printf("\nHello World!\n"); return 0;
}
int D()
{
char w0;
E();
while ( w=='=')
{
w0=w;
next();
E();
quat(w0);
}
return 1;
}
int E()
{
char w1;
T();
while ( w=='+' || w=='-') {
w1=w;
next();
T();
quat(w1);
}
return 1;
}
int T()
{
char w2;
F();
while ( w=='*' || w=='/') {
w2=w;
next();
F();
quat(w2);
}
return 1;
}
int F()
{
if ( w=='(')
{
next();
E();
if ( w!=')')
{
printf("err");
return 0;
}
}
else if ((w>='a' && w<='z')||(w>='0' && w<='9')) {
word.t=w; word.i=0 ;
sem[++i_sem]=word;
}
else
{
printf("err");
return 0;
}
next();
return 1;
}
void next()
{
w=exp[i];
i++;
}
void newt()
{
word.t='t';
word.i=j++;
}
void quat(char ww)
{
newt();
qt[q].w=ww;
qt[q].word1=sem[i_sem-1];
qt[q].word2=sem[i_sem];
qt[q].temp=word;
i_sem--;
i_sem--;
sem[++i_sem]=word;
q++;
}
8 实验总结:
编译原理课程对实践的要求比较高,所以实验课是培养我们实践能力的重要环节,是巩固和验证所学理论知识,培养学生分析能力的重要环节。
因此为了能达到好的效果,积极的促进我们对原理的理解,我们可以认真的设计实验内容,同时也达到了一
定的效果。
同时加深了我对词法分析和语法分析的理解,而且提高额C,C#的编程水平,有助于编译原理课程的学习。
在实验的过程中还发现了自己的许多不足之处,例如对知识理解的不够深刻,掌握得不够牢固,这样就可以从课本上查漏补缺。
除了课本上的知识,还进一步掌握了词法分析和递归子程序语法分析的实现过程。
总之,本次实验,使我获益匪浅。