语义分析实验报告.doc

合集下载

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

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

编译原理第六章语义分析目录1. 实验题目和要求 (2)2. 实验分析和思考 (3)3. 翻译方案 (4)4. LR实现自底向上分析(摘自语法分析实验) (5)4.1.构造识别所有活前缀的DFA (5)5.1. 扩充分析栈 ................................................................................................................ 7 5.2. 改造分析程序 ............................................................................................................ 7 5.3. 编程实现 .................................................................................................................... 76.运行结果截图: (13)1. 实验题目和要求题目:语义分析程序的设计与实现。

实验内容:编写语义分析程序,实现对算术表达式的类型检查和求值。

要求所分析算术表达式由如下的文法产生。

numE idF F F T F T T T T E T E E |)(||/|*||→→-+→ 实验要求:用自底向上的语法制导翻译技术实现对表达式的分析和翻译。

(1) 写出满足要求的语法制导定义或翻译方案。

(2) 编写分析程序,实现对表达式的类型进行检查和求值,并输出: ① 分析过程中所有产生式。

② 识别出的表达式的类型。

③ 识别出的表达式的值。

(3) 实验方法:可以选用以下两种方法之一。

① 自己编写分析程序。

② 利用YACC 自动生成工具。

2.实验分析和思考由于要求进行类型检查和求值,所以可以定义两个综合属性,一个记录值一个记录类型,存放在结构中,一并传入传出。

实验三-语义分析-实习报告

实验三-语义分析-实习报告

实验三语义分析一、实习目的通过上机实习,加深对语法制时翻译原理的理解,掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法.二、实习要求采用递归下降语法制导翻译法对算术表达式、赋值语句、条件语句、循环语句进行语义分析生成四元式序列。

三、实习过程实习代码;/***JavaCC file*/options {JDK_VERSION = "1。

5”;static=false;}PARSER_BEGIN(whileParse)package whileparse;import java。

io.FileInputStream;import java。

io.FileNotFoundException;import java.util。

ArrayList;public class whileParse {public int count=0; /*四元式标号*/public static ArrayList<Sys〉sysList = new ArrayList<Sys〉();public int ncount=0;/*临时变量下标*/public static void main(String args[]) throws ParseException {FileInputStream fileStream;t ry {fileStream = new FileInputStream("data/test.c");whileParse parser = new whileParse(fileStream);System.out。

println("Reading from standard input。

.”);System。

out。

println("Enter c programe only main()with only while();\" :");try {switch (parser.start()){case 0:System。

河北工业大学语义分析实验报告

河北工业大学语义分析实验报告

实验三语义分析程序实现一、实验设计在实现词法、语法分析程序的基础上,编写相应的语义子程序,进行语义处理,加深对语法制导翻译原理的理解,进一步掌握将语法分析所识别的语法范畴变换为某种中间代码(四元式)的语义分析方法。

基本实验题目:对文法G2[<算术表达式>]中的产生式添加语义处理子程序,完成运算对象是简单变量(标识符)和无符号数的四则运算的计值处理,将输入的四则运算转换为四元式形式的中间代码。

语法制导翻译模式是在语法分析的基础上,增加语义操作来实现的,实际上是对前后文无关文法的一种扩展。

一般而言,首先需要根据进行的语义分析工作,完成对给定文法的必要拆分和语义动作的编写,从而为每一个产生式都配备相应的语义子程序,以便在进行语法分析的同时进行语义解释。

即在语法分析过程中,每当用一个产生式进行推导或归约时,语法分析程序除执行相应的语法分析动作之外,还要调用相应的语义子程序,以便完成生成中间代码、查填有关表格、检查并报告源程序中的语义错误等工作。

每个语义子程序需指明相应产生式中各个符号的具体含义,并规定使用该产生式进行分析时所应采取的语义动作。

这样,语法制导翻译程序在对源程序从左到右进行的一遍扫描中,既完成语法分析任务,又完成语义分析和中间代码生成方面的工作。

本实验要求从编译器的整体设计出发,重点通过对实验二中语法分析程序的扩展,完成一个编译器前端程序的编写、调试和测试工作,形成一个将源程序翻译为中间代码序列的编译系统。

二、程序代码在词法分析和语法分析的基础上,完成了语义的分析,同样采用了头文件的形式,在VC++6.0中运行#include<stdio.h>#include<ctype.h>#include<stdlib.h>#include<string.h>#include<math.h>#include"cifa.h"#include"fenxibiao.h"# define PL 15 //+# define MI 16 //-# define MU 17# define DI 18#define acc 100#define MAXState 20#define NUMBER 9//表达式的个数#define MAXTEMP 10//最多临时变量的个数int State[MAXState];//状态栈int i=0;int CURRENTSTATE=0;//标识当前状态int LENGTH[NUMBER]={1,3,3,1,3,3,1,3,1};//表达式右边的长度int length;int index;//索引int Yes=0;//判断是否结束int tag=0;//判断是否需要调用词法程序//extern char * cifa();double e1,t4,f7;//整形char e12[20],t42[20],f72[20];//字符型int TEMP[MAXTEMP];int temp=0;int biaoshifu=0;FILE * fp;void REPORT_ERROR(){Yes=1;long f1=ftell(fp);char ch=fgetc(fp);fseek(fp,-1,1);printf("语法错误,第%d个字符'%C'处\n",f1,ch); }void Accept(){Yes=1;//printf("语法分析成功\n");}int INDEX(char a)//获取当前字符串对应的索引{int i;switch (a){case 'E':i=8;return(i);break;case 'T':i=9;return(i);break;case 'F':i=10;return(i);break;default: REPORT_ERROR();return(0);break;}}void Gen(int a,double i1,double i2,int t)//输出四元式{switch(a){case PL:printf("(+,%g,%g,%d)\n",i1,i2,t);break;case MI:printf("(-,%g,%g,%d)\n",i1,i2,t);break;case MU:printf("(*,%g,%g,%d)\n",i1,i2,t);break;case DI:printf("(/,%g,%g,%d)\n",i1,i2,t);break;default:break;}}void yuyi(int n)//语义子程序{switch(n){case 1:{temp++;//产生临时变量,Gen(PL,e1,t4,temp);e1=temp;break;}case 2:{temp++;//产生临时变量,TEMP[temp] Gen(MI,e1,t4,temp);e1=temp;break;}case 3:{e1=t4;break;}case 4:{temp++;Gen(MU,t4,f7,temp); t4=temp;break;}case 5:{temp++;Gen(DI,t4,f7,temp); t4=temp;break;}case 6:{t4=f7;break;}case 7:{f7=e1;break;}case 8:{f7=FCON;break;}default :printf("error\n");break;}}void Gen2(int a,char *i1,char *i2,int t)//输出四元式{switch(a){case PL:printf("(+,%s,%s,%d)\n",&i1,&i2,t);break;case MI:printf("(-,%s,%s,%d)\n",&i1,&i2,t);break;case MU:printf("(*,%s,%s,%d)\n",&i1,&i2,t);break;case DI:printf("(/,%s,%s,%d)\n",&i1,&i2,t); break;default:break;}}void fuzhi(char *a,char *b)//将数组b赋值给数组a {}void yuyi2(int n)//语义子程序{switch(n){case 1:{temp++;//产生临时变量Gen2(PL,e12,t42,temp);e12[0]=temp;break;}case 2:{temp++;//产生临时变量,TEMP[temp] Gen2(MI,e12,t42,temp);e12[0]=temp;break;}case 3:{//e12=t42;strcpy(e12,t42);break;}case 4:{temp++;Gen2(MU,t42,f72,temp); t42[0]=temp;break;}case 5:{temp++;Gen2(DI,t42,f72,temp); t42[0]=temp;break;}case 6:{//t42=f72;strcpy(t42,f72); break;}case 7:{//f72=e12;strcpy(f72,e12);break;}case 8:{//f72=TOKEN[0];strcpy(f72,TOKEN);break;}default :printf("error\n"); break;}}void INPUT(int a){index=a;int index2=0;if(Table[CURRENTSTATE][index]!=acc) {if (Table[CURRENTSTATE][index]==0)//报错{REPORT_ERROR();}elseif (Table[CURRENTSTATE][index]<20)//移近{ i++;State[i]=Table[CURRENTSTATE][index]; CURRENTSTATE=State[i];}else //规约{tag=1;length=LENGTH[Table[CURRENTSTATE][index]-20]; i=i-length;//指针回退switch(Table[CURRENTSTATE][index]-20){case 1:case 2:case 3:index2=8;break;case 4:case 5:case 6:index2=9;break;case 7:case 8:index2=10;break;default :REPORT_ERROR();break;}if (biaoshifu!=1)//不是标识符{yuyi(Table[CURRENTSTATE][index]-20);//规约调用语义子程序}else{yuyi2(Table[CURRENTSTATE][index]-20);//规约调用语义子程序}CURRENTSTATE=State[i];i++;State[i]=Table[CURRENTSTATE][index2];CURRENTSTATE=State[i];}}else{Accept();CURRENTSTATE=0;}}void main(){int res;State[0]=0;if((fp=fopen("b.txt","r"))==NULL) {printf("file open error!\n");exit(0);}else{res=cifa(fp);if(start==1)//文件以begin开始{do{res=cifa(fp);if(end==0){fseek(fp,-1,1);//文件指针回退一个*/。

语义分析实验报告

语义分析实验报告

云南大学编译原理实验报告实验题目:语义分析学院:信息学院专业:计算机科学与技术学号: 20091060064姓名:刘继远目录一、实验目的 0二、实验内容 0三、源程序分析 (2)1、程序采用的BNF (2)2、根据语义要求得到对应的翻译模式 (3)3、实现原理 (4)4、文法的属性分析 (4)5、过程设计 (5)6、子程序说明 (6)四、设计的基本思想(包括修改之后的属性文法、属性类型分析、翻译模式) (6)1、增加除法运算 (7)2、禁止同名重复声明 (8)五、结果及分析 (8)一、实验目的进一步理解递归下降分析原理和实现方法,理解语义分析的基本机制,掌握语义子程序的构造方法。

二、实验内容将带变量声明的表达式翻译为四元式序列,其中包括以下要求:非终结符号D实现定义两种类型int, real变量的声明;非终结符号S实现变量之间的*,+,: =(赋值运算)两个关键字 int 和real变量之间的*,+,: =(赋值) 运算只能使用声明过的变量,所以要检查使用的变量是否声明过。

对每个*,+,: =(赋值) 运算生成一条四元式如(*,A,B,T1),其中T1是临时变量*优先级别高于+,*满足左结合规则三、源程序分析这是一个简单的包含词法、语法、语义分析的程序:语义分析.h和语义分析.cpp。

实现的基本原理是自顶向下分析,单遍扫描,以语法分析为核心,调用词法分析,并实现语义分析。

1、程序采用的BNFP→ DS.D→B; DD→εB→int L | real LL→id | L,idS→ V := E HH→;S | εE→E+T | TT→T*F|FF→( E )F→idV→id消除左递归之后的等价文法start→ DS.D→B; DD→εB→int L | real LL→id AA→ ,idAA→εS→ V := E HH→;S | εE→T RR→+T RR→εT→F PP→* F PP→εF→( E )F→idV→id2、根据语义要求得到对应的翻译模式start→ DS.D→ B; DD→εB→ int L { L.type := int } | real L { L.type := real }L→ id { A.Type := L.type enter(v.entry, L.type)}AA→ ,idA { A1.Type := A.type enter(v.entry,A.type)}A→εS→ V := E { gen( ":=", E.place,0,V.place) } HH→;S | εE→T { R.i:=T.place} R {E.place:=R.s}R→+T { R1.i:= newtemp; gen( "+", R.i, T.place , R1.i) } R {R.s:= R1.s; }R→ ε {Rs=R.i}T→F { P.i:=F.place} P { T.place:=P.s}P→* F { p1.i:= newtemp; gen( "*", P.i, F.place , T) } P {P.s:=p1.s; }P→ε {P.s=P.i}F→( E ) { F.place := E.place}F→id {F.place:=position (id)}V→id {V.place:=position(id)}3、实现原理基于翻译模式的自上而下语义处理(翻译)1.对每个非终结符 A,构造一个函数,以 A 的每个继承属性为形参,以A的综合属性为返回值(若有多个综合属性,可返回记录类型的值)。

语义分析

语义分析

三、词法、语法、语义分析结合一、实验目的与要求在实现词法、语法分析程序的基础上,编写相应的语义子程序,进行语义处理,加深对语法制导翻译原理的理解,进一步掌握将语法分析所识别的语法范畴变换为某种中间代码(四元式)的语义分析方法,并完成相关语义分析器的代码开发。

二、实验内容语法制导翻译模式是在语法分析的基础上,增加语义操作来实现的。

对于给定文法中的每一产生式,编写相应的语义子程序。

在语法分析过程中,每当用一个产生式进行推导或归约时,语法分析程序除执行相应的语法分析动作之外,还要调用相应的语义子程序,以便完成生成中间代码、查填有关表格、检查并报告源程序中的语义错误等工作。

每个语义子程序需指明相应产生式中各个符号的具体含义,并规定使用该产生式进行分析时所应采取的语义动作。

这样,语法制导翻译程序在对源程序从左到右进行的一遍扫描中,既完成语法分析任务,又完成语义分析和中间代码生成方面的工作。

输入:包含测试用例,如由无符号数和+、−、*、/、(、)构成的算术表达式的源程序文件。

输出:将源程序转换为中间代码形式表示,并将中间代码序列输出到文件中。

若源程序中有错误,应指出错误信息。

三、实验设计语法制导翻译模式实际上是对前后文无关文法的一种扩展。

一般而言,首先需要根据进行的语义工作,完成对文法的必要拆分和语义动作的编写,从而为每个产生式都配备相应的语义子程序,以便在进行语法分析的同时进行语义解释。

要求从编译器的整体设计出发,重点通过对实验二中语法分析程序的扩展,完成一个编译器前端程序的编写、调试和测试工作,形成一个将源程序翻译为中间代码序列的编译系统。

对文法G3[<算术表达式>]中的产生式添加语义处理子程序,完成无符号数的四则运算的计值处理,将输入的四则运算转换为四元式形式的中间代码。

本实验只进行了算术表达式四元式的翻译。

四、源代码1、在.h文件中添加了//语义分析部分#define PMAX 5//define 后面不加括号,定义产生式符号属性字符串的长度int NXQ=0; /*全局变量NXQ用于指示所要产生的下一个四元式的编号*/int NXTemp=1;//整型变量NXTemp指示临时变量的编号int SentenceCount=1;//存放文件中句子的个数struct QUATERNION /*四元式表的结构*/{char op[PMAX]; /*操作符*/char arg1[PMAX]; /*第一个操作数*/char arg2[PMAX]; /*第二个操作数*/char result[PMAX]; /*运算结果*/}pQuad[256]; /*存放四元式的数组*/char EBracket_Place[PMAX];//(E)的语义属性char i_Place[PMAX];char E_Place[PMAX];char T_Place[PMAX];char F_Place[PMAX];//char JudgeStr[100];int EXCUTE (int state, int symbol,FILE *fp,char JudgeStr[],int row,int index);int GetChar (char ch);int HandleError (char StrJudge[],int row);int Push( int State );int Pop(int count);int SLRControl(FILE* fp);void GEN(char *Op, char *Arg1, char *Arg2, char *Result);char *NewTemp(void);void NextSentence(FILE* fp);//当语法或者词法产生错误的时候,跳过当前错误的句子,将文件指针指向下一个句子的开始#define MAXLENGTH 10;void GEN(char *Op, char *Arg1, char *Arg2, char *Result){strcpy (pQuad[NXQ].op, Op); /*pQuad为全局变量,是用于存放四元式的数组*/strcpy (pQuad[NXQ].arg1, Arg1);strcpy (pQuad[NXQ].arg2, Arg2);strcpy (pQuad[NXQ].result, Result);NXQ++; /*全局变量NXQ用于指示所要产生的下一个四元式的编号*/}char *NewTemp(void) /*产生一个临时变量*/{char *TempID=(char*)malloc(PMAX);sprintf (TempID, "T%d", NXTemp++);return TempID;}2、在.cpp文件中修改的部分int SLRControl(FILE* fp){while(Action[TopState][InputWordType][0] != 'A'){if (UNKNOWN==InputWordType){printf("**********************分析语句%i 时词法分析出错******************\n",SentenceCount);return 0;}printf("栈顶状态:%i\n",TopState);printf("扫描的单词类型:%i\n",InputWordType);/*if ('A'==Action[State][WordType][0]){TopState=0;//正确后把栈顶状态置为初始化StackPoint=0;//同理上面memset(StateStack,-1,sizeof(StateStack));printf("Right!");return 1;}*/if (-1==TopState){printf("分析语句%i 时状态栈栈顶指针错误!分析结束\n",SentenceCount);return 0;}if (' ' == Action[TopState][InputWordType][0]){printf("分析语句%i 时语法分析出错!分析结束\n",SentenceCount);return 0;}else if('s'==Action[TopState][InputWordType][0]){//TopState=atoi(&Action[TopState][InputWordType][1]);Push(atoi(&Action[TopState][InputWordType][1]));printf("执行压栈操作\n");if (EOF!=fgetc(fp)){scanner(fp);}else{printf("语句%i 不完整!分析结束\n",SentenceCount);return 0;}}else if('r'==Action[TopState][InputWordType][0]){//do//用一个while循环为了可能遇到连续规约的情况,即从文件中扫描一个单词之后,可能连续规约多次//{int ProductionNum=atoi(&Action[TopState][InputWordType][1]);int ProdutionLeft=0;if (1==ProductionNum){ProdutionLeft=E;//为下面差goto表提供列坐标Pop(3);printf("用产生式1 归约\n");char* Temp=NewTemp();GEN("+",E_Place,T_Place,Temp);strcpy(E_Place,Temp);printf("生成四元式:(“+”,E_Place,T_Place,E_Place)\n"); }else if(2==ProductionNum){ProdutionLeft=E;Pop(3);printf("用产生式2 归约\n");char* Temp=NewTemp();GEN("-",E_Place,T_Place,Temp);strcpy(E_Place,Temp);printf("生成四元式:(“-”,E_Place,T_Place,E_Place)\n"); }else if(3==ProductionNum){ProdutionLeft=E;Pop(1);printf("用产生式3 归约\n");char* Temp=NewTemp();GEN("",T_Place,"",Temp);strcpy(E_Place,Temp);printf("生成四元式:(-,-,T_Place,E_Place)\n");}else if(4==ProductionNum){ProdutionLeft=T;Pop(3);printf("用产生式4 归约\n");char* Temp=NewTemp();GEN("*",T_Place,F_Place,Temp);strcpy(T_Place,Temp);printf("生成四元式:(“*”,T_Place,F_Place,T_Place)\n"); }else if(5==ProductionNum){ProdutionLeft=T;Pop(3);printf("用产生式5 归约\n");char* Temp=NewTemp();GEN("/",T_Place,F_Place,Temp);strcpy(T_Place,Temp);printf("生成四元式:(“/”,T_Place,F_Place,T_Place)\n");}else if(6==ProductionNum){ProdutionLeft=T;Pop(1);printf("用产生式6 归约\n");char* Temp=NewTemp();GEN("+",F_Place,"",Temp);strcpy(T_Place,Temp);printf("生成四元式:(-,-,F_Place,T_Place)\n");}else if(7==ProductionNum){ProdutionLeft=F;Pop(3);printf("用产生式7 归约\n");char* Temp=NewTemp();GEN("+",EBracket_Place,"",Temp);strcpy(F_Place,Temp);printf("生成四元式:(-,-,(E)_Place,F_Place)\n");}else if(8==ProductionNum){ProdutionLeft=F;Pop(1);printf("用产生式8 归约\n");char* Temp=NewTemp();GEN("+",i_Place,"",Temp);strcpy(F_Place,Temp);printf("生成四元式:(-,-,i_Place,F_Place)\n");}else{printf("分析语句%i 时产生式编号超出范围!分析结束\n",SentenceCount);return 0;}Push(Goto[TopState][ProdutionLeft]);//}while('r' == Action[TopState][InputWordType][0])}}printf("栈顶状态:%i\n",TopState);printf("扫描的单词类型:%i\n",InputWordType);printf("*********************************语句%i 正确*********************************\n",SentenceCount);return 1;}void NextSentence(FILE* fp){while ('#'!= ch){ch=fgetc(fp);}if('\n'==fgetc(fp)){return;}SentenceCount++;return;}/////////////////////////////////主程序int main(int argc, char* argv[]){extern char ch;FILE *fp;if((fp=fopen("date.txt","r"))==NULL){printf("\nfile open error!\n");exit(0);}if(ch=fgetc(fp)=='EOF')//不管小括号内的判断是否成功,p指针都会向后移一个位置,判断不成功,ch中存的字符不变{printf("The file is null.\n");return 0;}while ('\n'!=fgetc(fp)){TopState=0;StackPoint=0;memset(StateStack,-1,sizeof(StateStack));printf("***********************语句%i 分析开始**************************\n",SentenceCount);scanner(fp);SLRControl(fp);NextSentence(fp);}//printf("第一个字母是:%c\n",ch);//fseek(p,-1,1);/*do{scanner(p);}while(ch=fgetc(p)!=EOF);*/fclose(fp);return 0;}五、测试用例和结果分析运行结果:结果分析:虽然能分开语句,但仍用“#”做结束标识符。

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

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

编译原理实验三语义分析实验报告◆学院:数学与计算机科学技术学院◆专业:计算机科学与技术◆班级:级计算机班◆小组组员:姓名:学号:姓名:学号:姓名:学号:姓名:学号:实验题目一、实验目的要求学生用与实验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) "ε" 表示空串。

(完整word版)语义分析实验报告(word文档良心出品)

(完整word版)语义分析实验报告(word文档良心出品)

软件学院实验卡和实验报告学号:xxxxxxxxxxx姓名:xxx年级专业班级:xxxxxxxxxxxxxxxxxxx xxx实验室组别:__ __ 实验日期:2xxx 年xx 月xxx 日附录1 程序功能1.1操作实例例如:对源程序begin a:=2+3*4;x:=(a+b)/c; end#进行判断;首先运行程序,程序出现提示:“请输入字符串,以#号结束:”,在光标处输入begin a:=2+3*4;x:=(a+b)/c; end#,回车,结果如图:程序给出了三地址码形式的四元式。

1.2 错误处理(1)如果用户在语句串开头处没有输入“begin ”,程序提示“缺少begin !”;如果用户没有输入“end ”,程序提示“end !错误”;(2)如果用户输入的语句串中缺少赋值符号(“:=”),程序提示“缺少赋值符号!”;(3)如果用户输入的语句串中“(”和“)”不匹配,程序提示“缺少“(”!”或“缺少“)!”。

2源程序#include<stdio.h>#include<string.h>#include <stdlib.h>char prog[80],token[8];char ch;int syn,p,m,n,sum;int kk=0,ii,N,nn=0;int k=0,t,i=0;char tt;char * keywords[6] = {"begin","if","then","while","do","end"}; //关键字表。

int scaner();int parser();int statement();int sentence();char *term();char *factor();char *expression();void emit(char *result,char *ag1,char *op,char *ag2);struct //四元式的结构。

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

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

编译原理实验报告语义分析实验名称:语义分析实验目的:1.掌握词法分析器生成的词法单元序列的构造;2.学会设计语法分析器,实现对程序的基本语法结构检查,并生成抽象语法树;3.学习语义规约的实现,实现对程序的语义分析和错误检查;4.熟悉语义分析向语法分析的接口。

实验原理:语义分析是编译过程的一个重要环节,它的主要任务是对生成的抽象语法树进行遍历,并验证程序的类型一致性、语义规则的正确性、错误的检查和恢复等。

语义分析的输入是由语法分析生成的抽象语法树,输出是继续优化的抽象语法树或中间代码,以供后续的中间代码生成等工作使用。

实验步骤:1.设计语法分析器,包括语法规则、优先级关系等;2.生成词法单元序列;3.构建语法分析器,进行语法分析,并生成抽象语法树;4.针对不同的语义规约,设计语义动作,实现对程序的语义分析和错误检查;5.完成语义分析器的构建和测试。

实验设备:1.计算机;2. 编程语言:C++/Java/Python等;3. 开发环境:Visual Studio/ Eclipse/PyCharm等。

实验结果:通过对语法分析生成的抽象语法树进行遍历,实现了对程序的语义分析和错误检查。

具体实现包括:1.类型检查:根据语义规约,对程序中的类型进行检查,包括变量的声明及使用、函数的调用、赋值语句的一致性等;2.作用域检查:检查变量的作用域和可见性等;3.错误检查:检测语义错误,如变量未声明、函数重复定义等;4.错误恢复:当检测到错误时,采取适当的错误恢复措施,如跳过错误的部分继续分析、提示错误信息等。

实验心得:本次实验主要学习了语义分析的原理和实现方法,深入了解了编译过程中各个环节的作用和关系。

通过实践操作,加深了对语法分析和语义分析的理解,提高了编程能力和解决问题的能力。

同时,实验过程中也遇到了一些挑战和困难,例如语义规约的设计和实现、错误检查和恢复等,但通过查阅资料和与同学讨论,最终解决了这些问题。

通过本次实验,我对编译原理和语义分析有了更深入的了解,并且对以后的学习和工作有了更好的准备。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验三语法分析20080810309 科3 李君林一.实验目的:通过使用、剖析和扩充TINY语言的语义分析程序,掌握编译器的语义分析程序的构造方法。

二.实验内容(一)运行TINY的语义分析程序(二)扩充TINY的语法分析程序提示:考虑作用域(如:函数)和数组时可能需要修改符号表。

三.实验步骤1.先读懂TINY语义程序(相关联的文件:MAIN.C ANALYZE.C ANALYZE.H)(1)buildSymtab(syntaxTree); //根据语法树建立符号表通过递归调用traverse(syntaxTree,insertNode,nullProc);进行static void insertNode( TreeNode * t),这样将遇到与ID有关的Node信息通过void st_insert( char * name, int lineno, int loc,int len )加入到hashTable[h]数据结构中。

(2)接着调用typeCheck(syntaxTree);进行类型检测通过递归调用traverse(syntaxTree,nullProc,checkNode);将语法树遍历,然后调用static void checkNode(TreeNode * t)对节点进行类型检测2.扩充TINY的语法分析程序本次实验我首先将源程序实现的功能改成符合C_MINUS的符号表与类型检测然后加入没申明调用与数组调用错误即数组没申明而调用数组类型。

四.实验结果1.正确的测试程序/**/int gcd (int u,int v[]){if(v==0)return u;elsereturn gcd(v,u);}void main(void){int x;int y;read x;x=y=2;while(x>0)y=y-1;write y;return (gcd(x,y));}/**/运行结果:经检验测试程序代码无语义错误2.错误测试程序/**/int gcd (int u,int v[]){if(v==0)return u;elsereturn gcd(v,u);}void main(void){int x;int y;read x;t=1;x=y=2;x[2]=2;while(x>0)y=y-1;write y;return (gcd(x,y));}/**/实验结果:检测到13行t没有申明检测到15行x不是一个数组五.实验心得通过本次实验学会了使用、剖析和扩充TINY语言的语义分析程序,掌握编译器的语义分析程序的构造方法。

加深了对书本语义分析的理解,感受到学以致用的快感,增强对本课程的兴趣。

实验中遇到的最大问题:如何查询符号表判断数组,后面在其数据结构中增加了一个属性Len,如果不是数组将其赋为-1.六.关键程序代码(ANALYZE.C)/****************************************************//* File: analyze.c *//* Semantic analyzer implementation *//* for the TINY compiler *//* Compiler Construction: Principles and Practice *//* Kenneth C. Louden *//****************************************************/#include "globals.h"#include "symtab.h"#include "analyze.h"/* counter for variable memory locations */static int location = 0;/* Procedure traverse is a generic recursive* syntax tree traversal routine:* it applies preProc in preorder and postProc* in postorder to tree pointed to by t*/static void traverse( TreeNode * t,void (* preProc) (TreeNode *),void (* postProc) (TreeNode *) ){ if (t != NULL){ preProc(t);{ int i;for (i=0; i < MAXCHILDREN; i++)traverse(t->child[i],preProc,postProc);}postProc(t);traverse(t->sibling,preProc,postProc);}}/* nullProc is a do-nothing procedure to* generate preorder-only or postorder-only* traversals from traverse*/static void nullProc(TreeNode * t){ if (t==NULL) return;else return;}static void typeError(TreeNode * t, char * message){ fprintf(listing,"Type error at line %d: %s\n",t->lineno,message);Error = TRUE;}static void unDecError(TreeNode * t){ fprintf(listing,"Type error at line %d: the %s doesn't declaration\n",t->lineno,t->); Error = TRUE;}static void notArrayError(TreeNode * t){ fprintf(listing,"Type error at line %d: the ID %s isn't a Array\n",t->lineno,t->); Error = TRUE;}/* Procedure insertNode inserts* identifiers stored in t into* the symbol table*/static void insertNode( TreeNode * t){ switch (t->nodekind){ case StmtK:switch (t->kind.stmt){default:break;}break;case ExpK:switch (t->kind.exp){ case IdK:if (st_lookup(t->) == -1){/* not yet in table, so treat as new definition */unDecError(t);//st_insert(t->,t->lineno,location++,0);}else{/* already in table, so ignore location,add line number of use only */// printf("LEN:%d\n",t->length);if(t->length!=-1&&st_isArray(t->)==-1)notArrayError(t);elsest_insert(t->,t->lineno,0,-1);}break;default:break;}break;case DecK:switch(t->kind.deck){case VarK:if (st_lookup(t->) == -1){/* not yet in table, so treat as new definition */if(t->length==-1){st_insert(t->,t->lineno,location++,-1);}else{st_insert(t->,t->lineno,location++,t->length);}if(t->length!=-1)location+=t->length-1;}else{/* already in table, so ignore location,add line number of use only */st_insert(t->,t->lineno,0,-1);}case ParaK:if (st_lookup(t->) == -1){/* not yet in table, so treat as new definition */if(t->length==-1){st_insert(t->,t->lineno,location++,-1);}else{st_insert(t->,t->lineno,location++,t->length);}}else/* already in table, so ignore location,add line number of use only */st_insert(t->,t->lineno,0,-1);break;case FunK:if (st_lookup(t->) == -1)/* not yet in table, so treat as new definition */st_insert(t->,t->lineno,location++,-1);/* already in table, so ignore location,add line number of use only */st_insert(t->,t->lineno,0,-1);break;default:break;}break;default:break;}}/* Function buildSymtab constructs the symbol* table by preorder traversal of the syntax tree*/void buildSymtab(TreeNode * syntaxTree){fprintf(listing,"\nunDecError and arrayCallError check\n");traverse(syntaxTree,insertNode,nullProc);fprintf(listing,"\nunDecError and arrayCallError check finished\n");if (TraceAnalyze){if (TraceAnalyze) fprintf(listing,"\nBuilding Symbol Table...\n");printSymTab(listing);}}/* Procedure checkNode performs* type checking at a single tree node*/static void checkNode(TreeNode * t){switch (t->nodekind){ case ExpK:switch (t->kind.exp){ case OpK:if ((t->child[0]->type != Integer) ||(t->child[1]->type != Integer))typeError(t,"Op applied to non-integer");if ((t->attr.op == EQ) || (t->attr.op == LT) || (t->attr.op == BG)|| (t->attr.op == LE) || (t->attr.op == BG) || (t->attr.op == UNEQ))t->type = Boolean;elset->type = Integer;break;case ConstK:case IdK:t->type = Integer;break;default:break;}break;case StmtK:switch (t->kind.stmt)if (t->child[0]->type == Integer)typeError(t->child[0],"if test is not Boolean");break;case IteK:if (t->child[0]->type == Integer)typeError(t->child[0],"while test is not Boolean");break;case WriteK:if (t->child[0]->type != Integer)typeError(t->child[0],"write of non-integer value");break;default:break;}break;default:break;}}/* Procedure typeCheck performs type checking* by a postorder syntax tree traversal*/void typeCheck(TreeNode * syntaxTree){traverse(syntaxTree,nullProc,checkNode);}。

相关文档
最新文档