实验三语义分析 编译原理
编译原理实验报告

编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。
二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。
三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。
在本次实验中,我们使用有限自动机的理论来设计词法分析器。
首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。
然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。
在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。
(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。
在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。
首先,我们根据给定的语法规则,编写了相应的递归函数。
每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。
在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。
(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。
在本次实验中,我们使用了四元式作为中间代码的表示形式。
在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。
同时,根据语法树的结构,生成相应的四元式中间代码。
(四)代码优化代码优化的目的是提高生成代码的质量和效率。
在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。
通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。
编译原理实验

编译原理实验编译原理是计算机科学中的一门重要课程,它研究的是将高级语言程序转化为机器语言的过程。
在编译原理实验中,我们可以通过实际操作来深入理解编译原理的各个概念和原理,进而提高自己的编程能力。
在编译原理实验中,我们通常会接触到以下几个重要的内容:1. 词法分析:词法分析是编译过程中的第一步,它将源代码分解为一个个的词法单元。
在实验中,我们可以编写词法分析器,通过正则表达式匹配来识别不同的词法单元,如标识符、关键字、常量等。
2. 语法分析:语法分析是编译过程中的第二步,它将词法单元组织成一个语法树。
在实验中,我们可以编写语法分析器,通过上下文无关文法和语法规则来构建语法树,并检查语法的正确性。
3. 语义分析:语义分析是编译过程中的第三步,它对语法树进行语义检查,并生成中间代码。
在实验中,我们可以编写语义分析器,通过符号表和类型检查来进行语义分析,并生成对应的中间代码。
4. 中间代码生成:中间代码是一种介于源代码和目标代码之间的代码表示形式。
在实验中,我们可以编写中间代码生成器,将语法树转化为中间代码,如三地址码、四元式等。
5. 代码优化:代码优化是为了提高目标代码的质量和性能,减少程序的执行时间和空间占用。
在实验中,我们可以编写代码优化器,通过对中间代码的分析和变换来优化程序。
6. 目标代码生成:目标代码是机器语言的表示形式,它可以直接在计算机上执行。
在实验中,我们可以编写目标代码生成器,将中间代码转化为目标代码,如汇编语言或机器语言。
在编译原理实验中,我们可以通过编写相应的程序来模拟编译过程的各个阶段。
通过实验,我们可以更加深入地理解编译原理的各个概念和原理,加深对编译过程的认识,并提高自己的编程能力。
编译原理实验是一门非常重要的课程,通过实践操作可以更好地理解和应用编译原理的知识。
通过编写词法分析器、语法分析器、语义分析器、中间代码生成器、代码优化器和目标代码生成器等程序,我们可以加深对编译过程的理解,提高自己的编程能力。
编译原理课程设计-语义分析程序的设计与实现

}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"};
p--;
}
break;
case'>':m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=24;
token[m++]=ch;
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;
while(syn==26)
{
scaner();
schain=statement();
}
}
else
{cout<<"缺begin!"<<endl;kk=1;}
return(schain);
}
编译原理实验报告实验三语法分析(LR分析程序)

编译原理实验报告实验三语法分析(LR分析程序)华北⽔利⽔电学院编译原理实验报告2012~2013学年第⼀学期2011 级计算机科学与技术专业班级:2011179 学号:2011179 姓名:⼀、实验题⽬:语法分析(LR分析程序)(1)选择最有代表性的语法分析⽅法LR分析法;(2)选择对各种常见程序语⾔都⽤的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析⽅法要⽐较贴切。
⼆、实验内容(1)根据给定⽂法,先求出FirstVt和LastVt集合,构造算符优先关系表(要求算符优先关系表输出到屏幕或者输出到⽂件);(2)根据算法和优先关系表分析给定表达式是否是该⽂法识别的正确的算术表达式(要求输出归约过程)(3)给定表达式⽂法为:G(E’): E’→#E#E→E+T | TT→T*F |FF→(E)|i(4) 分析的句⼦为:(i+i)*i和i+i)*i三、根据以上⽂法构造出的LR(1)分析表为:四、程序源代using System;using System.Text;using System.IO;namespace Syntax_Analyzer{class Syntax{StreamReader myStreamReader;int t;int[] lengh;int l =0;string[] grammar;int s=0;string[] Word;int w=0;int[] wordNum ;int n =0;int[,] LR;public Syntax(){lengh = new int[7];grammar=new string[7];Word=new string[100];wordNum = new int[100];LR=new int[30,30];}public void analyzer(){//读⼊grammarSyntax myTextRead=new Syntax();Console.WriteLine("-----------------------------语法分析开始---------------------------------\n"); //***************************//循环读取⽂法//***************************string strStart;strStart="grammar.txt";myTextRead.myStreamReader=new StreamReader(strStart);string strBufferStart;int uu=0;do{strBufferStart =myTextRead.myStreamReader.ReadLine();if(strBufferStart==null)break;foreach (String subString in strBufferStart.Split()){grammar[uu]=subString; //每⾏⽂法存⼊grammar[]uu++;}}while (strBufferStart!=null);myTextRead.myStreamReader.Close();//***************************//循环读取lengh//***************************strStart="lengh.txt";myTextRead.myStreamReader=new StreamReader(strStart);uu=0;do{strBufferStart =myTextRead.myStreamReader.ReadLine();if(strBufferStart==null)break;foreach (String subString in strBufferStart.Split()){lengh[uu]=Convert.ToInt32(subString); //每⾏⽂法存⼊grammar[] uu++;}}while (strBufferStart!=null);myTextRead.myStreamReader.Close();//****************************// 读⼊⽂件,进⾏语法分析////****************************string strReadFile;strReadFile="input.txt";myTextRead.myStreamReader=new StreamReader(strReadFile); string strBufferText;int wid =0;Console.WriteLine("分析读⼊程序(记号ID):\n");do{strBufferText =myTextRead.myStreamReader.ReadLine();if(strBufferText==null)break;foreach (String subString in strBufferText.Split()){if(subString!=""){int ll;if(subString!=null){ll= subString.Length; //每⼀个长度}else{break;}int a=ll+1;char[] b = new char[a];StringReader sr = new StringReader(subString); sr.Read(b, 0, ll); //把substring 读到char[]数组⾥int sort=(int)b[0];// word[i] 和wordNum[i]对应//先识别出⼀整个串,再根据开头识别是数字还是字母Word[wid]=subString;if(subString.Equals("+")){wordNum[wid]=0;}else{if(subString.Equals("*")){wordNum[wid]=1;}else{if(subString.Equals("(")){wordNum[wid]=2;}else{if(subString.Equals(")")){wordNum[wid]=3;}else{if(subString.Equals("i")){wordNum[wid]=4;}}}}}Console.Write(subString+"("+wordNum[wid]+")"+" ");wid++;}}Console.WriteLine("\n");}while (strBufferText!=null);wordNum[wid]=5;myTextRead.myStreamReader.Close();//*********************************//读⼊LR分析表////***********************************string strLR;strLR="LR-table.txt";myTextRead.myStreamReader=new StreamReader(strLR); string strBufferLR;int pp=0;do{strBufferLR =myTextRead.myStreamReader.ReadLine(); if(strBufferLR==null)break;else{int j=0;foreach (String subString in strBufferLR.Split())if(subString!=null){int lllr=Convert.ToInt16(subString);LR[pp,j]=lllr; //把⾏与列读⼊数组j++;}}}pp++;}while (strBufferLR!=null);myTextRead.myStreamReader.Close();int[] state = new int[100];string[] symbol =new string[100];state[0]=0;symbol[0]="#";int p1=0;int p2=0;Console.WriteLine("\n按⽂法规则归约顺序如下:\n"); //***************//归约算法//***************while(true){int j,k;j=state[p2];k=wordNum[p1];t=LR[j,k]; //当出现t为的时候if(t==0){//错误类型string error = "" ;if (k == 0)error = "+";if (k == 1)error = "*";elseif (k == 2)error = "(";elseif (k == 3)error = ")";elseif (k == 4)error = "i";elseerror = " 其它错误!";Console.WriteLine("\n检测结果:");Console.WriteLine("代码中存在语法错误");Console.WriteLine("错误状况:错误状态编号为"+j+" 读头下符号为"+error); break;}else{if(t==-100) //-100为达到接受状态{Console.WriteLine("\n");Console.WriteLine("\n检测结果:");Console.WriteLine("代码通过语法检测");break;}if(t<0&&t!=-100) //归约{string m=grammar[-t];Console.Write(m+" "); //输出开始符int length=lengh[-t];p2=p2-(length-1);Search mySearch=new Search();int right=mySearch.search(m);if(right==0){Console.WriteLine("\n");Console.WriteLine("代码中有语法错误");break;}int a=state[p2-1];int LRresult= LR[a,right];state[p2]=LRresult;symbol[p2]=m;}if(t>0){p2=p2+1;state[p2]=t;symbol[p2]=Convert.ToString(wordNum[p1]);p1=p1+1;}}}myTextRead.myStreamReader.Close();Console.WriteLine("-----------------------------语法分析结束---------------------------------\n"); Console.Read();}}class Search{public int search(string x){string[] mysymbol=new string[3];mysymbol[0]="E";mysymbol[1]="T";mysymbol[2]="F";int r = 0;for(int s=0;s<=2;s++){if(mysymbol[s].Equals(x))r=s+6 ;}return r;}}}五、测试结果输⼊”( i + i ) * i”字符串,分析如下图所⽰输⼊”i + i ”字符串,分析如下图所⽰六、⼩结(包括收获、⼼得体会、存在的问题及解决问题的⽅法、建议等)本次实验是LR分析法,LR分析法是⼀种有效的⾃上⽽下分析技术,在⾃左向右扫描输⼊串时就能发现其中的任何错误。
编译原理实验报告

