天津理工大学编译原理实验一.docx
《天津理工大学编译原理实验一.docx》由会员分享,可在线阅读,更多相关《天津理工大学编译原理实验一.docx(33页珍藏版)》请在冰豆网上搜索。
天津理工大学编译原理实验一
实验报告
学院(系)名称:
计算机与通信工程学院
姓名
学号
专业
计算机科学与技术
班级
实验项目
实验一:
词法分析
课程名称
编译原理
课程代码
实验时间
2016/03/17
2016/03/22
实验地点
软件实验室7-219
批改意见
成绩
教师签字:
实验内容:
实现标准C语言词法分析器。
实验要求:
(1)单词种别编码要求
基本字、运算符、界符:
一符一种
标识符:
统一为一种;
常量:
按类型编码;
(2)词法分析工作过程中建立符号表、常量表。
并以文本文件形式输出。
(3)词法分析的最后结果以文本文件形式输出。
实验源代码和心得体会
#include
#include
#include
#definebufsize1024
//关键字
#defineINCLUDE256
#defineAUTO257
#defineBREAK258
#defineCASE259
#defineCHAR260
#defineCONST261
#defineCONTINUE262
#defineDEFAULT263
#defineDO264
#defineDOUBLE265
#defineELSE266
#defineENUM267
#defineEXTERN268
#defineFLOAT269
#defineFOR270
#defineGOTO271
#defineIF272
#defineINT273
#defineLONG274
#defineREGISTER275
#defineRETURN276
#defineSHORT277
#defineSIGNED278
#defineSIZEOF279
#defineSTATIC280
#defineSTRUCT281
#defineSWITCH282
#defineTYPEDEF283
#defineUNION284
#defineUNSIGNED285
#defineVOLATILE286
#defineWHILE287
//运算符
#definePLUS288//+
#defineMINUS289//-
#defineMUL290//*
#defineDIV291///
#defineREMAIN292//%
#defineGREATER293//>
#defineLESS294//<
#defineEQUAL295//=
#defineMISTAKE296//!
#defineAND297//&
#defineOR298//|
#definePP299//++
#defineMM300//--
#defineEE301//==
#defineGE302//>=
#defineLE303//<=
#defineMISE304//!
=
#defineAA305//&&
#defineOO306//||
#definePE307//+=
#defineMINUSE308//-=
#defineMULE309//*=
#defineDIVE310///=
#definePOW311//^
//界符
#defineSEMIC312//;
#defineCOMMA313//,
#defineMULANNO_L314///*
#defineMULANNO_R315//*/
#defineBRACE_L316//{
#defineBRACE_R317//}
#defineBRAKET_L318//(
#defineBRAKET_R319//)
#defineMIDBRA_L320//[
#defineMIDBRA_R321//]
#defineONE_ANNO322////
//标识符和常量符
#defineTAG400
#defineCONINT401
#defineCONFLOAT402
#defineCONCHAR403
#defineCONSTRING404
//转义字符和字符串
#defineCA500
#defineCB501
#defineCF502
#defineCN503
#defineCR504
#defineCT505
#defineCV506
#defineCBSL507
#defineCQUE508
#defineCDQM509
#defineCQM510
#defineZERO511
usingnamespacestd;
typedefstructVariate{//变量标识符
intid;
charname[50];
}Variate;
typedefstructConstant{//常量
intid;
charname[50];
}Constant;
typedefstructSign{
charname[100];
intsym;
charattr[100];
}Sign;
constchar*keywordTable[]={"include","auto","break","case","char","const","continue",
"default","do","double","else","enum","extern","float","for",
"goto","if","int","long","register","return","short","signed",
"sizeof","static","struct","switch","typedef","union","unsigned",
"volatile","while","","##"};//##作用是判断是否结束
constchar*operateTable[]={"+","-","*","/","%",">","<","=","!
","&","|","++","--",
"==",">=","<=","!
=","&&","||","+=","-=","*=","/=","^","##"};
constchar*borderTable[]={";",",","/*","*/","{","}","(",")","[","]","//","##"};
constcharchangeList[12]={'a','b','f','n','r','t','v','\\','?
','"','\'','0'};
FILE*in;
FILE*Out;
FILE*Error;
intline=1;//用于输出错误的行数或者其他情况。
默认值是从1开始,为第一行
charbuf[bufsize];//存储读取的一行的字符串
charfirchar;//头文件下第一个字符
charChar;
intstart=0;
intVariateNum=0;//记录变量的个数,减去1
intConstantNum=0;//记录常量的个数
intSignNum=0;//记录标记的个数
intnotation=1;//记录是否找到多行注释的另一半*/,默认值是1即为有另一半
intisNotation=0;//判断是否是在注释行内0不是,1单行注释2多行注释
boollast=false;
intlate=0;
Variatevar;
Constantcon;
Signsign;
VariateVarArr[bufsize];
ConstantConArr[bufsize];
SignSigArr[bufsize];
//获取读取的文件本行的第一个字符,直到找到一个非空格字符
chargetfirstc(FILE*in)
{
charch=fgetc(in);//fgetc()函数的作用是读取文件的当前行的一个字符,返回读取的字符
while(ch==''||ch=='\n'||ch=='\t')
{
if(ch=='\n')
{
line++;
fputc('\n',Out);//向输出的文本文件中打印换行
}
ch=fgetc(in);
}
returnch;
}
//处理读取的本行内容
voiddealhead(char*buf)
{
charch[10];
charcha;
charstr[bufsize];
inti=0;
intj=0;
inttemp=0;
while(i{
if(buf[i]!
=''&&buf[i]!
='\0')
{
if(temp==0)
{
if(buf[i]=='i')
temp=1;
elseif(buf[i]=='d')
temp=2;
else
{
fprintf(Error,"Line:
%d\tformatiswrong!
Without'>'\n",line);
break;
}
}
if(temp==1)
{
ch[j]=buf[i];
j++;
if(buf[i]=='<')
{
ch[j]='\0';
break;
}
}
elseif(temp==2)
{
ch[j]=buf[i];
j++;
if(buf[i+1]=='')
{
ch[j]='\0';
i++;
break;
}
}
}
i++;
}
if(temp==1)
{
intindex=0;
fputc('#',Out);
while(buf[index]!
='\0')
{
if(buf[index]!
='')
fputc(buf[index],Out);
index++;
}
if(strcmp(ch,"include<")==0)
{
i++;//因为上面程序没进行++就直接break所以这里就需要加1到下一个角标
while((cha=buf[i])!
='>')
{
i++;
if(cha=='\n')
{
fprintf(Error,"Line:
%d\tincludeendwithout'>'\n",line);
break;
}
}
}
else
fprintf(Error,"Line:
%d\tincludeformatiswrong\n",line);
}
elseif(temp==2)
{
if(strcmp(ch,"define")!
=0)
{
i++;
while((cha=buf[i])=='')
{
if(cha=='\n')
{
//fprintf(Error,"Line:
%d\tincludeendwithout'>'\n",line);
break;
}
i++;
}
if(buf[i]!
='')
{
if(!
(isalpha(buf[i])))
fprintf(Error,"Line:
%d\tdefineformatiswrong\n",line);
//此处意思是define后必须有变量名称
}
}
else
{
//在上面的break之前已经进行过i++;所以这里可以直接用
while(!
isalpha(buf[i]))
{
if(buf[i]=='\0')
{
fprintf(Error,"Line:
%d\tdefinewithoutvatiateandname!
\n",line);
break;
}
i++;
}
intindex=0;
intspace=0;//计算在上一个字母之后第几次遇到空格
fputc('#',Out);
while(buf[index]!
='\0')
{
if(buf[index]!
='')
{
fputc(buf[index],Out);
space=0;
}
else
{
space++;
if(space==1&&index!
=0)
fputc('',Out);
}
index++;
}
}
}
}
//处理头文件
charhead(FILE*in)
{
charch;
if(late==0)
ch=getfirstc(in);
else
ch=firchar;//即为#
while(ch=='#')
{
fgets(buf,bufsize,in);//fgets()读取in文件当前一行的内容为bufsize-1个字符的内容
intlen=strlen(buf);
buf[len-1]='\0';
dealhead(buf);//这条语句执行完毕后且找到'>'就说明这行结束
line++;
ch=getfirstc(in);
if(ch=='#')
fputc('\n',Out);
}
returnch;
}
//判断关键字
intkeyword(char*str)
{
inti;
for(i=0;keywordTable[i]!
="##";i++)
if(strcmp(str,keywordTable[i])==0)
returni+256;//返回关键字对应的值
return-1;
}
//处理字母
voiddealAlpha()
{
charstr[50];
Variatevar;
Signsign;
inti;
intkey;//记录字符串str对应的值。
str[0]=firchar;
for(i=start;isalpha(buf[i])||isdigit(buf[i]);i++)
str[i-start+1]=buf[i];//将本行的第一个字符串赋值给str
str[i-start+1]='\0';
start=i;
firchar=buf[start];
key=keyword(str);
if(key==-1)
{//说明不是关键字,是标识符。
即为变量,函数名一类的
var.id=VariateNum;
strcpy(var.name,str);
VarArr[VariateNum]=var;
VariateNum++;
sign.sym=TAG;
sprintf(sign.attr,"%d",var.id);//暂时不知道什么用处
strcpy(sign.name,str);
SigArr[SignNum]=sign;
SignNum++;
}
else//说明是关键字
{
sign.sym=key;
strcpy(sign.name,str);
strcpy(sign.attr,"--");//sign.attr="--";是不正确的,attr的长度大,后面的不能忽略
SigArr[SignNum]=sign;
SignNum++;
}
}
//判断是否在常量表里
intInConTable(char*name)
{
inti;
for(i=0;iif(strcmp(name,ConArr[i].name)==0)
returnConArr[i].id;
return-1;
}
//处理数字
voiddealDigit()
{
intsymbol;
intid;
charword[100];
Signsign;
Constantconstant;
inti;
word[0]=firchar;
for(i=start;isdigit(buf[i]);i++)
{
word[i-start+1]=buf[i];
}
if(buf[i]=='.')
{
i++;
if(!
isdigit(buf[i]))
{
start=i;
firchar=buf[start];
fprintf(Error,"Line:
%d\tunavailabefloat\n",line);
return;
}
word[i-start]='.';
for(;isdigit(buf[i]);i++)
word[i-start+1]=buf[i];
word[i-start+1]='\0';
start=i;
firchar=buf[start];
id=InConTable(word);
/**不在常量表里,新加项**/
if(id==-1)
{
constant.id=ConstantNum;
strcpy(constant.name,word);
ConArr[ConstantNum]=constant;
ConstantNum++;
id=constant.id;
}
sign.sym=CONFLOAT;
sprintf(sign.attr,"%d",id);//changeinttostring
strcpy(sign.name,word);
SigArr[SignNum]=sign;
SignNum++;
}
else
{
word[i-start+1]='\0';
start=i;
firchar=buf[start];
id=InConTable(word);
/**不在常量表里,新加项**/
if(id==-1)
{
constant.id=ConstantNum;
strcpy(constant.name,word);
ConArr[ConstantNum]=constant;
ConstantNum++;
id=constant.id;
}
sign.sym=CONINT;
sprintf(sign.attr,"%d",id);//changeinttostring
strcpy(sign.name,word);
SigArr[SignNum]=sign;
SignNum++;
}
}
//处理注释
voiddealNotation()
{
charstr[3];
str[0]='/';
str[2]='\0';
if(buf[start]=='/')//确定是单行注释。
{
isNotation=1;
Signsign;
str[1]='/';
inti;
for(i=0;borderTable[i]!
="##";i++)
if(strcmp(str,borderTable[i])==0)
{
sign.sym=i+288;
break;
}
strcpy(sign.name,str);
strcpy(sign.attr,"--");
SigArr[SignNum]=sign;
SignNum++;
}
else//多行注释
{
isNotation=2;
str[1]='*';
Signsign1,sign2;
inti;
intst;
for(i=0;borderTable[i]!
="##";i++)
if(strcmp(str,borderTable[i])==0)
{
sign1.sym=i+312;
break;
}
strcpy(sign1.name,str);
strcpy(sign1.attr,"--");
SigArr[SignNum]=sign1;
SignNum++;
fputc('\n',Out);
if(Char!
='/')
fputc(Char,Out);
intlen;
len=strlen(buf);
charc=Char;
for(start=0;start{
if(c=='/'&&buf[start]=='*')
{
fputc('/',Out);
fputc('*',Out);
break;
}
else
{
fputc(buf[start],Out);
c=buf[start];
}
}
start++;