一、题目要求
题目:
选择部分C语言的语法成分,设计其词法分析程序、语法语义分析程序。
要求:
设计并实现一个一遍扫描的词法语法语义分析程序,将部分C语言的语法成分(包含赋值语句、if语句、while循环语句)翻译成三地址代码,要求有一定的出错提示和错误恢复功能。
二、源码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUFFSIZE 5000
char prog[BUFFSIZE],token[8];
char ch,ch1;
int syn,p,q,m,n,sum,i=1,k=0,kk,flag=0;
char *rwtab[32]={"main","break","case","char","define","continue","default",
"do","double","else","what","extern","float","for","goto","if",
"int","long","stack","return","short","fopen","sizeof",
"static","struct","switch","typedef","enum","unsigned","void","fclose","while"};
int main() /*主函数*/
{
void scaner();
int lrparser();
FILE *fp;
if((fp=fopen("test.txt","r"))==NULL)
{ printf("无法打开文件!\n");
exit(1);
}
p=0;
while(!feof(fp))
{ prog[p++]=fgetc(fp);
if(p>=5000)
{ printf("缓冲区容量不够!\n");
exit(1);
}
}/*把文件test中的内容存入数组prog中*/
fclose(fp);
printf("%s\n",prog);
p=0;
printf("输出词法分析结果:\n");
do
{
scaner();
switch(syn)
{
case 34:printf("(%d,%d),",syn,sum);break;
case -1:printf("error,");break;
default:printf("(%d,%s),",syn,token);
}
}while(syn!=0);
p=0;
printf("\n语法语义的分析开始:\n");
scaner();
lrparser();
system("pause");
return 0;
}
void scaner()
{
for(n=0;n<8;n++) token[n]=NULL;
m=0;
sum=0;
ch=prog[p];
while(ch==' '||ch=='\n')
{ p++;
ch=prog[p];
}/*读下一个字符*/
if((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z'))
{ while((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z')||(ch>='0'&&ch<='9'))
{ token[m]=ch;
m++;p++;
ch=prog[p];
}
token[m++]='\0';
syn=33;
for(n=0;n<32;n++)
if(strcmp(token,rwtab[n])==0)
{ syn=n+1;
break;
}
}/*判断输入字符是否为标识符或者关键字的情况*/
else
if(ch>='0'&&ch<='9')
{ while(ch>='0'&&ch<='9')
{ sum=sum*10+ch-'0';
p++;
ch=prog[p];
}
syn=34;
}/*判断输入字符是否为整型常数的情况*/
else
switch(ch)
{
case '<':token[m]=ch;
p++;
ch=prog[p];
if(ch=='>')
{ syn=42;
m++;
token[m]=ch;
p++;
}/*出现<>的情况*/
else if(ch=='=')
{ syn=43;
m++;
token[m]=ch;
p++;
}/*出现<=的情况*/
else
{ syn=41;}
break;
case '>':token[m]=ch;
p++;
ch=prog[p];
if(ch=='=')
{ syn=45;
m++;
token[m]=ch;
p++;
}/*出现>=的情况*/
else
{syn=44;}
break;
case ':':token[m]=ch;
p++;
ch=prog[p];
if(ch=='=')
{ syn=40;
m++;
token[m]=ch;
p++;
}/*出现:=的情况*/
else
{syn=39;}
break;
case '/':token[m]=ch;
p++;
ch=prog[p];
if(ch=='*')
{ syn=51;
q=0;
m++;
token[m]=ch;
p++;
q=p+1;
while(prog[p]!='*'||prog[q]!='/')
{p++;q++;}
}/*出现注释'/*'的情况*/
else
{syn=38;}
break;
case '*':token[m]=ch;
p++;
ch=prog[p];
if(ch=='/')
{ syn=52;
m++;
token[m]=ch;
p++;
}
else
{syn=37;}
break;
case '+':syn=35;token[0]=ch;p++;break;
case '-':syn=36;token[0]=ch;p++;break;
case '=':syn=46;token[0]=ch;p++;break;
case ';':syn=47;token[0]=ch;p++;break;
case '(':syn=48;token[0]=ch;p++;break;
case ')':syn=49;token[0]=ch;p++;break;
case '%':syn=50;token[0]=ch;p++;break;
case '{':syn=53;token[0]=ch;p++;break;
case '}':syn=54;token[0]=ch;p++;break;
case ',':syn=55;token[0]=ch;p++;break;
case '#':syn=0;token[0]=ch;p++;break;
default:syn=-1;
}
}
void emit(char *result,char *ag1,char *op,char *ag2)
{
printf("(%d) %s=%s%s%s\n",i,result,ag1,op,ag2);
i++;
return;
}
char *newtemp(void)
{
char *p;
char m[8];
p=(char *)malloc(8);
k++;
itoa(k,m,10);
strcpy(p+1,m);
p[0]='t';
return(p);
}
int lrparser()
{ int yucu();
int schain=0;
kk=0;
if(syn!=1)
{
printf("缺main错误!!\n");
flag++;
}
scaner();
if(syn!=48)
{
printf("main后缺(括号!!\n");
flag++;
}
else scaner();
if(syn!=49)
{
printf("main后缺)括号!!\n");
flag++;
}
else scaner();
if(syn!=53)
{
printf("main后缺{括号!!\n");
flag++;
}
else scaner();
schain=yucu();
if(syn==54)
{ scaner();
if(syn==0&&kk==0&&flag==0)/*kk是用来记录其他错误的标识*/
printf("语法与语义分析结束。分析结果为:success\n");
else
printf("程序存在着%d个错误\n",flag);
}
else
{if(kk!=1)
printf("缺}错误!!");
kk=1;
}
return(schain);
}
int yucu()
{
int statement();
int schain=0;
schain=statement();
while(syn==47)
{ scaner();
schain=statement();
}
return(schain);
}
int statement()
{
char *expression();
char tt[8],eplace[8];
int schain=0;
switch(syn)
{ case 33:
strcpy(tt,token);
scaner();
if(syn==46)
{ scaner();
strcpy(eplace,expression());
emit(tt,eplace," "," ");
schain=0;
}
else{printf("赋值号=错误!!");kk=1;}
return(schain);
break;
}
}
char *expression(void)
{ char *term();
char *tp,*ep2,*eplace,*tt;
tp=(char *)malloc(12);
ep2=(char *)malloc(12);
eplace=(char *)malloc(12);
tt=(char *)malloc(12);
strcpy(eplace,term());
while(syn==35||(syn==36))
{ strcpy(tt,token);
scaner();
strcpy(ep2,term());
strcpy(tp,newtemp());
emit(tp,eplace,tt,ep2);
strcpy(eplace,tp);
}
return(eplace);
}
char *term(void)
{
char *factor();
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==37||(syn==38))
{ 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==33)
{
strcpy(fplace,token);
scaner();
}
else if(syn==34)
{
itoa(sum,fplace,10);
scaner();
}
else if(syn==48)
{
scaner();
fplace=expression();
if(syn==49)
scaner();
else{printf("缺‘)’错误!!\n");kk=1;flag++;}
}
else{printf("表达式错误!!\n");kk=1;flag++;}
return(fplace);
}