编译原理实验报告一、实验目的编译原理是计算机科学中的重要学科,它涉及到将高级编程语言转换为计算机能够理解和执行的机器语言。
本次实验的目的是通过实际操作和编程实践,深入理解编译原理中的词法分析、语法分析、语义分析以及中间代码生成等关键环节,提高我们对编译过程的认识和编程能力。
二、实验环境本次实验使用的编程语言为C++,开发环境为Visual Studio 2019。
此外,还使用了一些相关的编译工具和调试工具,如 GDB 等。
三、实验内容(一)词法分析器的实现词法分析是编译过程的第一步,其任务是将输入的源程序分解为一个个单词符号。
在本次实验中,我们使用有限自动机的理论来设计和实现词法分析器。
首先,定义了各种单词符号的类别,如标识符、关键字、常量、运算符等。
然后,根据这些类别设计了相应的状态转换图,并将其转换为代码实现。
在实现过程中,使用了正则表达式来匹配输入字符串中的单词符号。
对于标识符和常量等需要进一步处理的单词符号,使用了相应的规则进行解析和转换。
(二)语法分析器的实现语法分析是编译过程的核心环节之一,其任务是根据给定的语法规则,分析输入的单词符号序列是否符合语法结构。
在本次实验中,我们使用了递归下降的语法分析方法。
首先,根据实验要求定义了语法规则,并将其转换为相应的递归函数。
在递归函数中,通过对输入单词符号的判断和处理,逐步分析语法结构。
为了处理语法错误,在分析过程中添加了错误检测和处理机制。
当遇到不符合语法规则的输入时,能够输出相应的错误信息,并尝试进行恢复。
(三)语义分析及中间代码生成语义分析的目的是对语法分析得到的语法树进行语义检查和语义处理,生成中间代码。
在本次实验中,我们使用了三地址码作为中间代码的表示形式。
在语义分析过程中,对变量的定义和使用、表达式的计算、控制流语句等进行了语义检查和处理。
对于符合语义规则的语法结构,生成相应的三地址码指令。
四、实验步骤(一)词法分析器的实现步骤1、定义单词符号的类别和对应的正则表达式。
编译原理语义分析实验报告

实验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#输出结果八、收获(体会)与建议通过此次实验, 让我了解到如何设计、编制并调试语义分析程序, 加深了对语法制导翻译原理的理解, 掌握了将语法分析所识别的语法成分变换为中间代码的语义翻译方法。
实验三编译原理综合实验报告——(LR(0)语法分析的实现)

m_pTree->SetControlInfo(IDC_TREE1, RESIZE_BOTH);
m_pTree->SetControlInfo(IDOK, ANCHORE_BOTTOM | ANCHORE_RIGHT);
void CAnalyzeDlg::OnOK()
{
// TODO: Add extra validation here
//CDialog::OnOK();
}
void CAnalyzeDlg::OnCancel()
{
// TODO: Add extra cleanup here
六、实验原理、数据(程序)记录
(一)实验原理:
利用LR(k)类分析算法的四个步骤,分别实现"移进"、"归约"、"成功"、"报错"的分析能力。同时采用相应的数据结构实现分析表的描述。
(二)程序框架:
#include "stdafx.h"
#include "GoData.h"
GoData::GoData()
assert(j != -1);
out.WriteString(GetStepInfo(iStep, Status, Symbol, m_input.Right(m_input.GetLength() - iPos), ToDo, j));
for(i = 0; i < m_g.GetPrecept(ToDo.two).GetRight().length(); i++)
编译原理_ 语义分析_实验报告

编译原理实验三语义分析实验报告◆学院:数学与计算机科学技术学院◆专业:计算机科学与技术◆班级:级计算机班◆小组组员:姓名:学号:姓名:学号:姓名:学号:姓名:学号:实验题目一、实验目的要求学生用与实验2相同的语言,编制语义分析程序。
二、实验准备微机CPU主频1.3G以上,128M内存,安装好C语言,PASCAL语言,或C++。
三、实验时间13学时四、实验内容要求学生用与实验2相同的语言,编制语义分析程序。
定义该语言的语义成分,将语义分析程序编制成子程序,在实验2分析出各语法单位后,分析其含义,并将可执行语句或表达式翻译为四元式输出,并将错误信息输出。
实验报告必须包括设计的思路,以及测试报告(输入测试例子,输出结果)。
五、上交文档1.实验报告(书面);2.程序文件(通过网络提交)。
<program> ::= <block> .<block> ::= <const-decl> <var-decl> <proc-decl> <statement><const-decl> ::= const <const-assignment-list> ; | ε<const-assignment-list> ::= <ident> = <number>| <const-assignment-list> , <ident> = <number><var-decl> ::= var <ident-list> ; |ε<ident-list> ::= <ident> | <ident-list> , <ident><proc-decl> ::= <proc-decl> procedure <ident> ; <block> ; |ε<statement> ::= <ident> := <expression>| call <ident>| begin <statement-list> end| if <condition> then <statement>| while <condition> do <statement>|ε<statement-list> ::= <statement> | <statement-list> ; <statement><condition> ::= odd <expression> | <expression> <relation> <expression><relation> ::= = | <> | < | > | <= | >=<expression> ::= <term> | <adding-operator> <term>| <expression> <adding-operator> <term><adding-operator> ::= + | -<term> ::= <factor> | <term> <multiplying-operator> <factor><multiplying-operator> ::= * | /<factor> ::= <ident> | <number> | ( <expression> )注意:(1) "ε" 表示空串。
编译原理实验报告语义分析

编译原理实验报告语义分析实验名称:语义分析实验目的:1.掌握词法分析器生成的词法单元序列的构造;2.学会设计语法分析器,实现对程序的基本语法结构检查,并生成抽象语法树;3.学习语义规约的实现,实现对程序的语义分析和错误检查;4.熟悉语义分析向语法分析的接口。
实验原理:语义分析是编译过程的一个重要环节,它的主要任务是对生成的抽象语法树进行遍历,并验证程序的类型一致性、语义规则的正确性、错误的检查和恢复等。
语义分析的输入是由语法分析生成的抽象语法树,输出是继续优化的抽象语法树或中间代码,以供后续的中间代码生成等工作使用。
实验步骤:1.设计语法分析器,包括语法规则、优先级关系等;2.生成词法单元序列;3.构建语法分析器,进行语法分析,并生成抽象语法树;4.针对不同的语义规约,设计语义动作,实现对程序的语义分析和错误检查;5.完成语义分析器的构建和测试。
实验设备:1.计算机;2. 编程语言:C++/Java/Python等;3. 开发环境:Visual Studio/ Eclipse/PyCharm等。
实验结果:通过对语法分析生成的抽象语法树进行遍历,实现了对程序的语义分析和错误检查。
具体实现包括:1.类型检查:根据语义规约,对程序中的类型进行检查,包括变量的声明及使用、函数的调用、赋值语句的一致性等;2.作用域检查:检查变量的作用域和可见性等;3.错误检查:检测语义错误,如变量未声明、函数重复定义等;4.错误恢复:当检测到错误时,采取适当的错误恢复措施,如跳过错误的部分继续分析、提示错误信息等。
实验心得:本次实验主要学习了语义分析的原理和实现方法,深入了解了编译过程中各个环节的作用和关系。
通过实践操作,加深了对语法分析和语义分析的理解,提高了编程能力和解决问题的能力。
同时,实验过程中也遇到了一些挑战和困难,例如语义规约的设计和实现、错误检查和恢复等,但通过查阅资料和与同学讨论,最终解决了这些问题。
通过本次实验,我对编译原理和语义分析有了更深入的了解,并且对以后的学习和工作有了更好的准备。
编译原理实验报告-语义分析

编译原理课程实验报告实验3:语义分析图2-1本程序根据之前两个实验的结果进一步进行语义分析,主要是通过在第二个实验句法分析过程中添加语义分析功能完成的。
在代码编写之前,我将程序的功能模块分为界面及主控程序,实体类和工具类三大部分。
MyCompiler是整个程序运行的入口,是主控程序;ComplierFrame完成程序的界面,以及界面里事件的响应;Token是词法分析中词法单元的实体类;ErrorToken是错误的词法单元实体类;Symbol是句法分析中符号的实体类;Production是产生式的实体类;ErrorProduction是句法分析中产生错误的时候使用的产生式实体类;Id是标示符实体类,保存了语义分析后的标识符表;Node是语法分析树的节点类,帮助完成语法分析树的构造;LL类使用LL(1)分析法完成句法分析,同时完成语义分析;MyScanner完成了词法分析。
图2-2三、详细设计及实现得分要求:对如下工作进行展开描述(1)核心数据结构的设计本程序使用了两个新的实体类,分别是Id和Node。
Id是标识符,里面也包含了该标识符在本程序中存储的地址和长度等信息。
Id的属性如下:private String name; //名private String type;//基本类型private int offset;//起始地址private int length;//长度开始输入词法分析读入Token尝试匹配是否错误存储错误记录,处理栈顶与Token 序列是否为语义符号存储产生式,处理栈顶与Token 序列判断动作符号执行语义动作是否读到Token末尾打印结果结束分析结果以及错误报告:图4-1 标识符表:图4-2。
哈工大威海编译原理实验三语义分析与中间代码生成(DOC X页)

哈工大威海编译原理实验三语义分析与中间代码生成(DOCX页)哈尔滨工业大学(威海)计算机学院编译原理实验报告姓名院系计算机学院学号 090410任课教师指导教师实验地点宋健二楼机房实验时间实验三语义分析及中间代码生成实验名称同组人无预习报告(对实验主要内容的认识) 得分(1) 通过本次试验,我应该加深对于编译原理制导方案的理解,并且加深对于语法变换的所起到的作用;(2) 对于试验中要用到得中间代码的格式规范,也应该进一步的分析和掌握(3) 能够很好的使用到前面开发出来的词法分析器和语法分析器,将它们与语义分析器结合起来,跟好的更系统的掌握编译原理这门专业技能 (4) 关于符号表以及token串表的维护,现在终于使其有所作用实验内容(问题,思路,程序,结果) 得分(1)开发环境:vs2010(2)输入:在运行打开的软件下(win32格式),输入相应的代码(即要进行词法分析的字符串)(比如:int a;)(3)输出:在输入字符串后,按回车键后,既可以得到相应的词法分析的结果(比如:int a 的输入对应的输出如下:int a;首先对于词法分析打印出:Int --- key //关键字A ---str //字符串; ---bor //边界符号对于语法分析:Accept //编译语句分析成功对于输入字符串的语义分析和中间代码的生成如下中间代码:)(4)在相应的运行程序的文件夹中生成一个txt文件,用来存储生成的Token 链表(5)系统功能:(2) 开发平台(操作系统、设计语言):1、操作系统:windows 72、设计语言:c++3、编译器:vs2010(3) 设计方案;1) 主数据流图开始词法分析Token表的生成及修改语法分析修改token表语义分析语句是否为变量声明对语句按照文法的action表进行归约加一个四元式结点向下进行语义分析生成中间代码结束2) 主要数据结构:符号表、TOKEN串表等。
编译原理实验三-自下而上语法分析报告及语义分析报告.docx

上海电力学院编译原理课程实验报告实验名称:实验三自下而上语法分析及语义分析院系:计算机科学与技术学院专业年级:学生姓名:学号:指导老师:实验日期:实验三自上而下的语法分析一、实验目的:通过本实验掌握LR分析器的构造过程,并根据语法制导翻译,掌握属性文法的自下而上计算的过程。
二、实验学时:4学时。
三、实验内容根据给出的简单表达式的语法构成规则(见五),编制LR分析程序,要求能对用给定的语法规则书写的源程序进行语法分析和语义分析。
对于正确的表达式,给出表达式的值。
对于错误的表达式,给出出错位置。
四、实验方法采用LR分析法。
首先给出S-属性文法的定义(为简便起见,每个文法符号只设置一个综合属性,即该文法符号所代表的表达式的值。
属性文法的定义可参照书137页表6.1),并将其改造成用LR分析实现时的语义分析动作(可参照书145页表6.5)。
接下来给出LR分析表。
然后程序的具体实现:●LR分析表可用二维数组(或其他)实现。
●添加一个val栈作为语义分析实现的工具。
●编写总控程序,实现语法分析和语义分析的过程。
注:对于整数的识别可以借助实验1。
五、文法定义简单的表达式文法如下:(1)E->E+T(2)E->E-T(3)E->T(4)T->T*F(5)T->T/F(6)T->F(7)F->(E)(8)F->i五、处理程序例和处理结果例示例1:20133191*(20133191+3191)+ 3191#六、源代码【cifa.h】//cifa.h#include<string> using namespace std;//单词结构定义struct WordType{int code;string pro;};//函数声明WordType get_w();void getch();void getBC();bool isLetter();bool isDigit();void retract();int Reserve(string str); string concat(string str); 【Table.action.h】//table_action.hclass Table_action{int row_num,line_num;int lineName[8];string tableData[16][8]; public:Table_action(){row_num=16;line_num=8;lineName[0]=30;lineName[1]=7;lineName[2]=13;lineName[3]=8;lineName[4]=14;lineName[5]=1;lineName[6]=2;lineName[7]=15;lineName[8]=0;for(int m=0;m<row_num;m++) for(int n=0;n<line_num;n++) tableData[m][n]="";tableData[0][0]="S5";tableData[0][5]="S4";tableData[1][1]="S6";tableData[1][2]="S12";tableData[1][7]="acc";tableData[2][1]="R3";tableData[2][2]="R3";tableData[2][3]="S7";tableData[2][6]="R3"; tableData[2][7]="R3"; tableData[3][1]="R6"; tableData[3][2]="R6"; tableData[3][3]="R6"; tableData[3][4]="R6"; tableData[3][6]="R6"; tableData[3][7]="R6"; tableData[4][0]="S5"; tableData[4][5]="S4"; tableData[5][1]="R8"; tableData[5][2]="R8"; tableData[5][3]="R8"; tableData[5][4]="R8"; tableData[5][6]="R8"; tableData[5][7]="R8"; tableData[6][0]="S5"; tableData[6][5]="S4"; tableData[7][0]="S5"; tableData[7][5]="S4"; tableData[8][1]="S6";tableData[8][6]="S11"; tableData[9][1]="R1"; tableData[9][2]="R1"; tableData[9][3]="S7"; tableData[9][4]="S13"; tableData[9][6]="R1"; tableData[9][7]="R1"; tableData[10][1]="R4"; tableData[10][2]="R4"; tableData[10][3]="R4"; tableData[10][4]="R4"; tableData[10][6]="R4"; tableData[10][7]="R4"; tableData[11][1]="R7"; tableData[11][2]="R7"; tableData[11][3]="R7"; tableData[11][4]="R7"; tableData[11][6]="R7"; tableData[11][7]="R7"; tableData[12][0]="S5"; tableData[12][5]="S4";tableData[13][5]="S4";tableData[14][1]="R2";tableData[14][2]="R2";tableData[14][3]="S7";tableData[14][4]="S13";tableData[14][6]="R2";tableData[14][7]="R2";tableData[15][1]="R5";tableData[15][2]="R5";tableData[15][3]="R5";tableData[15][4]="R5";tableData[15][5]="R5";tableData[15][6]="R5";tableData[15][7]="R5";}string getCell(int rowN,int lineN){int row=rowN;int line=getLineNumber(lineN);if(row>=0&&row<row_num&&line>=0&&line<=line_num) return tableData[row][line];elsereturn"";}int getLineNumber(int lineN){for(int i=0;i<line_num;i++)if(lineName[i]==lineN)return i;return -1;}};【Table_go.h】//table_go.hclass Table_go{int row_num,line_num;//行数、列数string lineName[3];int tableData[16][3];public:Table_go(){row_num=16;line_num=3;lineName[0]="E";lineName[1]="T";lineName[2]="F";for(int m=0;m<row_num;m++) for(int n=0;n<line_num;n++)tableData[m][n]=0;tableData[0][0]=1;tableData[0][1]=2;tableData[0][2]=3;tableData[4][0]=8;tableData[4][1]=2;tableData[4][2]=3;tableData[6][1]=9;tableData[6][2]=3;tableData[7][2]=10;tableData[12][1]=14;tableData[12][2]=3;tableData[13][2]=15;}int getCell(int rowN,string lineNa){int row=rowN;int line=getLineNumber(lineNa);if(row>=0&&row<row_num&&line<=line_num) return tableData[row][line];elsereturn -1;}int getLineNumber(string lineNa){for(int i=0;i<line_num;i++)if(lineName[i]==lineNa)return i;return -1;}};【Stack_num.h】class Stack_num{int i; //栈顶标记int *data; //栈结构public:Stack_num() //构造函数{data=new int[100];i=-1;}int push(int m) //进栈操作{i++;data[i]=m;return i;}int pop() //出栈操作{i--;return data[i+1];}int getTop() //返回栈顶{return data[i];}~Stack_num() //析构函数{delete []data;}int topNumber(){return i;}void outStack(){for(int m=0;m<=i;m++)cout<<data[m];}};【Stack_str.h】class Stack_str{int i; //栈顶标记string *data; //栈结构public:Stack_str() //构造函数{data=new string[50];i=-1;}int push(string m) //进栈操作{i++;data[i]=m;return i;}int pop() //出栈操作{data[i]="";i--;return i;}string getTop() //返回栈顶{return data[i];}~Stack_str() //析构函数{delete []data;int topNumber(){return i;}void outStack(){for(int m=0;m<=i;m++)cout<<data[m];}};【cifa.cpp】//cifa.cpp#include<iostream>#include<string>#include"cifa.h"using namespace std;//关键字表和对应的编码stringcodestring[10]={"main","int","if","then","else","return","void","cout","endlint codebook[10]={26,21,22,23,24,25,27,28,29};//全局变量char ch;int flag=0;/*//主函数int main(){WordType word;cout<<"请输入源程序序列:";word=get_w();while(word.pro!="#")//#为自己设置的结束标志{cout<<"("<<word.code<<","<<"“"<<word.pro<<"”"<<")"<<endl;word=get_w();};return 0;}*/WordType get_w(){string str="";int code;WordType wordtmp;getch();//读一个字符getBC();//去掉空白符if(isLetter()){ //以字母开头while(isLetter()||isDigit()){str=concat(str);getch();}retract();code=Reserve(str);if(code==-1){wordtmp.code=0;wordtmp.pro=str;}//不是关键字else{wordtmp.code=code;wordtmp.pro=str;}//是关键字}else if(isDigit()){ //以数字开头while(isDigit()){str=concat(str);getch();}retract();wordtmp.code=30;wordtmp.pro=str;}else if(ch=='(') {wordtmp.code=1;wordtmp.pro="(";} else if(ch==')') {wordtmp.code=2;wordtmp.pro=")";} else if(ch=='{') {wordtmp.code=3;wordtmp.pro="{";} else if(ch=='}') {wordtmp.code=4;wordtmp.pro="}";} else if(ch==';') {wordtmp.code=5;wordtmp.pro=";";} else if(ch=='=') {wordtmp.code=6;wordtmp.pro="=";} else if(ch=='+') {wordtmp.code=7;wordtmp.pro="+";} else if(ch=='*') {wordtmp.code=8;wordtmp.pro="*";} else if(ch=='>') {wordtmp.code=9;wordtmp.pro=">";} else if(ch=='<') {wordtmp.code=10;wordtmp.pro="<";} else if(ch==',') {wordtmp.code=11;wordtmp.pro=",";} else if(ch=='\'') {wordtmp.code=12;wordtmp.pro="\'";} else if(ch=='-') {wordtmp.code=13;wordtmp.pro="-";} else if(ch=='/') {wordtmp.code=14;wordtmp.pro="/";} else if(ch=='#') {wordtmp.code=15;wordtmp.pro="#";} else if(ch=='|') {wordtmp.code=16;wordtmp.pro="|";}else {wordtmp.code=100;wordtmp.pro=ch;}return wordtmp;}void getch(){if(flag==0) //没有回退的字符ch=getchar();else //有回退字符,用回退字符,并设置标志flag=0;}void getBC(){while(ch==' '||ch=='\t'||ch=='\n')ch=getchar();}bool isLetter(){if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')return true;elsereturn false;}bool isDigit(){if(ch>='0'&&ch<='9')return true;elsereturn false;}string concat(string str){return str+ch;}void retract(){flag=1;}int Reserve(string str){int i;for(i=0;i<=8;i++){if(codestring[i]==str) //是某个关键字,返回对应的编码return codebook[i];}if(i==9) //不是关键字return -1;}【LR.cpp】#include<iostream>#include<string>#include<cstdlib>#include"cifa.h"#include"stack_num.h"#include"stack_str.h"#include"table_action.h"#include"table_go.h"using namespace std;void process(){int stepNum=1;int topStat;Stack_num statusSTK; //状态栈Stack_str symbolSTK; //符号栈Stack_num valueSTK; //值栈WordType word;Table_action actionTAB; //行为表Table_go goTAB; //转向表cout<<"请输入源程序,以#结束:";word=get_w();//总控程序初始化操作symbolSTK.push("#");statusSTK.push(0);valueSTK.push(0);cout<<"步骤\t状态栈\t符号栈\t值栈\t当前词\t动作\t转向"<<endl;//分析while(1){topStat=statusSTK.getTop(); //当前状态栈顶string act=actionTAB.getCell(topStat,word.code);//根据状态栈顶和当前单词查到的动作//输出cout<<stepNum++<<"\t";statusSTK.outStack(); cout<<"\t";symbolSTK.outStack(); cout<<"\t";valueSTK.outStack(); cout<<"\t";cout<<word.pro<<"\t";//行为为“acc”,且当前处理的单词为#,且状态栈里就两个状态//说明正常分析结束if(act=="acc"&&word.pro=="#"&&statusSTK.topNumber()==1){cout<<act<<endl;cout<<"分析成功!"<<endl;cout<<"结果为:"<<valueSTK.getTop()<<endl;return;}//读到act表里标记为错误的单元格else if(act==""){cout<<endl<<"不是文法的句子!"<<endl;cout<<"错误的位置为单词"<<word.pro<<"附近。
编译原理语义分析实验报告

编译原理语义分析实验报告编译原理语义分析实验报告引言编译原理是计算机科学的重要基础课程之一,它主要研究如何将高级语言转换为低级语言,使计算机能够理解和执行人类可读的代码。
语义分析是编译过程中的重要环节,它负责对代码进行语义检查和语义解释,以确保代码的正确性和可执行性。
本实验报告旨在介绍编译原理中语义分析的基本原理和实验过程。
一、实验目的本次实验的主要目的是通过实现一个简单的语义分析器,加深对编译原理中语义分析的理解。
具体来说,我们将实现以下功能:1. 识别并解析变量声明和赋值语句;2. 检查变量的重复声明和赋值类型的一致性;3. 计算并输出表达式的值。
二、实验环境和工具为了完成本次实验,我们需要准备以下环境和工具:1. 操作系统:Windows、Linux或MacOS;2. 编程语言:C++、Java或Python;3. 开发工具:编译器和调试器。
三、实验原理语义分析是编译过程中的重要环节,它主要负责对代码进行语义检查和语义解释。
在编译器中,语义分析器通常通过构建抽象语法树(AST)来实现。
AST是一种树状的数据结构,用于表示代码的语法结构和语义信息。
在语义分析的过程中,我们需要进行变量声明和赋值语句的解析和检查。
首先,我们需要识别代码中的变量声明和赋值语句,并将其转换成AST。
在解析过程中,我们需要检查变量的重复声明和赋值类型的一致性。
如果发现错误,我们需要报告相应的错误信息,并终止编译过程。
接下来,我们需要对表达式进行求值。
表达式是编程语言中的核心概念,它由操作数和运算符组成。
在求值过程中,我们需要考虑运算符的优先级和结合性。
为了实现这一功能,我们可以使用递归下降法或者使用运算符优先级算法。
四、实验过程1. 识别变量声明和赋值语句我们首先需要编写词法分析器,将代码中的字符序列转换成标记序列。
在词法分析的过程中,我们需要识别变量声明和赋值语句的关键字和标识符,并将其转换成相应的标记。
2. 构建抽象语法树在词法分析的基础上,我们可以构建抽象语法树。
编译原理教程实验报告

一、实验目的本次实验旨在使学生通过编译原理的学习,了解编译程序的设计原理及实现技术,掌握编译程序的各个阶段,并能将所学知识应用于实际编程中。
二、实验内容1. 词法分析2. 语法分析3. 语义分析4. 中间代码生成5. 代码优化6. 目标代码生成三、实验步骤1. 词法分析(1)设计词法分析器,识别输入源代码中的各种词法单元;(2)使用C语言实现词法分析器,并进行测试。
2. 语法分析(1)根据文法规则设计语法分析器,识别输入源代码的语法结构;(2)使用C语言实现语法分析器,并进行测试。
3. 语义分析(1)设计语义分析器,检查语法分析后的语法树,确保语义正确;(2)使用C语言实现语义分析器,并进行测试。
4. 中间代码生成(1)设计中间代码生成器,将语义分析后的语法树转换为中间代码;(2)使用C语言实现中间代码生成器,并进行测试。
5. 代码优化(1)设计代码优化器,对中间代码进行优化,提高程序性能;(2)使用C语言实现代码优化器,并进行测试。
6. 目标代码生成(1)设计目标代码生成器,将优化后的中间代码转换为特定目标机的汇编语言;(2)使用C语言实现目标代码生成器,并进行测试。
四、实验结果与分析1. 词法分析实验结果:成功识别输入源代码中的各种词法单元,包括标识符、关键字、运算符、常量等。
2. 语法分析实验结果:成功识别输入源代码的语法结构,包括表达式、语句、程序等。
3. 语义分析实验结果:成功检查语法分析后的语法树,确保语义正确。
4. 中间代码生成实验结果:成功将语义分析后的语法树转换为中间代码,为后续优化和目标代码生成提供基础。
5. 代码优化实验结果:成功对中间代码进行优化,提高程序性能。
6. 目标代码生成实验结果:成功将优化后的中间代码转换为特定目标机的汇编语言,为程序在目标机上运行做准备。
五、实验心得1. 编译原理是一门理论与实践相结合的课程,通过本次实验,我对编译程序的设计原理及实现技术有了更深入的了解。
编译原理实验三 语义分析

编译原理实验三语法分析并进行语义分析输入:经过词法分析后形成的token[]和tokenstring[]输出:检查有无语法错误,形成语法树,并检查是否符合语义。
样例程序已经能对变量声明填符号表、进行类型检查。
文法:stmt_seq -->statement ; stmt_seq | statementstatement-->decl_stmt | assign_stmtdecl_stmt-->type var_listtype-->int |floatvar_list-->id , var_list | idassign_stmt--> id := expexp-->exp + term | exp - term |termterm--> term * factor | term * factor | factorfactor-->id | num | ( exp )要求掌握理解程序设计方法。
样例程序#include<stdio.h>#include<ctype.h>typedef enum {MINUS,PLUS,TIMES,OVER,LPAREN,RPAREN,SEMI,ASSIGN,NUM,ID,INT,FLOAT,COM MA,DOLLAR} tokentype;/*记号*/typedef enum {stmtk,expk} nodekind;typedef enum {ifk,assignk,declk} stmtkind;typedef enum {opk,constk,idk} expkind;typedef enum {integer,real} exptype;typedef struct treenode{ struct treenode * child[3];struct treenode * sibling;nodekind nodek;exptype dtype ;union { stmtkind stmt; expkind exp;} kind;union { tokentype op;int val;char * name; } attr;} treenode;typedef struct bucket{char * name; exptype dtype; struct bucket * next;} bucket;bucket * hashtable[211];/*tokentype token[6]={ID,ASSIGN,NUM,PLUS,NUM,INT,FLOAT,COMMA,DOLLAR};char tokenstring[6][30]={"ab",":=","12","+","5","$"};*/tokentype token[]={INT,ID,COMMA,ID,SEMI, ID,ASSIGN,NUM,PLUS,NUM,TIMES,NUM,SEMI,ID,ASSIGN,NUM,DOLLAR};chartokenstring[][30]={"int","ab",",","xy",";","ab",":=","12","+","5","*","3",";","xy",":=","34","$"}; int wordindex=0; /*以上两个数组的索引*/treenode * decl();treenode * factor();treenode * term();treenode * exp();treenode * assign_stmt();treenode * stmt_seq();pretraverse(treenode *);int hash ( char * );void st_insert( char * ,exptype);int st_lookup ( char * );void buildsymtab(treenode * );void setnodetype(treenode * );main(){treenode * t;t=stmt_seq(); /*语法分析建语法树*/buildsymtab(t); /*建符号表*/pretraverse(t); /*遍历语法树*/setnodetype(t); /*类型检查设置*/}treenode * stmt_seq(){treenode * t;treenode * p;if(( token[wordindex]==INT)||(token[wordindex]==FLOA T)){t=decl(); }if(token[wordindex]==ID) t=assign_stmt();p=t;while( (token[wordindex]==SEMI)&& (token[wordindex]!=DOLLAR)){treenode * q;wordindex++;q=assign_stmt();p->sibling=q;p=q;}return t;}treenode * assign_stmt(){treenode * t=(treenode *)malloc(sizeof(treenode));if(token[wordindex]==ID){t->nodek=stmtk;t->kind.stmt=assignk;t->=tokenstring[wordindex];wordindex++;}else {printf("error");exit(1);}if(token[wordindex]==ASSIGN)wordindex++;else {printf("error");exit(1);}t->child[0]=exp();t->child[1]=NULL;t->child[2]=NULL;t->sibling=NULL;return t;}treenode * exp(){treenode * t;t=term();while((token[wordindex]==PLUS)||(token[wordindex]==MINUS)) {treenode * p=(treenode *)malloc(sizeof(treenode));p->nodek=expk;p->kind.exp=opk;p->attr.op=token[wordindex];p->child[0]=t;t=p;wordindex++;t->child[1]=term();t->child[2]=NULL;t->sibling=NULL;}return t;}treenode * term(){treenode * t=factor();while((token[wordindex]==TIMES)||(token[wordindex]==OVER)) {treenode * p=(treenode *)malloc(sizeof(treenode));p->nodek=expk;p->kind.exp=opk;p->attr.op=token[wordindex];p->child[0]=t;t=p;wordindex++;t->child[1]=factor();t->child[2]=NULL;t->sibling=NULL;}return t;}treenode * factor(){treenode * t;switch(token[wordindex]){case LPAREN :wordindex++;t=exp();if(token[wordindex]==RPAREN)wordindex++;else {printf("error");exit(1);}break;case NUM :t=(treenode *)malloc(sizeof(treenode));t->nodek=expk;t->kind.exp=constk;t->attr.val=atoi(tokenstring[wordindex]);t->child[0]=NULL;t->child[1]=NULL;t->child[2]=NULL;t->sibling=NULL;wordindex++;break;case ID :t=(treenode *)malloc(sizeof(treenode));t->nodek=expk;t->kind.exp=idk;t->=tokenstring[wordindex];wordindex++;break;default:printf("error");}return t;}pretraverse(treenode * t){if (t!=NULL){ if (t->nodek==stmtk) printf("stmt-id:%s\n",t->);if (t->nodek==expk && t->kind.exp==idk) printf("exp-id:%s\n",t->);if (t->nodek==expk && t->kind.exp==opk) printf("exp-op:%d\n",t->attr.op);if (t->nodek==expk && t->kind.exp==constk) printf("exp-val:%d\n",t->attr.val);if(t->child[0]!=NULL) pretraverse(t->child[0]);if(t->child[1]!=NULL) pretraverse(t->child[1]);if(t->child[2]!=NULL) pretraverse(t->child[2]);if(t->sibling!=NULL) pretraverse(t->sibling);}}treenode * decl(){treenode * p,* q,* t1;treenode * t=(treenode *)malloc(sizeof(treenode));t->nodek=stmtk;t->kind.stmt=declk;t->=tokenstring[wordindex];t->child[1]=NULL;t->child[2]=NULL;wordindex++;if(token[wordindex]==ID){t1=(treenode *)malloc(sizeof(treenode));t->child[0]=t1;t1->nodek= expk;t1->kind.exp=idk;t1->=tokenstring[wordindex];t1->child[0]=NULL;t1->child[1]=NULL;t1->child[2]=NULL;t1->sibling=NULL;wordindex++;p=t1;while( token[wordindex]==COMMA){ wordindex++;q=(treenode *)malloc(sizeof(treenode));q->nodek= expk;q->kind.exp=idk;q->=tokenstring[wordindex];q->child[0]=NULL;q->child[1]=NULL;q->child[2]=NULL;q->sibling=NULL;p->sibling=q;wordindex++;p=q;}return t;}}int hash ( char * key ){ int temp = 0;int i = 0;while (key[i] != '\0'){ temp = ((temp << 4) + key[i]) % 211;++i;}return temp;}void st_insert( char * name,exptype datatype){ int h = hash(name);bucket * l = hashtable[h];while ((l != NULL) && (strcmp(name,l->name) != 0)) l = l->next;if (l == NULL) /* variable not yet in table */{ l = (bucket *) malloc(sizeof(bucket));l->name = name;l->dtype=datatype;l->next = NULL;l->next = hashtable[h];hashtable[h] = l; }}int st_lookup ( char * name ){ int h = hash(name);bucket * l = hashtable[h];while ((l != NULL) && (strcmp(name,l->name) != 0)) l = l->next;if (l == NULL) return -1;else return 1;}void buildsymtab(treenode * t){exptype datatype;treenode * q;if (t!=NULL){ if (t->nodek==stmtk && t->kind.stmt==declk){ if (strcmp(t->,"int")==0) datatype=integer;if(t->=="float") datatype=real;q=t->child[0];while(q!=NULL){ st_insert(q->,datatype);q=q->sibling;}}if(t->nodek!=stmtk && t->kind.stmt!=declk && t->child[0]!=NULL) buildsymtab(t->child[0]);if(t->child[1]!=NULL) buildsymtab(t->child[1]);if(t->child[2]!=NULL) buildsymtab(t->child[2]);if(t->sibling!=NULL) buildsymtab(t->sibling);}}void setnodetype(treenode * t){if(t!=NULL){if(t->child[0]!=NULL) setnodetype (t->child[0]);if(t->child[1]!=NULL) setnodetype (t->child[1]);if (t->nodek==expk && t->kind.exp==idk) {int h = hash(t->);bucket * l = hashtable[h];while ((l != NULL) && (strcmp(t->,l->name) != 0))l = l->next;if (l==NULL) {printf("no declare");exit(1);}else t->dtype=l->dtype;}if (t->nodek==expk && t->kind.exp==constk) t->dtype=integer;if (t->nodek==expk && t->kind.exp==opk) {if(t->child[1]==NULL) t->dtype=t->child[0]->dtype;elseif(t->child[0]->dtype==t->child[1]->dtype )t->dtype=t->child[0]->dtype;else {printf("type no match");exit(1);}} if (t->nodek==stmtk) t->dtype=t->child[0]->dtype;if(t->sibling!=NULL) setnodetype (t->sibling);}}查看主要内存变量:t-> t->attr.valt->child[0]-> t->child[0]->attr.valt->child[1]-> t->child[1]->attr.valt->sibling-> t->sibling->attr.val语法树样例:。
编译原理的实验报告

一、实验目的1. 理解编译原理的基本概念和原理。
2. 掌握编译器的各个阶段及其实现方法。
3. 能够运用编译原理的知识解决实际问题。
二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发工具:Visual Studio 20194. 实验内容:词法分析、语法分析、语义分析、中间代码生成、代码优化、目标代码生成三、实验内容1. 词法分析(1)实验目的:实现一个简单的词法分析器,将源代码中的字符序列转换为词法符号序列。
(2)实验步骤:1)定义词法符号类型,包括标识符、关键字、运算符、常量等。
2)设计词法分析器算法,对源代码进行遍历,将字符序列转换为词法符号序列。
3)实现词法分析器程序,输出词法符号序列。
(3)实验结果:输入源代码:int a = 10;输出词法符号序列:{<int, int>, <a, a>, <=, =>, <10, 10>, <;, ;>}2. 语法分析(1)实验目的:实现一个简单的语法分析器,将词法符号序列转换为抽象语法树(AST)。
(2)实验步骤:1)定义语法规则,包括产生式、非终结符、终结符等。
2)设计语法分析算法,根据语法规则对词法符号序列进行解析,生成AST。
3)实现语法分析器程序,输出AST。
(3)实验结果:输入词法符号序列:{<int, int>, <a, a>, <=, =>, <10, 10>, <;, ;>}输出AST:```AST:- ExpressionStatement- Expression- BinaryExpression- Identifier: a- Operator: =- Constant: 10```3. 语义分析(1)实验目的:实现语义分析器,对AST进行语义检查,确保程序的正确性。
(2)实验步骤:1)定义语义规则,包括类型检查、作用域检查等。
天津理工大学编译原理实验3:语义分析

