最新天津理工大学编译原理实验一.docx
《最新天津理工大学编译原理实验一.docx》由会员分享,可在线阅读,更多相关《最新天津理工大学编译原理实验一.docx(34页珍藏版)》请在冰点文库上搜索。
最新天津理工大学编译原理实验一
人和*大专实验报告
学院(系)名称:
计算机与通信工程学院
姓名
学号
专业
计算机科学与技术
班级
实验项目
实验一:
词法分析
课程名称
编译原理
课程代码
实验时间
2016/03/17
2016/03/22
实验地点
软件实验室7-219
批改意见
成绩
教师签字:
实验内容:
实现标准C语言词法分析器。
实验要求:
(1)单词种别编码要求
基本字、运算符、界符:
一符一种
标识符:
统一为一种;常量:
按类型编码;
(2)词法分析工作过程中建立符号表、常量表。
并以文本文件形式输出。
(3)词法分析的最后结果以文本文件形式输出。
实验源代码和心得体会
#include
#include#include
#definebufsize1024//关键字
#defineINCLUDE
256
#defineAUTO
257
#defineBREAK
258
#defineCASE
259
#defineCHAR
260
#defineCONST
261
#defineCONTINUE
262
#defineDEFAULT
263
#defineDO
264
#defineDOUBLE
265
#defineELSE
266
#defineENUM
267
#defineEXTERN
268
#defineFLOAT
269
#defineFOR
270
#defineGOTO
271
#defineIF272
#defineINT
273
#defineLONG
274
#defineREGISTER
275
#defineRETURN
276
#defineSHORT
277
#defineSIGNED
278
#defineSIZEOF
279
#defineSTATIC
280
#defineSTRUCT
281
#defineSWITCH
282
#defineTYPEDEF
283
#defineUNION
284
#defineUNSIGNED
285
#defineVOLATILE
286
#defineWHILE
287
//运算符
#definePLUS
288
//
+
#defineMINUS
289
//
-
#defineMUL
290
//
#defineDIV
291
//
/
#defineREMAIN
292
//
%
#defineGREATER
293
//
>
#defineLESS
294
//
<
#defineEQUAL
295
//
=
#defineMISTAKE
296
//
!
#defineAND
297
//
&
#defineOR
298
//
|
#definePP
299
//
++
#defineMM
300
//
--
#defineEE
301
//
==
#defineGE
302
//
>=
#defineLE
303
//
<=
#defineMISE
304
//
!
=
#defineAA
305
//
&&
#defineOO
306
//
||
#definePE
307
//
+=
#defineMINUSE
308
//
-=
#defineMULE
309
//
*一
#defineDIVE
310
//
/=
#definePOW
311
//
A
//界符
#defineSEMIC
312
//
J
#defineCOMMA
313
//
J
#defineMULANNO_L
314
//
/*
#defineMULANNO_R
315
//
*/
#defineBRACE_L
316
//
{
#defineBRACE_R
317
//
}
#defineBRAKET_L
318
//
(
#defineBRAKET_R
319
//
)
#defineMIDBRA_L
320
//
[
#defineMIDBRA_R
321
//
]
#defineONE_ANNO
322
////
//标识符和常量符
#defineTAG
400
#defineCONINT
401
#defineCONFLOAT
402
#defineCONCHAR403#defineCONSTRING404//转义字符和字符串
#defineCA500
#defineCB501
#defineCF502
#defineCN503
#defineCR504
#defineCT505
#defineCV506
#defineCBSL
507
#defineCQUE
#defineCDQM
#defineCQM
508
509
510
#defineZERO
511
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)
{
1到下一个角标
i++;//因为上面程序没进行++就直接break所以这里就需要加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];//将本行的第一个字符串赋值给strstr[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;startif(c=='/'&&buf[start]=='*')
{fputc('/',Out);fputc('*',Out);break;
}
else
{fputc(buf[start],Out);c=buf[start];
}
}
start++;
if(buf[start]=='\0')///*XXX\n类型
{
fputc('\n',Out);
line++;
while(fgets(buf,bufsize,in)!
=NULL)//说明这一行至少有一个字符\0除外{
len=strlen(buf);buf[len-1]='\0';
start=0;
if(buf[start]=='\0')
{
fputc('\n',Out);
line++;
}
else
{
st=start;
start++;while(buf[start]!
='\0'){
if(buf[st]=='*'&&buf[start]=='/')
{str[0]=buf[st];str[1]=buf[start];for(i=0;borderTable[i]!
="##";i++)if(strcmp(str,borderTable[i])==0){
sign2.sym=i+312;break;
}strcpy(sign2.name,str);strcpy(sign2.attr,"--");SigArr[SignNum]=sign2;SignNum++;fputs(sign2.name,Out);start++;