用C++定义了一个类,可以自定义保留字,通过调用类的方法来实现词法分析的功能,封装的还是挺高的。
前提假设
状态 | 内容 | 类别 |
---|---|---|
1 | main、if、int、for、while、do、return、break、continue… | 保留字 |
2 | 标识符 | |
3 | 常数 | |
4 | +、-、*、/、=、>、<、>=、<=、!= | 运算符 |
5 | 、;、{、}、(、) | 分割符 |
正规式
标识符:
(a|b|c…z|A|B|…|Z)(a|b|c…z|A|B|…|Z|0|1|2…9|)*
常数:
(0|1|2…9|)*
输入格式:
输出格式:
代码:
#include<iostream>
#include<string>
#include<fstream>
#include<map>
#include<vector>
class Compiler
{
protected:
std::map<std::string,int> table;//单词表格,包含了标识符表与
std::string *key_table;//保留字表
int key_len;
std::string singalword;
std::string doubleword;
std::vector<std::string> operator_table;//运算符表
std::vector<std::string> limitation_table;//界符表
public:
Compiler(int key_len,std::string *key_table);
void begin_compiler(std::string fin,std::string fout);
int lookup(std::string temp);
bool isOperator(std::string temp);
bool isLimitation(std::string temp);
};
Compiler::Compiler(int key_len,std::string *key_table){
Compiler::key_table = key_table;
Compiler::key_len = key_len;
Compiler::singalword = "+-*(){};,:";
Compiler::doubleword = "><=!!";//需要使用超前搜索
Compiler::operator_table = std::vector<std::string>{
"+", "-","*","/","=",">","<",">=","<=","!="};
Compiler::limitation_table = std::vector<std::string>{
",", ";","{","}","(",")"};
}
int Compiler::lookup(std::string temp){
int j=0;
for(auto i=key_table;j<Compiler::key_len;i++,j++){
if((*i)==temp){
//temp是保留字
return 0;
}
}
return 1;
}
bool Compiler::isOperator(std::string temp){
for(auto i=Compiler::operator_table.begin();i!=Compiler::operator_table.end();i++){
if((*i)==temp){
return true;
}
}
return false;
}
bool Compiler::isLimitation(std::string temp){
for(auto i=Compiler::limitation_table.begin();i!=Compiler::limitation_table.end();i++){
if((*i)==temp){
return true;
}
}
return false;
}
void Compiler::begin_compiler(std::string fin,std::string fout){
char c;
std::ifstream ifile(fin,std::ios::in);//打开fin文件
std::ofstream ofile(fout,std::ios::out);//打开fin文件
if (!ifile){
std::cout<<"输入文件打开失败!"<<std::endl;
}
if (!ofile){
std::cout<<"输出文件打开失败!"<<std::endl;
}
ifile>>c;
while (!ifile.eof()){
while(c==' '||c=='\n'||c=='\r'||c=='\t') ifile>>c;//处理空格与无意义字符
if(isalpha(c)){
//字母开头
std::string temp="";
temp = temp + c;
ifile.get(c);
while (!ifile.eof()&&(isdigit(c)||isalpha(c))){
temp = temp + c;
ifile.get(c);
}
if(!lookup(temp)){
//temp是保留字
table.insert(std::pair<std::string,int>(temp,1));//将(value,type)存入标识符表
ofile<<"("<<1<<","<<temp<<")"<<std::endl;
}else{
//temp是标识符
table.insert(std::pair<std::string,int>(temp,2));//将(value,type)存入标识符表
ofile<<"("<<2<<","<<temp<<")"<<std::endl;
}
}else if(isdigit(c)){
//数字开头
std::string temp="";
temp = temp + c;
ifile.get(c);
while (!ifile.eof()&&isdigit(c)){
temp = temp + c;
ifile.get(c);
}
table.insert(std::pair<std::string,int>(temp,3));//将(value,type)存入标识符表
ofile<<"("<<3<<","<<temp<<")"<<std::endl;
}else if(Compiler::singalword.find(c)!=std::string::npos){
//一定为单字符单词
std::string temp="";
temp = temp + c;
if(isLimitation(temp)){
table.insert(std::pair<std::string,int>(temp,5));//temp为界符
ofile<<"("<<5<<","<<temp<<")"<<std::endl;
}
else if(isOperator(temp)){
table.insert(std::pair<std::string,int>(temp,4));//temp为运算符
ofile<<"("<<4<<","<<temp<<")"<<std::endl;
}
ifile.get(c);
}else if(Compiler::doubleword.find(c)!=std::string::npos){
//可能为双字符单词或单字符单词
std::string temp="";
temp = temp + c;
ifile.get(c);
if(ifile.eof()){
//到文件尾部,肯定是单字符
if(isLimitation(temp)){
table.insert(std::pair<std::string,int>(temp,5));//temp为界符
ofile<<"("<<5<<","<<temp<<")"<<std::endl;
}
else if(isOperator(temp)){
table.insert(std::pair<std::string,int>(temp,4));//temp为运算符
ofile<<"("<<4<<","<<temp<<")"<<std::endl;
}
break;
}
std::string temp1 = temp+c;
if(isOperator(temp1)){
//为双字符
table.insert(std::pair<std::string,int>(temp1,4));//temp为双字符运算符
ofile<<"("<<4<<","<<temp1<<")"<<std::endl;
ifile.get(c);
}else{
table.insert(std::pair<std::string,int>(temp,4));//temp为单字符运算符
ofile<<"("<<4<<","<<temp<<")"<<std::endl;
}
}else{
//出错处理
ofile<<"(ERROR,"<<c<<")"<<std::endl;
ifile.get(c);
}
}
}
int main(){
int key_len;
std::string fin, fout, *key_table;
std::cout<<"是否自定义关键字:(y/n)";
char flag;
std::cin>>flag;
if((flag^'y')==0){
std::cout<<"请输入关键字数量:";
std::cin>>key_len;
key_table = new std::string[key_len];
for(int i=1;i<=key_len;i++){
std::cout<<"请输入关键字"<<i<<":";
std::cin>>key_table[i-1];
}
}else{
key_len = 9;
key_table = new std::string[key_len]{
"main","if","else","for","while","do","int","read","write"};
}
std::cout<<"请输入源文件地址:";
std::cin>>fin;
std::cout<<"请输入输出文件地址:";
std::cin>>fout;
Compiler *compiler = new Compiler(key_len,key_table);//制定编译的保留字表
(*compiler).begin_compiler(fin,fout);//编译文件
delete compiler;
delete[] key_table;
return 0;
}