实验报告学院名称:计算机科学与工程学院****** 实验报告内容详述 ****** 程序流程图实验结果:源代码:#include<iostream>#include<cstring>#define size 1024using namespace std;int step=0;typedef struct variable_T{char operate;//操作符 string var1;// 变量 1 string var2;// 变量 2 int num;// 第几个变量 }variable_T; variable_T t[size];// 记录四元式变量的变量 inttsize=-1;// 表示是第 tsize+1 个变量typedef struct char_stack{char content;//当前字符 string endchar;//这个符号代表的中间变量可以是 i, 也可以是 t1, t2, 等等 int num;// 和该字符相关的中间变量的序号}char_stack;string table[19][13]={// + - * / ^ ) # ( i E TF P/* 0 */ "err","err","err","err","err","err","err", "s5", "s6", "1", "2", "3", "4",/* 1 */ "s7","s8","err","err","err","err","acc","err","err","err","err","err","err", /* 2 */ "r3", "r3", "s9","s10","err", "r3","r3","err","err","err","err","err","err",/* 3 */ "r6", "r6", "r6", "r6","err", "r6","r6","err","err","err","err","err","err",/* 4 */ "r8", "r8", "r8", "r8","s11", "r8","r8","err","err","err","err","err","err",/* 5 */ "err","err","err","err","err","err","err", "s5", "s6", "c", "2", "3", "4",/* 6 */"r10","r10","r10","r10","r10","r10","r10","err","err","err","err","err" ,"err",/* 7 */ "err","err","err","err","err","err","err", "s5", "s6","err", "d", "3", "4",/* 8 */ "err","err","err","err","err","err","err", "s5", "s6","err", "e", "3", "4",/* 9 */ "err","err","err","err","err","err","err", "s5", "s6","err","err", "f", "4",/* 10*/ "err","err","err","err","err","err","err", "s5", "s6","err","err", "g", "4",/* 11*/ "err","err","err","err","err","err","err", "s5", "s6","err","err", "h", "4",/* 12*/ "s7",/* 13*/ "r1", "r1", "s9","s10","err", "r1","r1","err","err","err","err","err","err",/* 14*/ "r2", "r2", "s9","s10","err", "r2","r2","err","err","err","err","err","err",/* 15*/ "r4", "r4", "r4", "r4","err", "r4","r4","err","err","err","err","err","err",/* 16*/ "r5", "r5", "r5", "r5","err", "r5","r5","err","err","err","err","err","err",/* 17*/ "r7", "r7", "r7", "r7","err", "r7","r7","err","err","err","err","err","err",/* 18*/ "r9", "r9", "r9", "r9", "r9", "r9","r9","err","err","err","err","err","err"};int getLength(char str[size]){int i=0;while(str[i]!='\0')i++;return i;}int getLengthc(char_stack str[size]){int i=0;while(str[i].content!='\0')i++;return i;}int getstringLength(string str){int i=0;while(str[i]!='\0')i++;return i;}char gettop(char stack[size],int top){if(stack[top]!='\0')return stack[top];elsereturn '#';}void popstack(char *stack,int *pointer,int times){int p;for(int i=1;i<=times;i++){p=*pointer;stack[p]='\0';(*pointer)--;}}void popstackc(char_stack *stack,int *pointer,int times){int p;for(int i=1;i<=times;i++){p=*pointer;stack[p].content='\0';(*pointer)--;}}void pushstack(char_stack *stack,int *pointer,char *stack_state,int *pointer_state,char str,char sx,int x){int i=0;if(x==0) cout<<"\t\t\t 状态 "<<sx<<" 进状态栈 ";else if(x==1) cout<<" 状态 "<<sx<<" 进状态栈 ";if(str!='#'){cout<<str<<" 进字符栈 ";stack[(*pointer)].content=str;}(*pointer_state)++;stack_state[(*pointer_state)]=sx;}int getcol(char top){switch(top){case '+':return 0;case '-':return 1;case '*':return 2;case '/':return 3;case '^':return 4;case ')':return 5;case '#':return 6;case '(':return 7;case 'i':return 8;case 'E':return 9;case 'T':return 10;case 'F':return 11;case 'P':return 12;default:cout<<"Error! This character string is not this grammer`s sentence."<<endl; return -1;}}int getraw(char raw){switch(raw){case '0':return 0;case '1':return 1;case '2':return 2;case '3':return 3;case '4':return 4;case '5':return 5;case '6':return 6;case '7':return 7;case '8':return 8;case '9':return 9;case 'a':return 10;case 'b':return 11;case 'c':case 'e':return 14;case 'f':return 15;case 'g':return 16;case 'h':return 17;case 'i':return 18;default:cout<<"Error! This character string is not this grammer`s sentence."<<endl; return -1;}}char getraw_content(string str){if(str=="1")return '1';else if(str=="2")return '2';else if(str=="3")return '3';else if(str=="4")return '4';else if(str=="c")return 'c';else if(str=="d")return 'd';else if(str=="e")return 'e';else if(str=="f")return 'f';else if(str=="g")return 'g';else if(str=="h")return 'h';else if(str=="i")return 'i';}string get_tx(int num){switch(num){case 1:return "t1";case 2:return "t2";case 3:return "t3";case 4:return "t4";case 5:return "t5";case 6:return "t6";case 7:return "t7";case 8:return "t8";case 9:return "t9";case 10:return "t10";case 11:return "t11";case 12:case 14:return "t14";case 15:return "t15";case 16:return "t16"; //......本程序暂时用到这么多,等有时间编写合适的可以将数字转换为字符串的函数时,即可更改本函数}}void show(char str[size],int index){int length=getLength(str);if(index!=-1)cout<<"\t";for(int i=index+1;i<length;i++)cout<<str[i];}void showc(char_stack str[size],int index){int length=getLengthc(str);if(index!=-1)cout<<"\t";for(int i=index+1;i<length;i++)cout<<str[i].content;}void switch_method(char_stack *stack,int *pointer,char *state_stack,int *pointer_state,stringproduction,char *str,int *index){step++; cout<<"\n"<<step<<"\t";// 显示步骤 show(state_stack,-1);//显示状态栈 cout<<"\t"; showc(stack,-1);// 显示符号站cout<<"\t"<<str[(*index)]<<"\t";// 显示当前字符 show(str,(*index));// 显示输入串 char c=str[(*index)];if(production=="err"){cout<<"Error! This character string is not this grammer`s sentence."<<endl; return ;}else if(production=="s5"){char sx='5';(*index)++;pushstack(stack,pointer,state_stack,pointer_state,c,sx,0);}else if(production=="s6"){char sx='6';(*index)++;pushstack(stack,pointer,state_stack,pointer_state,c,sx,0);}else if(production=="s7"){char sx='7';(*index)++;pushstack(stack,pointer,state_stack,pointer_state,c,sx,0);}else if(production=="s8"){char sx='8';(*index)++;pushstack(stack,pointer,state_stack,pointer_state,c,sx,0);}else if(production=="s9"){char sx='9';(*index)++;pushstack(stack,pointer,state_stack,pointer_state,c,sx,0);char sx='a';(*index)++;pushstack(stack,pointer,state_stack,pointer_state,c,sx,0);}else if(production=="s11"){char sx='b';(*index)++;pushstack(stack,pointer,state_stack,pointer_state,c,sx,0);}else if(production=="s18"){char sx='i';(*index)++;pushstack(stack,pointer,state_stack,pointer_state,c,sx,0);}else if(production=="r1"){int po=(*pointer);// 用 P规约该表达式,有效变量在 E的 endchar 中,需要找到 E 的位置,即下面的操作 string st=stack[po].endchar;// 对应 Fpo-=2; string se=stack[po].endchar;// 在规约之前记录下要规约的字符所代表的变量。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
if(!ss&&c==strlen(t)-2)
is16=1;
if(is16&&ss)
{
char *s;
int i=(int)strtol(t,&s,16);
char ss[100];
//sprintf(ss,"%d",i);
return true;
};
bool resetstringJia3(string &strsor)
{
int index1 = strsor.find("-+");
if(index1 == string::npos)
return false;
strsor.replace(index1, 2, "-", 1);
return 1;
}
//cout<<"十六进制整数 "<<t<<endl;
else
return 0;
//cout<<"错误数据 "<<t<<endl;
using namespace std;
bool newstringXC(string &strsor);
bool newstringJJ(string &strsor);
bool resetstringJia1(string &strsor);
bool resetstringJia2(string &strsor);
};
bool newstringJJ(string &strsor)
{
int index1 = strsor.find_first_of("+-", 1);
if(index1 == string::npos)
return false;
int index2 = strsor.find_first_of("+-*/", index1+1);
while((resetstringJia4(childstr))){}
}
while(newstringJJ(childstr))
{
while((resetstringJia1(childstr))){}
while((resetstringJia2(childstr))){}
输出:
第五个单词‘(’出错
第八个单词‘)’出错
输入 0x11+07
输出:
运算式语法正确!
运算结果 24.00000
输入 0x11.88+07
输出:
运算式语法正确!
运算结果 24.75000
输入 0x11+07.44
输出:
运算式语法正确!
运算结果 24.75000
return true;
};
bool resetstringJia2(string &strsor)
{
int index1 = strsor.find("+-");
if(index1 == string::npos)
return false;
strsor.replace(index1, 2, "-", 1);
};
bool newstringXC(string &strsor)
{
int index1 = strsor.find_first_of("*/", 0);
if(index1 == string::npos)
return false;
int index2 = strsor.find_first_of("+-*/", index1+2);
/*
输入(0124.3+0x35a.4f)*12
输出:
运算式语法正确!
运算结果 11331.75000
输入 12a+45*013468-0x23a3
输出:
第一个单词是错误数据
第五个单词是错误数据
运算式语法正确!
输入 (1-44))/4
输出:
第六个单词‘)’出错
输入 (1-4(4))/4
while((resetstringJia1(strsor))){}
while((resetstringJia2(strsor))){}
while((resetstringJia3(strsor))){}
while((resetstringJia4(strsor))){}
return true;
if(index2 == string::npos)
index2 = strsor.length();
int index3 = strsor.find_last_of("+-*/", index1-1);
if((index3 == string::npos) || (index3 == 0))
while(newstringXC(childstr))
{
while((resetstringJia1(childstr))){}
while((resetstringJia2(childstr))){}
while((resetstringJia3(childstr))){}
bool resetstringJia3(string &strsor);
bool resetstringJia4(string &strsor);
bool newstringKH(string &strsor)
{
int index1 = strsor.rfind("(", strsor.length()-1);
char c_str3[50];
memset(c_str3, 0, 50);
sprintf(c_str3, "%.5f", dob3);
strsor.replace(index3 +1, index2-index3-1, c_str3, strlen(c_str3));
return true;
输入 10*(2+3)/100
输出:
运算式语法正确!
运算结果 0.50000
*/
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <string>
#include <sstream>
double dob2 = atof(str2.c_str());
double dob3;
if(strsor.at(index1) == '*')
dob3 = dob1 * dob2;
else if(strsor.at(index1) == '/')
dob3 = dob1 / dob2;
}
if(t[0]=='0'&&t[1]=='x')
{
int c=0;
for(j=2;j<strlen(t);j++)
if((t[j]-'0'>=0&&t[j]-'0'<10)||(t[j]-'a'>=0&&t[j]-'a'<6))
c++;
if(ss&&c==strlen(t)-3)
index3 = -1;
string str1;
str1.assign(strsor, index3+1, index1-index3-1);
string str2;
str2.assign(strsor, index1+1, index2-index1-1);
double dob1 = atof(str1.c_str());
return true;
};
char yuyi[100]={'\0'};
int f(char *t)
{
int j;
bool ss=0,is8=0,is10=0,is16=0;
for(j=0;j<strlen(t);j++)
{
if(t[j]=='.')
ss=1;
//cout<<"十六进制实数 "<<t<<endl;
else if(is16)
{
char *s;
int i=(int)strtol(t,&s,16);
char ss[100];
sprintf(ss,"%d",i);
strcat(yuyi,ss);
//strcat(yuyi,ss);
double ans=(double)i;
i=0;
double sum=0;