编译原理---词法分析器的简单实现(c++)

什么是词法分析器

简单来说,词法分析器,就是将用户输入的代码(一个个字符)通过某种方式拼接成有意义的一个个字符片段,什么是有意义呢?不同语言的定义不太相同,但大体来说,有意义表示这五类:关键字、标识符、数字串、运算符和分隔符、空白字符。拼接的方式多种多样,可以使用DFA也可以单纯的进行字符的拼接。

大致思路

这里就使用字符的拼接,由于这个程序比较简单,就每次判断下一个字符是字母、数字或者下划线或者是其他字符,比如第一个字符是字母数字或下划线,那就一直向下加,直至加到不是字母数字或下划线,然后一直加不是字母数字或下划线。虽然这种思路有一点点小的bug,但对付大部分数据还是可以的。

实验具体内容及要求

实验目的

设计、编制并调试一个简单语言CP(Compiler Principle)的词法分析程序,加深对词法分析原理的理解。

实验内容

1. CP语言的词法

(1) 关键词: begin  end  if   then  else   for  while  do  and  or  not

注意:所有关键词都是小写的。

(2) 标识符ID,与标准C语言一致,即:以下划线或字母开头的字母数字下划线组成的符号串。

(3)无符号整数NUM:数字串

(4)运算符和分界符: +、-、*、/、>、<、=、:=、>=、<=、<>、++、--、(、)、; 、 #

注意::=表示赋值运算符、#表示注释开始的部分,;表示语句结束,<>表示不等关系

(5) 空白符包括空格、制表符和换行符,用于分割ID、NUM、运算符、分界符和关键词,词法分析阶段要忽略空白符。

2. 说明

(1)CP语言是大小写敏感语言;

(2)字母为a-zA-Z,数字为0-9;

(3)学有余力同学可以在上述词法要求基础上进行扩充和改造;

(4)每行代码中从#开始的部分为注释部分(参考python语法)

3. 设计要求

(1) 给出各类单词符号的分类编码(可以根据自己程序的需要来给各种类别单词编码,给每个词法单位一个编码,也可以给一个类别里所有符号都编同一个编码)。

(2) 词法分析程序应该能发现输入串中的错误

(3) 词法分析作为单独一遍,将词法分析程序输出的二元式序列保存为中间文件形式【也可以在屏幕窗口直接输出】

 

实验要求

1. 写出程序框图、设计过程、主要数据结构等。

2.写出程序源代码,并调试通过,输出实验结果。

3.完成实验报告及总结【按实验教学的PDF文件要求撰写和提交】。

注意:实现语言不限,用你最熟悉或最感兴趣的语言来实现即可

源代码

首先给关键字进行以下标号

其中1.cpp为词法分析器实现代码,yuan.txt为需要处理的源代码,out.txt为处理输出结果

GitHub地址

#include<bits/stdc++.h>
using namespace std; 
string str;         //源程序
int flag=0;         //注释
map<string,int> mmap,guan;      //存放所有关键字和出现的关键字
set<string> vec;                 //错误字符
set<string> v;                   //无符号整数
set<string> biao_zhi;            //标识符
string word[]={
"",
"#",   
"begin",
"end",
"if",
"then",
"else",
"for",
"while",
"do",
"and",
"or",
"not",
"+",
"-",
"*",
"/",
">",
"<",
"=",
":=",
">=",
"<=",
"<>",
"++",
"--",
"(",
")",
";" };

int check(char c){                     //检查是否为数字 字母 下划线
    if(c=='_'||(c>='0'&&c<='9')||((c>='a'&&c<='z')||(c>='A'&&c<='Z')))
        return 1;
    return -1;
}

void init(){        //初始化map(单词符号和种别码一一对应关系)
    for(int q=1;q<=28;q++){
        mmap.insert(map<string,int>::value_type(word[q],q));
    }
}

void yu_chu_li(){   //预处理,去掉空白符
    string s="";
    for(int q=0;q<str.length();q++){
        if(str[q]=='\n'||str[q]=='\t')
            s+=" ";
        else 
            s+=str[q];
    }
    str.assign(s);
}

bool biao(string s){        //标识符匹配
    bool flag=true;
    if(s[0]=='-'||((s[0]>='a'&&s[0]<='z')||(s[0]>='A'&&s[0]<='Z'))){
        for(int q=1;q<s.length();q++){
            if(s[q]=='-'||((s[q]>='a'&&s[q]<='z')||(s[q]>='A'&&s[q]<='Z'))){}
            else{
                flag=false;
                break;
            }
        }
    }
    else flag=false;
    return flag;
}

bool dfa(string s){         //无符号整数匹配
    bool flag=true;
    for(int q=0;q<s.length();q++){
        if(s[q]>='0'&&s[q]<='9') {}
        else{
            flag=false;
            break;
        }
    }
    return flag;
}

int main(){
    guan.clear();
    vec.clear();
    str="";
    ofstream out("out.txt");
    ifstream data("yuan.txt");
    string line;
    while(!data.eof()){
        getline(data,line);
        for(int q=0;q<line.length();q++){
            if(line[q]=='#') { guan.insert(map<string,int>::value_type("#",mmap["#"])); break; }          //去掉注释并添加#关键字
            str+=line[q];
        }
    }
    yu_chu_li();
    init();
    string s1="",s2="";
    int in=1;                   //为1识别关键字   -1其他
    str+="  ";
    for(int q=0;q<str.length();q++){
        if(str[q]==' '){
            goto part;
        }
        if(s1.length()==0){
            if(s2.length()!=0){
                in=check(s2[0]);
                s1+=s2[0];
                s2="";
            }
            else
                in=check(str[q]);
        }
        if(check(str[q])==in){
            s1+=str[q];
        }
        else{
            s2+=str[q];
        }
        part:
        if(in!=check(str[q])){
            if(s1.length()>0){
                if(mmap[s1]!=0){        //是否为关键字
                    guan.insert(map<string,int>::value_type(s1,mmap[s1]));
                }
                else if(biao(s1)){      //是否为标识符
                    biao_zhi.insert(s1);
                }
                else if(dfa(s1)){       //是否为无符号整型常量
                    v.insert(s1);
                }
                else{                   //错误字符
                    vec.insert(s1);
                }
            }
            s1="";
        }
    }
    cout<<"success"<<endl;
    if(vec.size()!=0) out<<vec.size()<<" errors"<<endl;
    out<<"------关键字------"<<endl;
    for(map<string,int>::iterator it=guan.begin();it!=guan.end();it++){     //关键字输出
        out<<"<"<<it->first<<","<<it->second<<">"<<endl;
    }
    out<<"------标识符------"<<endl;
    for(set<string>::iterator it=biao_zhi.begin();it!=biao_zhi.end();it++){  //标识符输出
        out<<"<标识符,"<<*it<<">"<<endl;
    }
    out<<"------无符号整型常量------"<<endl;
    for(set<string>::iterator it=v.begin();it!=v.end();it++){            //无符号整数输出
        out<<"<无符号整型常量,"<<*it<<">"<<endl;
    }
    out<<"------错误------"<<endl;
    for(set<string>::iterator it=vec.begin();it!=vec.end();it++){        //错误输出
        out<<"<错误,"<<*it<<">"<<endl;
    }
    out.close();
    data.close();
    return 0;
}

 

  • 6
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值