#include <iostream>
#include <fstream>
using namespace std;
//函数定义
string InputSource(string); //输入源代码
string DeleteExtra(string); //删除额外字符
void OutputCode(string); //输出结果
void SaveResult(int,int,string); //保存结果
void SaveError(int,int,string); //保存错误
bool IsDigit(char); //判断是否数字
bool IsLetter(char); //判断是否字母
bool IsOperate(char); //判断是否运算符
bool IsSymbol(char); //判断是否符号
bool IsReserved(string); //判断是否保留字
void IsNumber(int,string&,int,int&); //数字类型
void IsIdenti(int,string&,int,int&); //标识符
void IsString(int,string&,int,int&); //字符串
void IsMarco(int,string&,int,int&); //宏
void IsOpt(int,string&,int,int&); //操作粗
void IsSym(int,string&,int,int&); //分隔符
//存储容器
struct save{
int line;
int type;
string content;
}Error[1000],Result[1000];
int Ei=0,Ri=0;
//主函数
int main(int argc,char* argv[]){
//输入代码
if(argc==1){
cout<<"词法分析器V0.2 BY 1T0F\n\n使用方法:lex [PATH]"<<endl;
exit(-1);
}
string TempFile=InputSource(argv[1]);
TempFile=DeleteExtra(TempFile);
//词法分析部分
int i=0,LineNum=1;
while(TempFile[i]){
if(TempFile[i]=='\n')
{i++;LineNum++;} //行号
else if(TempFile[i]=='"')
IsString(LineNum,TempFile,i++,i); //字符串
else if(TempFile[i]=='#')
IsMarco(LineNum,TempFile,i++,i); //宏
else if(TempFile[i]=='+'||TempFile[i]=='-'||IsDigit(TempFile[i]))
IsNumber(LineNum,TempFile,i++,i); //数字(+/-/0-9)
else if(IsLetter(TempFile[i])||TempFile[i]=='_')
IsIdenti(LineNum,TempFile,i++,i); //标识符(字母或下划线)
else if(IsOperate(TempFile[i]))
IsOpt(LineNum,TempFile,i++,i); //运算符
else if(IsSymbol(TempFile[i]))
IsSym(LineNum,TempFile,i++,i); //分隔符
else
i++; //其他
}
OutputCode(argv[1]);
cout<<"运行结束"<<endl;
return 0;
}
//输入源代码
string InputSource(string path){
ifstream infile(path.c_str(),ios::in);
if (!infile){
cout<<"找不到文件,请检查文件路径是否正确"<<endl;
exit(-1);
}
char temp[3000];
infile.getline(temp,3000,EOF);
infile.close();
return temp;
}
//删除额外字符
string DeleteExtra(string code){
string temp;
int i=0;
while(code[i]){
if(code[i]=='/'&&code[i+1]=='/')while(code[i]!='\n')i++;//过滤注释
while(code[i]==' '&&code[i+1]==' ')i++; //过滤连续空格
if(code[i]!='\t')temp=temp+code[i]; //过滤TAB
i++;
}
return temp;
}
//输出结果
void OutputCode(string path){
if(Ei>0){
cout<<"出错了!"<<endl;
for(int j=0;j<Ei;j++){
cout<<"行号:"<<Error[j].line<<"\t"<<Error[j].content<<"\t原因:";
if(Error[j].type==0)
cout<<"未知字符";
else if(Error[j].type==1)
cout<<"错误的数字表示";
cout<<endl;
}
}
else{
string filename=path;
filename=filename+".txt";
ofstream outfile(filename.c_str(),ios::out);
if (!outfile){
cout<<"分析结果无法保存"<<endl;
exit(-1);
}
for(int j=0;j<Ri;j++){
outfile<<"L:"<<Result[j].line<<"\t";
if(Result[j].type==0)
outfile<<"Mar";
else if(Result[j].type==1)
outfile<<"Num";
else if(Result[j].type==2)
outfile<<"Key";
else if(Result[j].type==3)
outfile<<"ID";
else if(Result[j].type==4)
outfile<<"Opt";
else if(Result[j].type==5)
outfile<<"Sym";
else if(Result[j].type==6)
outfile<<"Str";
outfile<<"\t"<<Result[j].content<<endl;
}
outfile.close();
}
}
//保存结果
void SaveResult(int line,int type,string content){
Result[Ri].line=line;
Result[Ri].type=type;
Result[Ri].content=content;
Ri++;;
}
//保存错误
void SaveError(int line,int err,string content){
Error[Ei].line=line;
Error[Ei].type=err;
Error[Ei].content=content;
Ei++;
}
//是否是数字
bool IsDigit(char letter){
if(letter>='0'&&letter<='9')
return true;
return false;
}
//是否是字母
bool IsLetter(char letter){
if(letter>='a'&&letter<='z')
return true;
if(letter>='A'&&letter<='Z')
return true;
return false;
}
//是否是运算符
bool IsOperate(char letter){
char Array[7]={'*','/','=','<','>','+','-'};
for(int i=0;i<7;i++)
if(Array[i]==letter)return true;
return false;
}
//是否是符号
bool IsSymbol(char letter){
char Array[8]={',',';','{','}','(',')','[',']'};
for(int i=0;i<8;i++)
if(Array[i]==letter)return true;
return false;
}
//是否是保留字
bool IsReserved(string str){
string Array[17]={"char","int","float","void","const","break","case","continue","default","do","else","for","goto","if","return","switch","while"};
for(int i=0;i<17;i++)
if(Array[i]==str)return true;
return false;
}
//数字类型
void IsNumber(int line,string& src,int begin,int& end){
int err=-1;
while(IsDigit(src[end]))end++;
if(src[end]=='.'){
end++;
while(IsDigit(src[end]))end++;
}
if(src[end]=='e'||src[end]=='E'){
end++;
if(src[end]=='+'||src[end]=='-'||IsDigit(src[end])){
end++;
while(IsDigit(src[end]))end++;
}
else
err=1;
}
string TmpWord(src,begin,end-begin);
if(err!=-1)
SaveError(line,1,TmpWord);
else if(TmpWord=="+"||TmpWord=="-")
SaveResult(line,4,TmpWord);
else
SaveResult(line,1,TmpWord);
}
//标识符(含关键字的区分)
void IsIdenti(int line,string& src,int begin,int& end){
while(IsLetter(src[end])||IsDigit(src[end])||src[end]=='_')end++;
string TmpWord(src,begin,end-begin);
if(IsReserved(TmpWord))
SaveResult(line,2,TmpWord);
else
SaveResult(line,3,TmpWord);
}
//字符串
void IsString(int line,string& src,int begin,int& end){
while(src[end]!='"'){
if(src[end]=='\\')end++;
end++;
}
end++;
string TmpWord(src,begin,end-begin);
SaveResult(line,6,TmpWord);
}
//宏
void IsMarco(int line,string& src,int begin,int& end){
while(src[end]!='\n')end++;
string TmpWord(src,begin,end-begin);
SaveResult(line,0,TmpWord);
}
//运算符
void IsOpt(int line,string& src,int begin,int& end){
while(IsOperate(src[end]))end++;
string TmpWord(src,begin,end-begin);
SaveResult(line,4,TmpWord);
}
//分隔符
void IsSym(int line,string& src,int begin,int& end){
string TmpWord(src,begin,end-begin);
SaveResult(line,5,TmpWord);
}