语义分析实验报告.doc
软件学院实验卡和实验报告 学号: xxxxxxxxxxx 姓名: xxx 年级专业班级:xxxxxxxxxxxxxxxxxxx xxx 实验室 组别:_ _ 实验日期: 2xxx 年 xx 月 xxx 日课程名称编译原理实验课时4实验名称和序号语义分析4同组者 姓 名实验目的通过上机实验,加深对语法制导翻译的理解,掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法。实验环境(1)软件环境:Microsoft Visual Studio 6.0;(2)硬件环境:Windows 2000操作系统。实验内容和原理对给定的程序通过语义分析器能够判断语句串是否正确。正确则输出三地址指令形式的四元式代码,错误则抛出错误信息。实验步骤方 法关键代码(1)输入待分析的字符串。语法如下:a.关键字:begin,if,then,while,do,end.b.运算符和界符::= + - * / < <= > >= <> = ; ( ) #c.其他单词是标识符(ID)和整形常数(NUM):ID=letter(letter|digit)*,NUM=digitdigit*d.空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM、运算符、界符和关键字,词法分析阶段通常被忽略。(2)扫描字符串,采用递归向下进行分析。主要函数如下:a.scaner()/词法分析函数,char token8用来存放构成单词符号的字符串;b.parser()/语法分析,在语法分析的基础上插入相应的语义动作:将输入串翻译成四元式序列。只对表达式、赋值语句进行翻译。c.emit(char *result,char *arg1,char *op,char *ag2)/该函数功能是生成一个三地址语句返回四元式表中。d.char *newtemp()/该函数返回一个新的临时变量名,临时变量名产生的顺序为T1,T2,。( (接上页)实验步骤方 法关键代码四元式表的结构如下:struct char result8;char ag18;char op8;char ag28;quad20;(3)输出为三地址指令形式的四元式序列。例如:语句串begin a:=2+3*4;x:=(a+b)/c;end#,输出的三地址指令如下:t1=3*4t2=2+t1a=t2t3=a+bt4=t3/cx=t4测试记录分 析结 论对于正确的语句串,例如: begin a:=2+3*4;x:=(a+b)/c; end#,运行结果如图:对于缺少赋值符号、“end”、“begin”、“(”、“)”等均可做出错误判断并给出相应提示。小 结实现了输出为三地址指令形式的四元式序列。通过上机实验,加深了对语法制导翻译原理的理解,掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法。加深了对C+语言的用途的理解。以下由实验教师填写记 事评 议 成绩评定 平时成绩_ 实验报告成绩_ 综合成绩 _ 指导教师签名:附录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 prog80,token8;char ch;int syn,p,m,n,sum;int kk=0,ii,N,nn=0;int k=0,t,i=0;char tt;char * keywords6 = "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 /四元式的结构。char resulted8;char ag1ed8;char oped8;char ag2ed8;quad20;void main() p=0;printf("请输入字符串,以#号结束: n");doscanf("%c",&ch);progp+=ch;while(ch != '#'); /没有遇到结束符,则首先调用scaner()进行词法分析,之后进行语义分析。p=0;scaner();parser();char * newtemp(void) /返回一个新的临时变量名,临时变量名产生的顺序为t1,t2,。char * P;char M8;P = (char *)malloc(8);k+;itoa(k,M,10);strcpy(P+1,M);P0 = 't'return(P);int parser() /在语法分析的基础上插入相应的语义动作:将输入串翻译成四元式序列。只对表达式、赋值语句进行翻译。int schain = 0;kk = 0;if(syn = 1)scaner();schain = sentence(); /调用语句串分析函数进行分析。if(syn = 6) /“end”。scaner();if(syn = 0 && (kk = 0)printf("success");else if(kk!=1)printf("缺end错误"); / 输出“end”错误。kk=1;elseprintf("begin错误"); /输出“begin”错误。kk=1; return(schain);int sentence() /语句串分析函数。int schain = 0;schain = statement(); /调用语句分析函数进行分析。while (syn = 26) /“;”。scaner();schain = statement(); /调用语句分析函数进行分析。return(schain);int statement() /语句分析函数。char tt8,eplace8;int schain = 0;switch(syn)case 10:strcpy(tt,token);scaner();if(syn = 18) /赋值语句。scaner();strcpy(eplace,expression();emit(tt,eplace,"","");schain = 0;elseprintf("缺少赋值号"); /缺少“:=”错误。kk=1;return(schain);break;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分析产生表达式计算的第一项eplace。while(syn = 13 | syn = 14) /加减。strcpy(tt,token);scaner();strcpy(ep2,term(); /调用term()分析产生表达式计算的第二项ep2。strcpy(tp,newtemp(); /调用newtemp()产生临时变量tp存储计算结果。emit(tp,eplace,tt,ep2); /生成四元式送入四元式表。strcpy(eplace,tp);return(eplace);char * term(void)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 = 15 | syn = 16) /乘除。strcpy(tt,token);scaner();strcpy(ep2,factor();strcpy(tp,newtemp();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);scaner();else if (syn = 11) /数字。itoa(sum,fplace,10);scaner();else if(syn = 27) /“(”。scaner();strcpy(fplace,expression();if(syn = 28) /有“)”。scaner();elseprintf("')'错误"); /只有“(”,缺少“)”。kk=1;elseprintf("'('错误");kk=1;return(fplace);void emit(char * result,char * ag1,char * op,char * ag2) /生成一个三地址码并返回到四元式代码中。strcpy(quadnn.resulted,result);strcpy(quadnn.ag1ed,ag1);strcpy(quadnn.oped,op);strcpy(quadnn.ag2ed,ag2);printf("(%d) %s=%s%s%sn", nn+1,quadnn.resulted,quadnn.ag1ed,quadnn.oped,quadnn.ag2ed);nn+;scaner() /此函数为词法分析。 for(n=0;n<8;n+) tokenn=NULL; ch=progp+; m=0; while(ch=' ') ch=progp+ ; if(ch>='a') && (ch<='z') /判断是否是字母。 while(ch>='a') && (ch<='z') | (ch>='0') && (ch<='9') /判断下一个是否是字母或数字。 tokenm+=ch; ch=progp+; tokenm+='0' p-; syn=10; for(n=0;n<6;n+) if(strcmp(token,keywordsn)=0) /判断是否匹配关键字。 syn=n+1; break; else if(ch>='0' && ch<='9') /判断数字。 sum=0; while(ch>='0')&&(ch<='9') /判断下一个是否是数字。sum=sum*10+(int)ch-'0' ch=progp+; p-; syn=11; else switch(ch) case'<': /是否是“<”。 m=0; tokenm+=ch; if(ch='>') /是否是“>”。 syn=21; tokenm+=ch; else if(ch='=') /判断下一个是否是“=”,即为判断符号“<=”。 syn=22; tokenm+=ch; else syn=20; ch=progp+; break; case'>': /是否是“>”。 m=0; tokenm+=ch; ch=progp+; if(ch='=') /判断下一个是否是“=”,即为判断符号“>=”。 syn=24; tokenm+=ch; else syn=23; p-; break; break; case':': /是否是“:”。 m=0; tokenm+=ch; ch=progp+; if(ch='=') /判断下一个是否是“=”,即为判断符号“:=”。 syn=18; tokenm+=ch; else syn=17; p-; break; case'+':syn=13;token0=ch; break; /判断符号“+”。 case'-':syn=14;token0=ch; break; /判断符号“-”。 case'*':syn=15;token0=ch; break; /判断符号“*”。 case'/':syn=16;token0=ch; break; /判断符号“=”。 case'=':syn=25;token0=ch; break; /判断符号“;”。 case'':syn=26;token0=ch; break; /判断符号“+”。 case'(':syn=27;token0=ch; break; /判断符号“(”。 case')':syn=28;token0=ch; break; /判断符号“)”。 case'#':syn=0;token0=ch; break; /判断符号“#”。 default:syn=-1;return syn;