PL0语言词法分析程序.docx
《PL0语言词法分析程序.docx》由会员分享,可在线阅读,更多相关《PL0语言词法分析程序.docx(18页珍藏版)》请在冰豆网上搜索。
PL0语言词法分析程序
PL/0语言词法分析程序
//这是我编译原理的一次作业,中间有许多不足之处希望大家指正
/*编写PL/0语言的词法分析程序
要求:
1、读入用PL/0语言编写的源程序,正确的进行词法分析,并输出二元式序列。
2、若源程序有词法错误,能够给出出错的准确位置。
3、词法代号如下
(+,+);
(-,-);
(*,*);
(/,/);
((,();
(),));
(,,,);
(;,;);
(.,.);
(#,#);
(=,=);
(>,>);
(<,<);
(:
=,a);
(>=,b);
(<=,c);
(数字,d);
(标识符,e);
关键字代号:
(begin,f);
(call,g);
(const,h);
(do,i);
(end,j);
(if,k);
(odd,l);
(procedure,m);
(read,n);
(then,o);
(var,p);
(while,q);
(write,r);
4、等于运算符号为一个=
测试程序:
A.C
======================
CONSTA=10;
VARB,C;
PROCEDUREP;
VARD;
PROCEDUREQ;
VARX;
BEGIN
READ(X);
D:
=X;
WHILEX
DOCALLP;
END;
BEGIN
WRITE(D);
CALLQ;
END;
BEGIN
CALLP;
END.
*/
/*programname:
chifufenxi*/
/*作者:
小万QQ:
421404493*/
/*date:
2004.10.11*/
#include
#include
#include
#include
#include
#defineN256//每一行的字符数不能超过256个
charbuffer[N];//用作存放一行字符
charword[20];//用作存放经过分析单词
char*kword[13]={"begin","call","const","do","end","if","odd","procedure","read","then","var","while","write"};
charktype[13]={'f','g','h','i','j','k','l','m','n','o','p','q','r'};
intlen;//记录每一行的长度
intcount=0;//用来记录行数
voidwrite(char*wstr,charwc,FILE*wout)//将分析结果按照规则写入到文件
{
fputc('(',wout);
fputs(wstr,wout);
fputc(',',wout);
fputc(wc,wout);
fputc(')',wout);
}
intreadbuffer(FILE*fp)
{
charch;
len=0;
ch=fgetc(fp);
while(!
feof(fp)&&ch!
='\n')//读取字符到缓冲区
{
buffer[len]=ch;
ch=fgetc(fp);
len++;
}
len--;//用来控制词法分析时行分析中字母的个数
if(feof(fp))//标志文件是否结束
return0;
else
return1;
}
voiderror(inttype)
{
if(type==1)
printf("为无效字符,第%d行词法出错,标志符不能以数字开头\n",count);
elseif(type==2)
printf("第%d行词法出错,赋值符应为\:
\=\n",count);
elseprintf("为无效字符,第%d行词法出错\n",count);
}
voidcheck(char*str,FILE*out);//声明函数,此函数用来分类单词
voidfenxi(char*row,FILE*op)//此函数用来对每一行的单词进行语法分析
{
//printf("%d\n",count);
intk=0;//用作控制临时存放单词的变量str0
inti=0;//定义两个变量用作控制每一行是否结束,
intferror=0;//用作出错标志
charstr0[20];//临时存放单词的变量
while(i<=len)
{
k=0;//将k置0
strcpy(word,"\0");//将存放单词的变量清空
/*去除空格*/
if(isspace(row[i]))//去出空格,跳格符,换行符
{
i++;
continue;
}
/*去出无效字符*/
while(!
isalpha(row[i])&&!
isdigit(row[i])&&i<=len&&!
isspace(row[i])&&!
(row[i]=='\0'||row[i]==':
'||row[i]=='>'||row[i]=='<'||row[i]=='+'||row[i]=='-'||row[i]=='*'||row[i]=='/'||row[i]=='('||row[i]==')'||row[i]==','||row[i]==';'||row[i]=='.'||row[i]=='#'||row[i]=='='))
{
putchar(row[i]);
i++;
ferror=1;//设置错误标志符
}
if(ferror==1)
{
error(3);//调用出错处理函数
ferror=0;
}
/*对注释进行处理,假设此语言的注释只能单行注释以双斜杠"//"为注释开始标志*/
if(row[i]=='/')
{
i++;
if(row[i]=='/')
{
i=len+1;//忽略注释符后面的单词
continue;
}
else
i--;
}
/*判断是否为数字*/
if(isdigit(row[i]))
{
while(i<=len&&!
isspace(row[i])&&!
(row[i]=='\0'||row[i]==':
'||row[i]=='>'||row[i]=='<'||row[i]=='+'||row[i]=='-'||row[i]=='*'||row[i]=='/'||row[i]=='('||row[i]==')'||row[i]==','||row[i]==';'||row[i]=='.'||row[i]=='#'||row[i]=='='))
//当不到行尾,是数字或字母当然有可能是无效字符
{
if(isdigit(row[i]))//是数字则将字符逐个存入临时数组
{
str0[k]=row[i];
i++;
k++;
//putchar('e');
}
else//数字中加有字母或无效字符则报错
{
//putchar('x');
ferror=1;break;//已经出错设置标志并退出循环
}
}
if(ferror==1)//检测是否出错
{/*将刚刚的那个单词后面的数字和字母
清空,如123abc123或则123$$23等,当出现错误后,需
要消除abc123和$$23 以免误作为下一个标志符*/
for(intj=0;j putchar(str0[j]);
while(i<=len&&!
isspace(row[i])&&!
(row[i]=='\0'||row[i]==':
'||row[i]=='>'||row[i]=='<'||row[i]=='+'||row[i]=='-'||row[i]=='*'||row[i]=='/'||row[i]=='('||row[i]==')'||row[i]==','||row[i]==';'||row[i]=='.'||row[i]=='#'||row[i]=='='))
{
putchar(row[i]);
i++;
}
error
(1);//putchar('e');//调用出错处理函数
ferror=0;//重新设置错误标志位
//i--;//strcpy(word,"");
}
else//未出错照常处理
{
str0[k]='\0';
strcpy(word,str0);
i--;//减一是为了使最后取出的那个字符不在被下面的程序判断
//str0[0]='\0';
}
}
/*判断是否为标志符和关键字即由字母开头并且不含标点符号用ispunct(intch)判断标点符号*/
if(isalpha(row[i]))//标志符或关键字由字母开头
{
k=0;
while(i<=len&&row[i]!
=32&&!
(row[i]=='\0'||row[i]==':
'||row[i]=='>'||row[i]=='<'||row[i]=='+'||row[i]=='-'||row[i]=='*'||row[i]=='/'||row[i]=='('||row[i]==')'||row[i]==','||row[i]==';'||row[i]=='.'||row[i]=='#'||row[i]=='='))//关键字和标志符由数字和字母组成
{
if(isalpha(row[i])||isdigit(row[i]))//由数字和字母组成
{
str0[k]=row[i];
i++;
k++;
}
else//出错,原因可能是出现了不可识别的字符
{
ferror=1;break;
}
}
if(ferror)
{
for(intj=0;j putchar(str0[j]);
while(i<=len&&!
isspace(row[i])&&!
(row[i]=='\0'||row[i]==':
'||row[i]=='>'||row[i]=='<'||row[i]=='+'||row[i]=='-'||row[i]=='*'||row[i]=='/'||row[i]=='('||row[i]==')'||row[i]==','||row[i]==';'||row[i]=='.'||row[i]=='#'||row[i]=='='))
{
putchar(row[i]);//消除整个非法单词
i++;
}
ferror=0;
error(3);
//i--;
}
else
{
str0[k]='\0';
strcpy(word,str0);
str0[0]='\0';
i--;
}
}
/*判断运算符*/
if(row[i]=='+'||row[i]=='-'||row[i]=='*'||row[i]=='/'||row[i]=='('||row[i]==')'||row[i]==','||row[i]==';'||row[i]=='.'||row[i]=='#'||row[i]=='=')
{
str0[0]=row[i];
str0[1]='\0';
strcpy(word,str0);
str0[0]='\0';
}//要先判断单个字符的运算符,以避免诸如>=的运算符后面的=再次被判断
if(row[i]==':
')
{
i++;
if(row[i]=='=')
{
//word[0]=':
';
//word[1]='=';
//word[2]='\0';
strcpy(word,">=");
}
else
{
error
(2);//出错后调用处理函数
i--;
}
}
if(row[i]=='>')
{
i++;
if(row[i]=='=')
{
strcpy(word,">=");
}
else
{
strcpy(word,">");
i--;
}
}
if(row[i]=='<')
{
i++;
if(row[i]=='=')
{
strcpy(word,"<=");
}
else
{strcpy(word,"<");i--;}
}
//puts(word);
check(word,op);/*
调用分类函数,辨别每一个单词的类别要求
输入的每一个单词必须符合词法规则*/
//word[0]='\0';
i++;//使指针后移,取出下一个字母
}
}
voidcheck(char*str,FILE*out)
{
if(isdigit(str[0]))/*如果第一个字符是数字那么整个单词都是数字组成的,即为常数*/
{
write(str,'d',out);//调用写函数将分好类的单词写入文件
}
if(isalpha(str[0]))/*如果第一个字符是字母,那么这个单词是标志符或关键字*/
{
intfyiyong=0;//用作标记这个单词是否已被分类
/*以下判别是否是关键字*/
for(intct=0;ct<13;ct++)
{
if(!
strcmp(str,kword[ct]))
{
write(str,ktype[ct],out);
fyiyong=1;
}
}
/*经过以上判别,可以判别是否是关键字,不是即为标志符*/
if(fyiyong!
=1)
{
write(str,'e',out);
}
}
/*以下对运算符分类*/
if(str[0]=='>')
{
if(str[1]=='=')
{
write(str,'b',out);
}
else
{
write(str,'>',out);
}
}
if(str[0]=='<')
{
if(str[1]=='=')
{
write(str,'c',out);
}
else
{
write(str,'<',out);
}
}
if(!
strcmp(str,":
="))
{
write(str,'a',out);
}
if(str[0]=='+'||str[0]=='-'||str[0]=='*'||str[0]=='/'||str[0]=='('||str[0]==')'||str[0]==','||str[0]==';'||str[0]=='.'||str[0]=='#'||str[0]=='=')
{
write(str,str[0],out);
}
}
voidmain()
{
count=1;
charscfilename[20],rsfilename[20];//定义用来存放输入源文件和输出目标文件的名字
printf("Pleaseinputyoursourcefilename:
");
gets(scfilename);
printf("Pleaseinputyourresultfilename:
");
gets(rsfilename);
FILE*fp,*op;
fp=fopen(scfilename,"r");
op=fopen(rsfilename,"w");
if(fp)//打开文件成功后调用函数对源文件进行词法分析
{
while(readbuffer(fp))
{
fenxi(buffer,op);
count++;//行加一
}
}
else//whilethefilenotexist
{
printf("Yoursoucefilenotexist!
!
!
\n");
exit(0);
}
fclose(fp);//closethefiles
fclose(op);
printf("ok!
");//outputthemarkofend
getchar();
}