编译原理实验报告三.docx

上传人:b****8 文档编号:9187256 上传时间:2023-02-03 格式:DOCX 页数:29 大小:156.37KB
下载 相关 举报
编译原理实验报告三.docx_第1页
第1页 / 共29页
编译原理实验报告三.docx_第2页
第2页 / 共29页
编译原理实验报告三.docx_第3页
第3页 / 共29页
编译原理实验报告三.docx_第4页
第4页 / 共29页
编译原理实验报告三.docx_第5页
第5页 / 共29页
点击查看更多>>
下载资源
资源描述

编译原理实验报告三.docx

《编译原理实验报告三.docx》由会员分享,可在线阅读,更多相关《编译原理实验报告三.docx(29页珍藏版)》请在冰豆网上搜索。

编译原理实验报告三.docx

编译原理实验报告三

实验三语义分析程序实现

一、实验目的与要求

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

二、一般实现方法

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

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

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

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

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

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

三、实验内容

基本实验题目:

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

输入:

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

输出:

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

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

五、源程序

#include

#include

#include

#include

#include

#defineUNKNOWN-1

#defineLB0

#defineRB1

#definePL2

#defineMI3

#defineMU4

#defineDI5

#defineUCON6//Supposetheclassnumberofunsignedconstantis7

#defineOVER

#defineLT8

#defineLE9

#defineEQ10

#defineNE11

#defineGT12

#defineGE13

#defineIS19//14至18被五个关键字占用

#defineID20

#defineMAX_KEY_NUMBER20/*关键字的数量*/

#defineKEY_WORD_END"waitingforyourexpanding"/*关键字结束标记*/

char*KeyWordTable[MAX_KEY_NUMBER]={"begin","end","if","then","else",KEY_WORD_END};

charTOKEN[20]="";//存储已扫描的单词

charch='';//用于存储带判断的字符

introw=1;

////////////////////////无符号数部分

#defineDIGIT1

#definePOINT2

#defineOTHER3

#definePOWER4

#definePLUS5

#defineMINUS6

#defineClassOther200

#defineEndState-1

intindex=0;

intw,n,p,e,d;

intClass;//Usedtoindicateclassoftheword

intICON;

floatFCON;

staticintCurrentState;//Usedtopresentcurrentstate,theinitialvalue:

0

////////////////////////语法分析部分

////////////////////////产生式

//1、E->E+T2、E->E-T3、E->T4、T->T*F5、T->T/F6、T->F7、F->(E)8、F->i

#defineSMAX256

///////////////////////goto表的列项

#defineE0

#defineT1

#defineF2

intStateStack[SMAX];//状态栈

intStackPoint;//状态栈指针

intTopState;//作为状态栈盏栈顶指针

intInputWordType;//输入的单词类型

////////////////()+-*/i#

charAction[16][8][4]={"s4","","","","","","s5","",

"","","s6","s7","","","","A",

"","r3","r3","r3","s8","s9","","r3",

"","r6","r6","r6","r6","r6","","r6",

"s4","","","","","","s5","",

"","r8","r8","r8","r8","r8","","r8",

"s4","","","","","","s5","",

"s4","","","","","","s5","",

"s4","","","","","","s5","",

"s4","","","","","","s5","",

"","s15","s6","s7","","","","",

"","r1","r1","r1","s8","s9","","r1",

"","r2","r2","r2","s8","s9","","r2",

"","r4","r4","r4","r4","r4","","r4",

"","r5","r5","r5","r5","r5","","r5",

"","r7","r7","r7","r7","r7","","r7",};//action表

//ETF

intGoto[16][3]={{1,2,3},

{-1,-1,-1},

{-1,-1,-1},

{-1,-1,-1},

{10,2,3},

{-1,-1,-1},

{-1,11,3},

{-1,12,3},

{-1,-1,13},

{-1,-1,14},

{-1,-1,-1},

{-1,-1,-1},

{-1,-1,-1},

{-1,-1,-1},

{-1,-1,-1},

{-1,-1,-1},};//goto表

////////////////////////语义分析部分

#definePMAX5//define后面不加括号,定义产生式符号属性字符串的长度

intNXQ=0;/*全局变量NXQ用于指示所要产生的下一个四元式的编号*/

intNXTemp=1;//整型变量NXTemp指示临时变量的编号

intSentenceCount=1;//存放文件中句子的个数

structQUATERNION/*四元式表的结构*/

