计算机编译原理实验生成四元式序列.docx
编译原理实验报告
编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。
二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。
三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。
在本次实验中,我们使用有限自动机的理论来设计词法分析器。
首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。
然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。
在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。
(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。
在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。
首先,我们根据给定的语法规则,编写了相应的递归函数。
每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。
在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。
(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。
在本次实验中,我们使用了四元式作为中间代码的表示形式。
在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。
同时,根据语法树的结构,生成相应的四元式中间代码。
(四)代码优化代码优化的目的是提高生成代码的质量和效率。
在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。
通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。
写出如下语句的四元式序列
写出如下语句的四元式序列1.引言1.1 概述在编程语言中,为了对程序进行分析和执行,我们需要将程序转换成计算机能够理解和执行的形式。
而四元式序列就是一种常用的表示方式之一。
四元式序列是由四个元素组成的元组,分别是操作符、操作数1、操作数2和结果。
它可以将复杂的程序语句拆分成更简单的操作,方便计算机进行处理。
在撰写四元式序列时,我们需要根据具体的语句来确定操作符、操作数1、操作数2和结果。
以以下语句为例:pythonx = y + z我们可以将这个语句转换成如下的四元式序列:1. (+, y, z, t1)2. (=, t1, "", x)在这个序列中,第一行的操作符是加号,操作数1和操作数2分别是变量y和z,结果是临时变量t1。
第二行的操作符是赋值号,操作数1是临时变量t1,操作数2为空,结果是变量x。
这样,通过四元式序列的表示,我们可以更清晰地描述程序的执行过程,方便后续的语义分析和执行。
总的来说,四元式序列在程序分析和执行中具有重要的作用,它可以将复杂的程序语句转换成更简单的操作,方便计算机进行处理。
在实际的编程中,我们可以根据具体的语句来编写相应的四元式序列,以达到更高效、更准确地执行程序的目的。
1.2文章结构文章1.2 文章结构文章结构是指文章整体的组织形式,包括各个部分之间的关系和排列顺序。
一个合理的文章结构能够使读者更好地理解文章的主题和内容,提高文章的可读性和逻辑性。
在本文中,我们将主要围绕三个部分展开,分别是引言、正文和结论。
引言部分作为文章的开端,其主要功能是引起读者的兴趣,明确文章的主题和目的。
在引言部分中,我们将对本文的概述进行介绍,简要说明文章的主要内容和结构,并阐述文章撰写的目的。
通过清晰明了地阐述引言部分的内容,能够让读者对后续的内容有一个整体的认识和预期,为接下来的阅读打下基础。
正文部分是文章的核心,也是作者表达观点和论证思路的主要部分。
在正文部分中,我们将围绕两个要点展开,分别是要点一和要点二。
编译原理课程设计——算术表达式、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函数,用来将括号部分替换为大写字母)。
新的式子中,只含有加减乘除以及赋值这四种运算,后根据优先级的不同,逐步生成四元式。
其算法流程图如右图所示。
编译原理语义分析实验报告
实验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#输出结果八、收获(体会)与建议通过此次实验, 让我了解到如何设计、编制并调试语义分析程序, 加深了对语法制导翻译原理的理解, 掌握了将语法分析所识别的语法成分变换为中间代码的语义翻译方法。
编译原理实验报告
《编译原理》实验报告软件131 陈万全132852一、需求分析通过对一个常用高级程序设计语言的简单语言子集编译系统中词法分析、语法分析、语义处理模块的设计、开发,掌握实际编译系统的核心结构、工作流程及其实现技术,获得分析、设计、实现编译程序等方面的实际操作能力,增强设计、编写和调试程序的能力。
通过开源编译器分析、编译过程可视化等扩展实验,促进学生增强复杂系统分析、设计和实现能力,鼓励学生创新意识和能力。
1、词法分析程序设计与实现假定一种高级程序设计语言中的单词主要包括五个关键字begin、end、if、then、else;标识符;无符号常数;六种关系运算符;一个赋值符和四个算术运算符,试构造能识别这些单词的词法分析程序。
输入:由符合和不符合所规定的单词类别结构的各类单词组成的源程序文件。
输出:把所识别出的每一单词均按形如(CLASS,VALUE)的二元式形式输出,并将结果放到某个文件中。
对于标识符和无符号常数,CLASS字段为相应的类别码的助记符;VALUE字段则是该标识符、常数的具体值;对于关键字和运算符,采用一词一类的编码形式,仅需在二元式的CLASS字段上放置相应单词的类别码的助记符,VALUE字段则为“空”。
2、语法分析程序设计与实现选择对各种常见高级程序设计语言都较为通用的语法结构——算术表达式的一个简化子集——作为分析对象,根据如下描述其语法结构的BNF定义G2[<算术表达式>],任选一种学过的语法分析方法,针对运算对象为无符号常数和变量的四则运算,设计并实现一个语法分析程序。
G2[<算术表达式>]:<算术表达式> → <项> | <算术表达式>+<项> | <算术表达式>-<项><项> → <因式> | <项>*<因式> | <项>/<因式><因式> → <运算对象> | (<算术表达式>)若将语法范畴<算术表达式>、<项>、<因式>和<运算对象>分别用E、T、F和i 代表,则G2可写成:G2[E]:E → T | E+T | E-T T → F | T*F | T/F F → i | (E)输入:由实验一输出的单词串,例如:UCON,PL,UCON,MU,ID ······输出:若输入源程序中的符号串是给定文法的句子,则输出“RIGHT”,并且给出每一步分析过程;若不是句子,即输入串有错误,则输出“ERROR”,并且显示分析至此所得的中间结果,如分析栈、符号栈中的信息等,以及必要的出错说明信息。
编译原理报告三四元式
四元式生成一、目的和要求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(除自身外)的任意属性。
编译原理LL1语法分析算法的实现(token转四元式)
编译原理LL1语法分析算法的实现(token转四元式)编译原理LL1语法分析算法的实现(token转四元式)博客分类:•c++/数据结构/算法算法F#J##include <stdio.h>#include <stack>#include <vector>#include <iostream>#include <fstream>#include <malloc.h>using namespace std;//token结构struct token {int code; //token的类别,code为1则是符号,为2则是数字char value; //token的值};typedef struct token tokens;vector<tokens> tokenBuffer; //用于存储token的缓冲区stack<tokens> tokenBuffers;//产生式结构struct formula {int id; //产生式编号char left; //产生式左部char right[256]; //产生式右部int r_length; //产生式右部长度};typedef struct formula formulas;formulas formulaBuffer[11]; //用于存储产生式的缓冲区//四元式结构struct expression {char symbol; //操作符char num1; //第一个操作数char num2; //第二个操作数char result; //结果变量};typedef struct expression expressions;vector<expressions> expressionBuffer; //用于存储四元式的缓冲区int expressionCount = 0; //四元式个数//分析表中每一项的结构struct analysisTable {char currentState; //分析栈的栈顶符号char currentToken; //当前字符int expressionNum; //对应的产生式编号};typedef struct analysisTable analysisT ables;vector<analysisTables> analysisTableBuffer; //LL1分析表的缓冲区stack<char> analysisStack; //分析栈stack<char> sematicStack; //语义栈//初始化LL1分析表void initialAnalysisTableBuffer() { analysisTables* temp1a = new analysisTable; analysisTables* temp1b = new analysisTable; analysisTables* temp1c = new analysisTable; analysisTables* temp2 = new analysisTable; analysisTables* temp3 = new analysisTable; analysisTables* temp4 = new analysisTable; analysisTables* temp5 = new analysisTable; analysisTables* temp6 = new analysisTable; analysisTables* temp7a = new analysisTable; analysisTables* temp7b = new analysisTable; analysisTables* temp7c = new analysisTable; analysisTables* temp8 = new analysisTable; analysisTables* temp9 = new analysisTable; analysisTables* temp10 = new analysisTable; analysisTables* temp11 = new analysisTable; analysisTables* temp12 = new analysisTable; analysisTables* temp13 = new analysisTable; analysisTables* temp14 = new analysisTable; analysisTables* temp15a = new analysisTable; analysisTables* temp15b = new analysisTable; analysisTables* temp15c = new analysisTable; analysisTables* temp16 = new analysisTable;temp1a->expressionNum = 1;temp1a->currentState = 'E';temp1a->currentT oken = 'a';temp1b->expressionNum = 1; temp1b->currentState = 'E'; temp1b->currentT oken = 'b';temp1c->expressionNum = 1; temp1c->currentState = 'E'; temp1c->currentT oken = 'c';temp2->expressionNum = 1; temp2->currentState = 'E'; temp2->currentToken = '(';temp3->expressionNum = 2; temp3->currentState = 'L'; temp3->currentToken = '+';temp4->expressionNum = 3; temp4->currentState = 'L'; temp4->currentToken = '-';temp5->expressionNum = 4; temp5->currentState = 'L'; temp5->currentToken = ')';temp6->expressionNum = 4; temp6->currentState = 'L'; temp6->currentToken = '#';temp7a->expressionNum = 5;temp7a->currentT oken = 'a';temp7b->expressionNum = 5; temp7b->currentState = 'T'; temp7b->currentT oken = 'b';temp7c->expressionNum = 5; temp7c->currentState = 'T'; temp7c->currentT oken = 'c';temp8->expressionNum = 5; temp8->currentState = 'T'; temp8->currentToken = '(';temp9->expressionNum = 8; temp9->currentState = 'M'; temp9->currentToken = '+';temp10->expressionNum = 8; temp10->currentState = 'M'; temp10->currentT oken = '-';temp11->expressionNum = 6; temp11->currentState = 'M'; temp11->currentT oken = '*';temp12->expressionNum = 7;temp12->currentT oken = '/';temp13->expressionNum = 8;temp13->currentState = 'M';temp13->currentT oken = ')';temp14->expressionNum = 8;temp14->currentState = 'M';temp14->currentT oken = '#';temp15a->expressionNum = 9;temp15a->currentState = 'F';temp15a->currentToken = 'a';temp15b->expressionNum = 9;temp15b->currentState = 'F';temp15b->currentToken = 'b';temp15c->expressionNum = 9;temp15c->currentState = 'F';temp15c->currentToken = 'c';temp16->expressionNum = 10;temp16->currentState = 'F';temp16->currentT oken = '(';analysisTableBuffer.push_back(*temp1a); analysisTableBuffer.push_back(*temp1b); analysisTableBuffer.push_back(*temp1c);analysisTableBuffer.push_back(*temp2);analysisTableBuffer.push_back(*temp3);analysisTableBuffer.push_back(*temp4);analysisTableBuffer.push_back(*temp5);analysisTableBuffer.push_back(*temp6);analysisTableBuffer.push_back(*temp7a);analysisTableBuffer.push_back(*temp7b);analysisTableBuffer.push_back(*temp7c);analysisTableBuffer.push_back(*temp8);analysisTableBuffer.push_back(*temp9);analysisTableBuffer.push_back(*temp10);analysisTableBuffer.push_back(*temp11);analysisTableBuffer.push_back(*temp12);analysisTableBuffer.push_back(*temp13);analysisTableBuffer.push_back(*temp14);analysisTableBuffer.push_back(*temp15a);analysisTableBuffer.push_back(*temp15b);analysisTableBuffer.push_back(*temp15c);analysisTableBuffer.push_back(*temp16);}//由于本次实验主要是考察语法分析和语义分析,所以为了节省时间不采用查表的方式获取token,而是直接初始化token的值。
编译原理课程设计-翻译成四元式
编译原理课程设计一、课程设计题目:第(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.。
词法分析程序+语法语义分析四元式生成+实验报告
《编译原理》实验报告本文档集合了编译原理大作业的实验报告加代码实验主要内容为用C++实现了词法分析程序;语法语义以及四元式生成程序代码见附录,复制进VS后程序绝对可编译执行。
文档代码为原创,谨慎使用(姚砺的大作业)实验设计一[一、实验名称]词法分析程序[二、实验目的](1)设计一个词法分析程序,每调用一次就从源程序文件中顺序识别出一个单词符号,并返回该单词符号的内部编码、单词符号自身、行列位置信息。
(2)要能处理单行注释。
[三、实验内容及要求]单词种类与识别规则(1)标识符:首字符为字母或下划线,其后由字母、数字或下划线组成、长度不超过255个字符;(2)整数:由1到8个数字组成。
(3)小数:数字串1 .数字串2,其中:数字串1由1-8个数字符组成;数字串2由0-8个数字符组成,即:数字串2可以为空。
(4)字符串:由一对“”括起来的符号串,长度不超过255个字符;(5)保留字:if、else、while、do、integer、float、string、input、output、and、or、function、end、def、as、begin(6)数学运算符:+、-、*、/、=(7)比较运算符:<、<=、>、>=、<>、==(8)逻辑运算符: and、or(9)分隔符:{、}、(、)、;、,[四、实验环境]操作系统:Win7/其他编译工具:VC++6.0 / CFree / VS2012[五、设计 ]1设计大体思路将读取的文件采用一遍扫描的方法,即从左到右只扫描一次源程序,将读取的数据存放在一个二维数组里。
然后通过扫描函数scan,再从数组中一行一行的读取数据,每调用其依次返回一个单词的类型,同时单词本身以及行列号存放在全局变量中。
而说词法分析作为语法分析的一个子程序,故在编写词法分析程序时,将会反复调用scan函数来获取一个个单词信息。
3设计流程图4函数设计/*词法分析函数*/int scan( string s ,int line ) 框架:{初始化工作是空格直接跳过,知直到读取到一个字符if( 是字母 ){查表判断是否为关键字判断是否为逻辑运算符and或orElse则为标识符}else if( 是否为数字 ){判断是整数Else是小数}Else{其余情况判断是否为运算符,字符串等}else if( getchar==’/’ ){if( content[line][i+1]=='/') //向前看一个,确定是否为行注释;如果是,则游标指向行末,跳过行注释if( content[line][i+1]=='/*')如果向前看一个发现时块注释则一直向前扫描直到出现“*/”停止,略过块注释如果都不是则Else判断为除号,返回运算符类型}}2 对其中部分实现的说明(1) 数字识别while( content[line][i]>='0' && content[line][i]<='9' ) //判断是否为数字{text += content[line][i];i++;flag=1;}if( flag==1 ){if( content[line][i]=='.' ){text += content[line][i];i++;while( content[line][i]>='0' && content[line][i]<='9' ) //判断是否为数字{text += content[line][i];i++;}return 2; //整数}return 3; //小数}每读入一个字符,判断是否数字,然后找小数点,找到即为小数(2)标识符处理while( (content[line][i]>=65 && content[line][i]<=90) || (content[line][i]>=91 && content[line][i]<=122) || content[line][i]>='0' && content[line][i]<='9' ) //判断是否为数字或者字母或者下划线{text += content[line][i];i++;}for( j=0; j<=13 ; j++ )if( text==key[j] ) //查表判断是否为保留字return 5;检查到读取的字符为字母时,进行查表判断,找到即说明为关键字(3)空格,注释,行号的处理if( mode==0 ){if( i<content[k].length() ) i++;} //如果为行注释直接跳到下一行elseif( mode==-1 ) //如果为块注释找回行号k=templine;[六、程序源代码]见源代码文件。
目标代码中间代码生成-四元式设计文档
工程第一神刀公子编译原理实验实验名称:中间代码生成程序设计指导老师:轻语专业:计算机科学与技术班级:LOL学号:0000001姓名:神刀公子2008.6.22实验任务:在实验4的基础上,完成以下描述赋值语句和算数表达式文法G[A]的语法制导生成中间代码四元式的过程。
A-->V:=E V--><标识符> E→E+T|E-T|T T→T*F|T/F|F F→(E)|<标识符>说明:标识符的定义参见实验一程序的功能描述从文件中读入表达式,输出其四元式的结果序列本程序只能生成赋值语句及算数表达式中间代码的四元式不能生成逻辑表达式及其他复杂语句中间代码的四元式,其功能还需要进一步完善。
程序测试方案测试用例一:d=a+b*(3*n)/(b-a)测试用例二:x=x*(x+y-(x-y)/(z+x)-y)实验总结此程序基本达到了实验要求,能够生成简单的赋值及算数表达式中间代码的四元式,但其功能实在是过于简单。
第一次调试通过后程序还存在以下不足:(1)此程序只能从文件中读入一个表达式,读入多个则会出错;(2)所读入的表达式中若含有多于一个括号,程序会出错;(3)括号内若多于一个表达式则会出错;(4)在测试用例二中的分析过程明显是错误的,这足以看出程序的漏洞很多但经过进一步优化算法,以上问题基本解决,但程序中仍然存在很多不足,例如时间效率和空间效率方面做的还不够好,要改善这些不足还需要进一步完善程序,在以后的学习生活中我会根据所学知识的不断深入而不断完善此程序,争取使其功能更加强大。
经过这次实验我更加深刻的理解了生成中间代码的算法思想,及时的将所学知识用于实践,更加深刻的掌握了所学知识。
附录#include<stdlib.h>#include<fstream>#include<iostream>using namespace std;#define MAX 100int m=0,sum=0;//sum用于计算运算符的个数//m用于标记输入表达式中字符的个数char JG='A';char str[MAX];//用于存输入表达式int token=0;//左括号的标志/***********用于更改计算后数组中的值**************/void change(int e){int f=e+2;char ch=str[f];if(ch>='A'&&ch<='Z'){for(int l=0;l<m+10;l++) {if(str[l]==ch)str[l]=JG;}}if(str[e]>='A'&&str[e]<='Z') {for(int i=0;i<m;i++){if(str[i]==str[e])str[i]=JG;}}}void chengchuchuli(int i,int m){i++;for( ;i<=m-1;i++)//处理乘除运算{if(str[i]=='*'||str[i]=='/'){cout<<"("<<str[i]<<" "<<str[i-1]<<" "<<str[i+1]<<" "<<JG<<")"<<endl;change(i-1);str[i-1]=str[i]=str[i+1]=JG;sum--;JG=(char)(int)JG++;}}void jiajianchuli(int j,int m){j++;for( ;j<=m-1;j++)//处理加减运算{if(str[j]=='+'||str[j]=='-'){cout<<"("<<str[j]<<" "<<str[j-1]<<" "<<str[j+1]<<" "<<JG<<")"<<endl;change(j-1);str[j-1]=str[j]=str[j+1]=JG;sum--;JG=(char)(int)JG++;}}}/*扫描一遍从文件中读入表达式*/void scan(FILE *fin)_ {int p[MAX];char ch='a';int c=-1,q=0;while(ch!=EOF){ch=getc(fin);while(ch==' '||ch=='\n'||ch=='\t') ch=getc(fin);//消除空格和换行符str[m++]=ch;if(ch=='='||ch=='+'||ch=='-'||ch=='*'||ch=='/') sum++;else if(ch=='('){p[++c]=m-1;}else if(ch==')'){_ q=m-1;chengchuchuli(p[c],q);//从左括号处理到又括号jiajianchuli(p[c],q);JG=(char)(int)JG--;str[p[c]]=str[m-1]=JG;c--;JG=(char)(int)JG++;}}}/*对表达是进行处理并输出部分四元式*/void siyuanshi(){for(int i=0;i<=m-1;i++)//处理乘除运算{if(str[i]=='*'||str[i]=='/'){cout<<"("<<str[i]<<" "<<str[i-1]<<" "<<str[i+1]<<"_ "<<JG<<")"<<endl;change(i-1);str[i-1]=str[i]=str[i+1]=JG;sum--;JG=(char)(int)JG++;}}for(int j=0;j<=m-1;j++)//处理加减运算{if(str[j]=='+'||str[j]=='-'){cout<<"("<<str[j]<<" "<<str[j-1]<<" "<<str[j+1]<<" "<<JG<<")"<<endl;change(j-1);str[j-1]=str[j]=str[j+1]=JG;sum--;JG=(char)(int)JG++;}}for(int k=0;k<=m-1;k++)//处理赋值运算{if(str[k]=='='){JG=(char)(int)--JG;cout<<"("<<str[k]<<" "<<str[k+1]<<" "<<" "<<" "<<str[k-1]<<")"<<endl;sum--;change(k+1);str[k-1]=JG;}}}/***************主函数*******************/void main(){char in[MAX]; //用于接收输入输出文件名FILE *fin; //用于指向输入输出文件的指针cout<<"请输入源程序文件名(例如ceshi.txt):";cin>>in;cout<<endl;if ((fin=fopen(in,"r"))==NULL) //判断输入文件名是否正确{cout<<endl<<"打开词法分析输入文件出错!"<<endl;}cout<<"四元式如下:"<<endl;scan(fin);//调用函数从文件中读入表达式/********调用生成四元式的函数********/siyuanshi();/*********判断是否成功**********/if(sum==0) cout<<"成功!"<<endl;else cout<<"有错误!"<<endl;//关闭文件fclose(fin);}。
编译原理报告三四元式参考模板
四元式生成一、目的和要求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 (除自身外)的任意属性。
(完整)编译原理实验报告(词法分析器 语法分析器)
编译原理实验报告实验一一、实验名称:词法分析器的设计二、实验目的: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)。
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)文法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
temp=(i nt)tempva叶1;
tempvar=(char)temp;
调用生成四元式的函数********/
Prin t();
判断是否成功**********/
if(co Un t==0)
Printf("Successful!∖n"); else
Printf("Wrong!");
Prin tf("∖n");
SyStem("pause");
}
void SET_Mul_Div(int i,int m) //处理乘除运算
{
for(i++;i<=m='*'∣∣stri ng[i]==7')
{
Prin tf("(%c %c %c%c)∖n",stri ng[i],stri ng[i-1],stri ng[i+1],
{
Prin tf("(%c%c %c %c)∖n",stri ng[j],stri ng[j-1],stri ng[j+1],tempvar);
Stri ng[j-1]=stri ng[j]=stri ng[j+1]=tempvar;
COun t--;
temp=(i nt)tempva叶1;
tempvar=(char)temp;
tempvar);
Stri ng[i-1]=stri ng[i]=stri ng[i+1]=tempvar;
COun t--;
temp=(i nt)tempva叶1;
tempvar=(char)temp;
}
}
}
void SET Add Sub(i nt j,i nt m) //处理加减运算
{
j++;
COun t--;
temp=(i nt)tempva叶1;
tempvar=(char)temp;
}
}
}
∕*打印*/
void Prin t()
{
int i;
for(i=0;i<=m-1;i++)〃处理乘除运算
{
if(stri ng[i]=='*'∣∣stri ng[i]==7')
{
Prin tf("(%c %c %c %c)∖n",stri ng[i],stri ng[i-1],stri ng[i+1],tempvar);
void SET_Add_Sub( int j,i nt m);
void Prin t();
int m=0;
int coun t=0;
Char tempvar='A';
int temp;
Char Stri ng[MAX];〃用于存放表达式
int main()
{
in t p[MAX];
Char ch;
{
P[++c]=m-1;
}
else if(ch==')')
{
q=m-1;
SET_MULDiV(P[c],q);//从左括号处理到又括号
SET_Add_Sub(p[c],q);
temp=(i nt)tempvar-1;
tempvar=(char)temp;
Stri ng[p[c]]=stri ng[m-1]=tempvar;
for(;jv=m-1;j++)
{
if(stri ng[j]=='+'∣∣stri ng[j]=='-')
{
Prin tf("(%c %c %c %c)∖n",stri ng[j],stri ng[j-1],stri ng[j+1],tempvar);
Stri ng[j-1]=stri ng[j]=stri ng[j+1]=tempvar;
int c=-1,q=0;
Printf("请输入赋值语句:∖n");
WhiIe((Ch = getchar())!='∖n')
{
Stri ng[m++]=ch; if(ch=='='∣∣ch=='+'∣∣ch=='-'∣∣ch=='*'∣∣ch==7')
COun t++;
else if(ch=='(')
西北师范大学计算机科学与工程学院学生实验报告
学号
专业
计算机科学与技术
姓名
课程名称
计算机编译原理
班级
实验名称生成四元式序列课程类型专业课
实验目的:
编程实现生成四元式的语法分析程序,掌握的结合语法分析实现翻译方案的思路和
方法。
实验内容:
实验输入:输入任意的赋值语句表达式;
实验输出:相应的四元式序列。
测试实例:
}
}
int k;
for(k=0;k<=m-1;k++)//处理赋值运算
{
if(stri ng[k]=='=')
{
temp=(i nt)tempvar--;
tempvar=(char)temp;
Prin tf("(%c%c %c)∖n",stri ng[k],stri ng[k+1],
Stri ng[k-1],tempvar);
Stri ng[i-1]=stri ng[i]=stri ng[i+1]=tempvar;
COUn t--;
temp=(i nt)tempva叶1;
tempvar=(char)temp;
}
}
int j;
for(j=0;jv=m-1;j++)〃处理加减运算
{
if(stri ng[j]=='+'∣∣stri ng[j]=='-')
输入表达式
1.a = ( ( b+C) * d -e/f)* 2
2.q =( ( X * X+W) -(y/y-e) )* r
实验代码:
#in CIudeVStdio.h>
#i nclude<stdlib.h>
#define MAX 100
void SET_Mul_Div(i nt i,i nt m);
实验评语:
该学生在本次试验中完成生成四元式的语法分析程序,基本掌握的结合语法分析实现 翻译方案的思路和方法,但是程序在一些细节及特殊文法的处理上还需要进一步完善, 如编程时注意编程风格:空行的使用、注释的使用、缩进的使用,如果遇到错误的表达 式,应输出错误提示信息等。
实验成绩
教师签字
COUn t--;
Stri ng[k-1]=tempvar;
}
}
}
实验结果:
实验总结:
通过本次实验我完成生成四元式的语法分析程序,掌握的结合语法分析实现翻译方
案的思路和方法。本次实验还是遇到许多困难,通过上网查看以及查看许多书籍,最终 还是完成了本次试验,还是收获挺大的。但是实验中还存在着许多不足,如规则的顺序,first集合的求解等,还需不断完善。