#include 《stdio.h》
#include 《ctype.h》
#include 《conio.h》
#include “stdio.h”
//下面定義保留,為簡化程序,使用字符指針數(shù)組保存所有保留字。
//如果想增加保留字,可繼續(xù)添加,并修改保留字?jǐn)?shù)目
#define keywordSum 8
#define maxvartablep 500//定義符號表的容量
char *keyword[keywordSum]={ “if”,“else”,“for”,“while”,“do”,“int”,“read”,“write”};
//下面定義純單分界符,如需要可添加
char singleword[50]=“+-*(){};,:”;
//下面定義雙分界符的首字符
char doubleword[10]=“》《=!”;
//函數(shù)調(diào)用
int TESTparse();
int program();
int compound_stat();
int statement();
int expression_stat();
int expression();
int bool_expr();
int additive_expr();
int term();
int factor();
int if_stat();
int while_stat();
int for_stat();
int write_stat();
int read_stat();
int declaration_stat();
int declaration_list();
int statement_list();
int compound_stat();
int name_def(char *name);
char token[20],token1[40];//token保存單詞符號,token1保存單詞值
char Scanout[300],Codeout[300]; //保存詞法分析輸出文件名
FILE *fp,*fout; //用于指向輸入輸出文件的指針
struct{//定義符號表結(jié)構(gòu)
char name[8];
int address;
}vartable[maxvartablep];//改符號表最多容納maxvartablep個(gè)記錄
int vartablep=0,labelp=0,datap=0;
int TESTscan();
char Scanin[300],Errorfile[300]; //用于接收輸入輸出以及錯(cuò)誤文件名
FILE *fin; //用于指向輸入輸出文件的指針
int TESTscan()//詞法分析函數(shù)
{
char ch,token[40]; //ch為每次讀入的字符,token用于保存識別出的單詞
int es=0,j,n; //es錯(cuò)誤代碼,0表示沒有錯(cuò)誤。j,n為臨時(shí)變量,控制組合單詞時(shí)的下標(biāo)等
printf(“請輸入源程序文件名(包括路徑):”);
scanf(“%s”,Scanin);
printf(“請輸入詞法分析輸出文件名(包括路徑):”);
scanf(“%s”,Scanout);
if ((fin=fopen(Scanin,“r”))==NULL) //判斷輸入文件名是否正確
{
printf(“/n打開詞法分析輸入文件出錯(cuò)!/n”);
return(1);//輸入文件出錯(cuò)返回錯(cuò)誤代碼1
}
if ((fout=fopen(Scanout,“w”))==NULL) //判斷輸出文件名是否正確
{
printf(“/n創(chuàng)建詞法分析輸出文件出錯(cuò)!/n”);
return(2); //輸出文件出錯(cuò)返回錯(cuò)誤代碼2
}
ch=getc(fin);
while(ch!=EOF)
{
while (ch==‘ ’||ch==‘/n’||ch==‘/t’) ch=getc(fin);
if (ch==EOF) break;
if (isalpha(ch)) //如果是字母,則進(jìn)行標(biāo)識符處理
{
token[0]=ch; j=1;
ch=getc(fin);
while(isalnum(ch)) //如果是字母數(shù)字則組合標(biāo)識符;如果不是則標(biāo)識符組合結(jié)束
{
token[j++]=ch; //組合的標(biāo)識符保存在token中
ch=getc(fin); //讀下一個(gè)字符
}
token[j]=‘/0’; //標(biāo)識符組合結(jié)束
//查保留字
n=0;
while ((n《keywordSum) && strcmp(token,keyword[n])) n++;
if (n》=keywordSum) //不是保留字,輸出標(biāo)識符
fprintf(fout,“%s/t%s/n”,“ID”,token); //輸出標(biāo)識符符號
else//是保留字,輸出保留字
fprintf(fout,“%s/t%s/n”,token,token); //輸出保留字符號
} else if (isdigit(ch))//數(shù)字處理
{
token[0]=ch; j=1;
ch=getc(fin); //讀下一個(gè)字符
while (isdigit(ch)) //如果是數(shù)字則組合整數(shù);如果不是則整數(shù)組合結(jié)束
{
token[j++]=ch; //組合整數(shù)保存在token中
ch=getc(fin); //讀下一個(gè)字符
}
token[j]=‘/0’; //整數(shù)組合結(jié)束
fprintf(fout,“%s/t%s/n”,“NUM”,token); //輸出整數(shù)符號
} else if (strchr(singleword,ch)》0) //單分符處理
{
token[0]=ch; token[1]=‘/0’;
ch=getc(fin);//讀下一個(gè)符號以便識別下一個(gè)單詞
fprintf(fout,“%s/t%s/n”,token,token); //輸出單分界符符號
}else if (strchr(doubleword,ch)》0) //雙分界符處理
{
token[0]=ch;
ch=getc(fin); //讀下一個(gè)字符判斷是否為雙分界符
if (ch==‘=’) //如果是=,組合雙分界符
{
token[1]=ch;token[2]=‘/0’; //組合雙分界符結(jié)束
ch=getc(fin); //讀下一個(gè)符號以便識別下一個(gè)單詞
} else//不是=則為單分界符
token[1]=‘/0’;
fprintf(fout,“%s/t%s/n”,token,token); //輸出單或雙分界符符號
} else if (ch==‘/’) //注釋處理
{
ch=getc(fin); //讀下一個(gè)字符
if (ch==‘*’) //如果是*,則開始處理注釋
{ char ch1;
ch1=getc(fin); //讀下一個(gè)字符
do
{ ch=ch1;ch1=getc(fin);} //刪除注釋
while ((ch!=‘*’ || ch1!=‘/’)&&ch1!=EOF); //直到遇到注釋結(jié)束符*/或文件尾
ch=getc(fin);//讀下一個(gè)符號以便識別下一個(gè)單詞
} else //不是*則處理單分界符/
{
token[0]=‘/’; token[1]=‘/0’;
fprintf(fout,“%s/t%s/n”,token,token); //輸出單分界符/
}
} else//錯(cuò)誤處理
{
token[0]=ch;token[1]=‘/0’;
ch=getc(fin); //讀下一個(gè)符號以便識別下一個(gè)單詞
es=3; //設(shè)置錯(cuò)誤代碼
fprintf(fout,“%s/t%s/n”,“ERROR”,token); //輸出錯(cuò)誤符號
}
}
fclose(fin);//關(guān)閉輸入輸出文件
fclose(fout);
return(es); //返回主程序
}
//語法、語義分析及代碼生成
//插入符號表動(dòng)作@name-def↓n, t的程序如下:
int name_def(char *name)
{
int i,es=0;
if (vartablep》=maxvartablep) return(21);
for(i=vartablep-1;i==0;i--)//查符號表
{
if (strcmp(vartable[i].name,name)==0)
{
es=22;//22表示變量重復(fù)聲明
break;
}
}
if (es》0) return(es);
strcpy(vartable[vartablep].name,name);
vartable[vartablep].address=datap;
datap++;//分配一個(gè)單元,數(shù)據(jù)區(qū)指針加1
vartablep++;
return(es);
}
//查詢符號表返回地址
int lookup(char *name,int *paddress)
{
int i,es=0;
for(i=0;i《vartablep;i++)
{
if (strcmp(vartable[i].name,name)==0)
{
*paddress=vartable[i].address;
return(es);
}
}
es=23;//變量沒有聲明
return(es);
}
//語法、語義分析及代碼生成程序
int TESTparse()
{
int es=0;
if((fp=fopen(Scanout,“r”))==NULL)
{
printf(“/n打開%s錯(cuò)誤!/n”,Scanout);
es=10;
return(es);
}
printf(“請輸入目標(biāo)文件名(包括路徑):”);
scanf(“%s”,Codeout);
if((fout=fopen(Codeout,“w”))==NULL)
{
printf(“/n創(chuàng)建%s錯(cuò)誤!/n”,Codeout);
es=10;
return(es);
}
if (es==0) es=program();
printf(“==語法、語義分析及代碼生成程序結(jié)果==/n”);
switch(es)
{
case 0: printf(“語法、語義分析成功并抽象機(jī)匯編生成代碼!/n”);break;
case 10: printf(“打開文件 %s失??!/n”,Scanout);break;
case 1: printf(“缺少{!/n”);break;
case 2: printf(“缺少}!/n”);break;
case 3: printf(“缺少標(biāo)識符!/n”);break;
case 4: printf(“少分號!/n”);break;
case 5: printf(“缺少(!/n”);break;
case 6: printf(“缺少)!/n”);break;
case 7: printf(“缺少操作數(shù)!/n”);break;
case 21: printf(“符號表溢出!/n”);break;
case 22: printf(“變量重復(fù)定義!/n”);break;
case 23: printf(“變量未聲明!/n”);break;
}
fclose(fp);
fclose(fout);
return(es);
}
//program::={《declaration_list》《statement_list》}
int program()
{
int es=0,i;
fscanf(fp,“%s %s/n”,token,token1);
printf(“%s %s/n”,token,token1);
if(strcmp(token,“{”))//判斷是否‘{’
{
es=1;
return(es);
}
fscanf(fp,“%s %s/n”,&token,&token1);
printf(“%s %s/n”,token,token1);
es=declaration_list();
if (es》0) return(es);
printf(“ 符號表/n”);
printf(“ 名字 地址/n”);
for(i=0;i《vartablep;i++)
printf(“ %s %d/n”,vartable[i].name,vartable[i].address);
es=statement_list();
if (es》0) return(es);
if(strcmp(token,“}”))//判斷是否‘}’
{
es=2;
return(es);
}
fprintf(fout,“ STOP/n”);//產(chǎn)生停止指令
return(es);
}
//《declaration_list》::=
//《declaration_list》《declaration_stat》|《declaration_stat》
//改成《declaration_list》::={《declaration_stat》}
int declaration_list()
{
int es=0;
while (strcmp(token,“int”)==0)
{
es=declaration_stat();
if (es》0) return(es);
}
return(es);
}
//《declaration_stat》↓vartablep,datap,codep -》int ID↑n@name-def↓n,t;
int declaration_stat()
{
int es=0;
fscanf(fp,“%s %s/n”,&token,&token1);printf(“%s %s/n”,token,token1);
if (strcmp(token,“ID”)) return(es=3); //不是標(biāo)識符
es=name_def(token1);//插入符號表
if (es》0) return(es);
fscanf(fp,“%s %s/n”,&token,&token1);printf(“%s %s/n”,token,token1);
if (strcmp(token,“;”) ) return(es=4);
fscanf(fp,“%s %s/n”,&token,&token1);printf(“%s %s/n”,token,token1);
return(es);
}
//《statement_list》::=《statement_list》《statement》|《statement》
//改成《statement_list》::={《statement》}
int statement_list()
{
int es=0;
while (strcmp(token,“}”))
{
es=statement();
if (es》0) return(es);
}
return(es);
}
//《statement》::= 《if_stat》|《while_stat》|《for_stat》
// |《compound_stat》 |《expression_stat》
int statement()
{
int es=0;
if (es==0 && strcmp(token,“if”)==0) es=if_stat();//《IF語句》
if (es==0 && strcmp(token,“while”)==0) es=while_stat();//《while語句》
if (es==0 && strcmp(token,“for”)==0) es=for_stat();//《for語句》
//可在此處添加do語句調(diào)用
if (es==0 && strcmp(token,“read”)==0) es=read_stat();//《read語句》
if (es==0 && strcmp(token,“write”)==0) es=write_stat();//《write語句》
if (es==0 && strcmp(token,“{”)==0) es=compound_stat();//《復(fù)合語句》
if (es==0 && (strcmp(token,“ID”)==0||strcmp(token,“NUM”)==0||strcmp(token,“(”)==0)) es=expression_stat();//《表達(dá)式語句》
return(es);
}
//《IF_stat》::= if (《expr》) 《statement 》 [else 《 statement 》]
/*
if (《expression》)@BRF↑label1 《statement 》 @BR↑label2 @SETlabel↓label1
?。?else 《 statement 》] @SETlabel↓label2
評論
查看更多