{

charop[PMAX];/*操作符*/

chararg1[PMAX];/*第一个操作数*/

chararg2[PMAX];/*第二个操作数*/

charresult[PMAX];/*运算结果*/

}pQuad[256];/*存放四元式的数组*/

charEBracket_Place[PMAX];//(E)的语义属性

chari_Place[PMAX];

charE_Place[PMAX];

charT_Place[PMAX];

charF_Place[PMAX];

intEXCUTE(intstate,intsymbol,FILE*fp,charJudgeStr[],introw,intindex);

intGetChar(charch);

intHandleError(charStrJudge[],introw);

intPush(intState);

intPop(intcount);

intSLRControl(FILE*fp);

voidGEN(char*Op,char*Arg1,char*Arg2,char*Result);

char*NewTemp(void);

voidNextSentence(FILE*fp);//当语法或者词法产生错误的时候,跳过当前错误的句子,将文件指针指向下一个句子的开始

////////////////////////查保留字表,判断是否为关键字

intlookup(char*token)

{

intn=0;

while(strcmp(KeyWordTable[n],KEY_WORD_END))//strcmp比较两串是否相同,若相同返回0

{

if(!

strcmp(KeyWordTable[n],token))//比较token所指向的关键字和保留字表中哪个关键字相符

{

returnn+1;//根据单词分类码表I,设置正确的关键字类别码,并返回此类别码的值

break;

}

n++;

}

return6;//单词不是关键字,而是标识符

}

////////////////////////输出分析结果

voidout(inti,char*pStr)

{

charMnemonic[5];

if(0==i)

{

strcpy(Mnemonic,"LB");

}

elseif(1==i)

{

strcpy(Mnemonic,"RB");

}

elseif(2==i)

{

strcpy(Mnemonic,"PL");

}

elseif(3==i)

{

strcpy(Mnemonic,"MI");

}

elseif(4==i)

{

strcpy(Mnemonic,"MU");

}

elseif(5==i)

{

strcpy(Mnemonic,"DI");

}

elseif(6==i)

{

strcpy(Mnemonic,"UCON");

}

elseif(7==i)

{

strcpy(Mnemonic,"OVER");

}

elseif(8==i)

{

strcpy(Mnemonic,"LT");

}

elseif(9==i)

{

strcpy(Mnemonic,"LE");

}

elseif(10==i)

{

strcpy(Mnemonic,"EQ");

}

elseif(11==i)

{

strcpy(Mnemonic,"NE");

}

elseif(12==i)

{

strcpy(Mnemonic,"GT");

}

elseif(13==i)

{

strcpy(Mnemonic,"GE");

}

elseif(14==i)

{

strcpy(Mnemonic,"BEGIN");

}

elseif(15==i)

{

strcpy(Mnemonic,"END");

}

elseif(16==i)

{

strcpy(Mnemonic,"IF");

}

elseif(17==i)

{

strcpy(Mnemonic,"THEN");

}

elseif(18==i)

{

strcpy(Mnemonic,"ELSE");

}

elseif(19==i)

{

strcpy(Mnemonic,"IS");

}

elseif(20==i)

{

strcpy(Mnemonic,"ID");

}

else

{

strcpy(Mnemonic,"UnkownType");

}

printf("(%s)对应%s\n",Mnemonic,pStr);

}

////////////////////////报错部分

voidreport_error(introw)

