📄 张文萍词法分析器.cpp
字号:
#include <iostream.h>
#include <stdio.h>
#include <string.h>
#include <fstream.h>
#define NULL 0
#define MAX_KEY_NUM 15
#define MAX_UNI_NUM 17
#define MAX_DOU_NUM 11
FILE *sfile;//源文件指针
FILE *dfile;//目标文件指针
int count=0;//记录错误个数
int line=0;//记录行数
char sfilename[20],dfilename[20];
char *key[MAX_KEY_NUM]={"int","char","float","void","const","for","if","else","then","while","switch","break","begin","end","main"};
char *unifort[MAX_UNI_NUM]={",",";","{","}","(",")","[","]","+","-","*","/","%","!","<",">","="};
char *doublet[MAX_DOU_NUM]={"/=","+=","-=","*=","%=","||","&&","<=","==",">=","!="};
char consts[100][20]; //定义常数表
char label[100][20]; //定义标识符表
int connum=0; //数字数组的下标
int labnum=0; //标识符数组的下标
//====函数定义=========
int Initscanner();
void Scanner();
void Lexscan(char);
void Isalpha(char[]);
void Isnumber(char[]);
void Isanotation(char[]);
void Isother(char[]);
void Output();
void error(int);
void close();
//===================主函数============================
void main()
{
cout<<"=============欢迎您使用由张文萍编写的词法分析器================"<<endl;
Initscanner();
cout<<endl;
cout<<"开始编译"<<endl;
cout<<endl;
Scanner();
cout<<endl;
cout<<"编译完成"<<endl;
cout<<endl;
close();
char choice;
cout<<"是否输出编译成功的结果?(Y or N)"<<endl;
cin>>choice;
if(choice=='Y'||choice=='y')
{
Output();
}
else
cout<<"感谢您使用此编译系统!"<<endl;
}
//==================初始化函数===================
int Initscanner()
{
cout<<"请输入您要编译的源文件名:"<<endl;
cin>>sfilename;
sfile=fopen(sfilename,"r");
if(sfile==NULL)
{
cout<<"文件不存在!"<<endl;
}
cout<<"请输入目标文件名:"<<endl;
cin>>dfilename;
dfile=fopen(dfilename,"w");
if(dfile==NULL)
{
cout<<"无法打开文件!"<<endl;
return -1;
}
return 1;
}
//===================浏览函数==========================
void Scanner()
{
char s;
s=fgetc(sfile);
line++;
while(s!=EOF)
{
if(s=='\n')line++;
while(s==' '||s=='\n')
{
s = fgetc(sfile);
if(s=='\n')line++;
}
Lexscan(s);
s=fgetc(sfile);
}
return;
}
//======================Lexscan函数=========================
void Lexscan(char byte)
{
char wordty[20];
//数组中第一个字符是数字,转向Isnumber函数处理
if((byte>='0')&&(byte<='9'))
{
wordty[0]=byte;
int k=1;
char s;
s=fgetc(sfile);
if(s=='\n')line++;
if(s!=EOF&&s!=' '&&s!='\n')
{
if(s>='0'&&s<='9')
{wordty[k++]=s;
s=fgetc(sfile);}//再读入下一个字符
if(s=='\n')line++;
while(s>='0'&&s<='9')
{
wordty[k++]=s;
s=fgetc(sfile);
if(s=='\n')line++;
}
if(s!='.')//如果当前读入的符号不为小数点,则常数读完毕,输出此常数
wordty[k++]='\0';
else//当前字符为小数点则继续向下读入
{ wordty[k++]=s;
s=fgetc(sfile);
if(s=='\n')line++;
while(s>='0'&&s<='9')
{
wordty[k++]=s;
s=fgetc(sfile);
if(s=='\n')line++;
}
wordty[k++]='\0';
}
}
fseek(sfile,-1,SEEK_CUR);
Isnumber(wordty);
}
else
//数组中第一个字符是字母,则转向Isalpha函数处理
if (byte>='A'&&byte<='Z'||byte>='a'&&byte<='z'||byte=='_')
{
wordty[0]=byte;
int n=1;
char s;
s=fgetc(sfile);
if(s=='\n')line++;
if(s!=EOF&&s!=' '&&s!='\n')
{
wordty[n++]=s;
s=fgetc(sfile);//再读入下一个字符
if(s=='\n')line++;
while((s>='0'&&s<='9')||(s>='a'&&s<='z')||(s>='A'&&s<='Z'))
{
wordty[n++]=s;
s=fgetc(sfile);
if(s=='\n')line++;
}
wordty[n]='\0';
}
fseek(sfile,-1,SEEK_CUR);
Isalpha(wordty);
return;
}
else
if(byte!=EOF&&byte!=' '&&byte!='\n')
{//第一个字符是符号,则调用Isother函数
if(byte=='/')
{
wordty[0]=byte;
Isanotation(wordty);
}
else
{
wordty[0]=byte;
int m=1;
char s;
s=fgetc(sfile);
if(s==' ')
wordty[m]='\0';
else
if(s=='\n')
{
line++;
wordty[m]='\0';
}
else
{
if(s!=EOF)
{
if(s=='='||s=='&'||s=='|')
{wordty[m++]=s;
wordty[m]='\0';}
else
{ wordty[m]='\0';
fseek(sfile,-1,SEEK_CUR);}
}
else
wordty[m]='\0';
}
Isother(wordty);
return;
}
}
}
//=====================Isalpha函数==========================
void Isalpha(char wordty[])
{
for (int m=0;m<MAX_KEY_NUM;m++)
{
if (strcmp(key[m],wordty)==0)
{
fprintf(dfile,"(%s,-) ",wordty);
return;
}
}
if(labnum!=0)
{
int j=0;
while(j<labnum)
{
if(strcmp(label[j],wordty)==0)
break;
else j++;
}
if(j>=labnum)//"标识符表未定义"
{
strcpy(label[labnum],wordty);
fprintf(dfile,"(%s,%d) ","id",labnum);
labnum++;
return;
}
else
{
fprintf(dfile,"(%s,%d) ","id",j);
return;
}
}
else
{
strcpy(label[labnum],wordty);
fprintf(dfile,"(%s,%d) ","id",labnum);
labnum++;
return;
}
}
//==================Isnumber函数=============================
void Isnumber(char wordty[])
{
if(connum!=0)
{
int j=0;
while(j<connum)
{
if(strcmp(consts[j],wordty)==0)
break;
else
j++;
}
if(j>=connum)//"数字表未定义"
{
strcpy(consts[connum],wordty);
fprintf(dfile,"(%s,%d) ","num",connum);
connum++;
}
else //定义输出位置
{
fprintf(dfile,"(%s,%d) ","num",j);
}
}
else
{
strcpy(consts[connum],wordty);
fprintf(dfile,"(%s,%d) ","num",connum);
connum++;
}
}
//=====================符号处理函数=============================
void Isother(char wordty[])
{
if(strlen(wordty)==2)
{
for (int i=0;i<MAX_DOU_NUM;i++)
if (strcmp(doublet[i],wordty)==0)
{
if((strcmp(wordty,"<=")==0)||(strcmp(wordty,">=")==0)||(strcmp(wordty,"!=")==0)||(strcmp(wordty,"==")==0))
{fprintf(dfile,"(rlop,-) ");}
else
if(strcmp(wordty,"&&")==0)
{fprintf(dfile,"(%s,-) ","and");}
else
if(strcmp(wordty,"||")==0)
{fprintf(dfile,"(%s,-) ","or");}
else
{fprintf(dfile,"(%s,-) ",wordty);}
}
}
else
if(strlen(wordty)==1)
{
int flag=0;
int j=0;
while(j<MAX_UNI_NUM)
{
if (strcmp(unifort[j],wordty)==0)
{
flag=1;
if((strcmp(wordty,"<")==0)||(strcmp(wordty,">")==0))
{fprintf(dfile,"(rlop,-) ");break;}
else
if(strcmp(wordty,"!")==0)
{fprintf(dfile,"(%s,-) ","not");break;}
else
{fprintf(dfile,"(%s,-) ",wordty);break;}
}
else j++;
}
if(!flag)
{cout<<wordty;error(1);}
}
}
//==========================处理/号函数============================
void Isanotation(char wordty[])
{
char s;
s=fgetc(sfile);
if(s=='\n')line++;
else
{
switch(s)
{
case '=':
{ fprintf(dfile,"(/=,-) ");
break;}
case '*': //查找/*错误
{for(;;)
{
s=fgetc(sfile);
if(s=='\n')line++;
if(s==EOF){error(2);break;}
if(s=='*')
{
s=fgetc(sfile);
if(s=='/')
{
return;
}
}
}
break;}
case '/'://"//"之后为注释内容
s=fgetc(sfile);
if(s=='\n')line++;
else
while(s!='\n')
{
s=fgetc(sfile);
if(s=='\n')line++;
}cout<<"第"<<line-1<<"行//后为注释内容"<<endl;
break;
default: /*不是注释,当作除号处理*/
{fprintf(dfile,"(/,-) ");
break;}
}
}
}
//==================输出函数========================
void Output()
{
dfile=fopen(dfilename,"r");
char ch;
ch=fgetc(dfile);
cout<<ch;
while(ch!=EOF)
{ch=fgetc(dfile);
cout<<ch;
}
}
//======================报错函数=========================
void error(int a)
{
count++;
switch(a)
{
case 1: cout<<"错误"<<count<<":第"<<line<<"行此字符非法!"<<endl;break;
case 2: cout<<"错误"<<count<<":第"<<line-1<<"行没有匹配的*/"<<endl;break;
default:break;
}
}
//======================关闭文件===============================
void close()
{
fclose(sfile);//关闭原文件
fclose(dfile);//关闭目标文件
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -