编译原理:词法分析器实现

用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;
}

猜你喜欢

转载自blog.csdn.net/qq_45931661/article/details/123944148