{

printf("%s无法识别的单词!

Inthe%drow\n",TOKEN,row);

}

////////////////////////扫描程序部分

voidscanner(FILE*fp)

{

inti,c;

fseek(fp,-1,1);//首先回溯一个字符,就是将文件所有的字符都在scanner内部判断,外部while循环不会浪费任何字符

ch=fgetc(fp);//scanner中要想判断字符,必须开头先读一个字符

while(''==ch||'\n'==ch||'\t'==ch)//消耗文件中空字符串

{

if('\n'==ch)

{

row++;

}

ch=fgetc(fp);

}

if(EOF==ch)

{

return;

}

if(isalpha(ch))/*itmustbeaidentifer!

*/

{

TOKEN[0]=ch;ch=fgetc(fp);i=1;

while(isalnum(ch))

{

TOKEN[i]=ch;i++;

ch=fgetc(fp);

}

TOKEN[i]='\0';

fseek(fp,-1,1);/*retract*/

c=lookup(TOKEN);

if(c!

=6)out(c+13,TOKEN);elseout(c+14,TOKEN);//此处加13或者14因为一些常量的定义产生冲突,被迫修改以适应

}

elseif(isdigit(ch)||'.'==ch)

{

fseek(fp,-1,1);//回溯一个字符,为下面循环内部使用先读字符后判断的格式。

intType;

CurrentState=0;

i=0;

do

{

ch=fgetc(fp);

TOKEN[i]=ch;

i++;

TOKEN[i]='\0';

Type=GetChar(ch);

EXCUTE(CurrentState,Type,fp,TOKEN,row,i);

}while(CurrentState!

=EndState);

}else

switch(ch)

{

case'<':

ch=fgetc(fp);

if(ch=='=')out(LE,"<=");

elseif(ch=='>')out(NE,"<>");

else

{

out(LT,"<");

}

break;

case'=':

{

ch=fgetc(fp);

if('='==ch)

{

out(EQ,"==");

}

else

{

out(IS,"=");

}

}

break;

case'>':

ch=fgetc(fp);

if(ch=='=')out(GE,">=");

else

{

out(GT,">");

}

break;

case'+':

{

InputWordType=PL;

out(PL,"+");

}

break;

case'-':

{

InputWordType=MI;

out(MI,"-");

}

break;

case'*':

{

InputWordType=MU;

out(MU,"*");

}

break;

case'/':

{

InputWordType=DI;

out(DI,"/");

}

break;

case'(':

{

InputWordType=LB;

out(LB,"(");

}

break;

case')':

{

InputWordType=RB;

out(RB,")");

}

break;

case'#':

{

InputWordType=OVER;

out(OVER,"#");

}

break;

default:

{

InputWordType=UNKNOWN;

report_error(row);

}break;

}

return;

}

/////////////////////////无符号数判断矩阵执行程序

intEXCUTE(intstate,intsymbol,FILE*fp,charJudgeStr[],introw,intindex)//row用于指示出错的行数,index用于为待输出的字符串赋结束符‘\0’时用

{

switch(state)

{

case0:

switch(symbol)

{

caseDIGIT:

n=0;p=0;e=1;w=d;CurrentState=1;Class=UCON;break;

casePOINT:

w=0;n=0;p=0;e=1;CurrentState=3;Class=UCON;break;

default:

{

Class=ClassOther;

CurrentState=EndState;

InputWordType=UNKNOWN;

printf("无符号数的第一个字符是非法的!

\n");

}

}

break;

case1:

switch(symbol)

{

caseDIGIT:

w=w*10+d;break;//CurrentState=1

casePOINT:

CurrentState=2;break;

casePOWER:

CurrentState=4;break;

default:

{

if(ch!

=EOF)//如果是因为读到文件结束字符而终止识别(是正确识别一个无符号数结束),就不应该回退,否则可能造成死循环

{

fseek(fp,-1,1);//遇到其他的字符,可能是一条语句中的其他字符,需后退,因为主函数外层循环每次都要读一个字符进行判断,而这个判读不回溯,所以在内部把这个多读的字符回溯

}

ICON=w;CurrentState=EndState;

JudgeStr[index-1]='\0';

InputWordType=UCON;

printf("(UCON,%i)对应%s\n",ICON,JudgeStr);

}break;

}

break;

case2:

switch(symbol)

{

caseDIGIT:

n++;w=w*10+d;break;

casePOWER:

CurrentState=4;break;

default:

{

if(ch!

=EOF)

{

fseek(fp,-1,1);

}

FCON=w*pow(10,e*p-n);CurrentState=EndState;

JudgeStr[index-1]='\0';

InputWordType=UCON;

printf("(UCON,%f)对应于%s\n",FCON,JudgeStr);

}

}

break;

case3:

switch(symbol)

{

caseDIGIT:

n++;w=w*10+d;CurrentState=2;break;

default:

{

InputWordType=UNKNOWN;

HandleError(JudgeStr,row);CurrentState=EndState;

}

}

break;

case4:

switch(symbol)

{

caseDIGIT:

p=p*10+d;CurrentState=6;break;

caseMINUS:

e=-1;CurrentState=5;break;

casePLUS:

CurrentState=5;break;

default:

{

InputWordType=UNKNOWN;

HandleError(JudgeStr,row);CurrentState=EndState;

}

}

break;

case5:

switch(symbol)

{

caseDIGIT:

p=p*10+d;CurrentState=6;break;

default:

{

InputWordType=UNKNOWN;//判断一个无符号数的最后一个字符应该都是多余读取的,所以为了防止引起后面再次判断下一无符号数时产生呑字符的现象,都应该回溯一个字符

HandleError(JudgeS

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 政史地

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1