词法分析(C++实现)

  • 词法分析实验设计思想及算法

本实验采用的基本思想是根据C++语言的基本状态集,根据各个状态的转移条件构造各个判断逻辑,将程序运行的状态加以区别。源程序来源采用文件导入的方式,对输入源程序的文件进行逐行的词法分析。支持对标识符、关键字、整数、浮点数、分界符、运算符等识别。对于读取的每一行代码保存在字符数组buf [120]中,设置起点指示器start(数组下标索引)和搜索指示器end(数组下标索引),其中start指向当前正在识别单词的开始位置(指向新单词的首字符),而end用于先前搜索寻找单词的终点。识别每一个单词依赖于其相应的词法分析的状态转换图。对于关键字,不专设对应的转换图,把其存放在字符串数组中(保留字表)。当转化图识别出一个标识符时,就去查这张表,确定是否为关键字。具体实现思路见如下分析。

  • 主程序设计基本思路

按照如下状态转移图的形式,对目标分析文件中的内容进行分析:

                                                           图1.1  状态转换图

按照上图所示,采用超前搜索的核心思路进行分析。每读取一行代码后后,默认进入
状态 0,超前搜索指针 end 向前搜索, 按照以下分析逻辑依次序进行:

  1. 如果识别到空格,start索引和end索引分别先前移动(即加1)。
  2. 如果连续识别的都是字母,end指向运算符或分界符时识别结束,获取索引start和end-1之间的字符串,此时应该对读取的字符串与关键字表进行对比,如果是关键字,则将其返回。否则,返回标识符。
  3. 如果start指向”_”或字母,end如果识别数字或字母,同时也向前移动,此间如果遇到非法字符(不包括字母、数字、运算符和分界符),则标志变量flag = 1,否则为0。标志变量为1表示为非法标识符,同时end继续前进直到识别分割符为止(运算符和分界符)。然后获取索引start和end-1之间的字符串,如果flag =1,则返回非法标识符,否则,返回此标识符。

注:在算法实现上可以把标识符的识别和关键字的识别放在一起。即可在设置一个标记变量isKey = 0,其识别状态见如下表格1.1:

                                                                                 表1.1

isKey

flag

状态

1

0/1

关键字

0

0

标识符

0

1

非法标识符

        4. 果start指向数字,end连续的识别字符,最后end指向分割符。其中如果end有识别非法字符,则isInt = 0,否则isInt =1 ;,见 如下表1.2

                                                                                 表1.2

isInt

状态

0

非法整数

1

整数

     5.如果start指向数字,end连续的识别数字,之后识别小数点,再连续识别数字,最后end指向分割符。再这期间如果识别非法字符,则报错。

     6.对于运算符、分界符正常识别即可。

程序逻辑图如下:

                                           图1.2

  • 代码实现
#ifndef _READFILE_
#define _READFILE_

#include <iostream>
#include <Cstdio>
#include <vector>
#include <Cstring>

using namespace std;

 class Table{
public:
    string array[100];
    int length;

    Table(){
        length = 0;
    }
};

//定义关键字容器
Table key;
//定义界定符容器
Table delimiter;
//定义算术运算符容器
Table arithmeticOperator;
//定义逻辑运算符容器
Table logicalOperator;
//定义关系运算符容器
Table relationOperator;

void loadFile(){

    int N =5;
    string fileName[N] = {"key.txt","delimiter.txt","arithmeticOperator.txt","logicalOperator.txt","relationOperator.txt"};
    Table* tableName[N] = {&key,&delimiter,&arithmeticOperator,&logicalOperator,&relationOperator};
    //定义文件指针
    FILE * fp;
    //保存字符串的缓冲数组
    char buf[30];
    char temp[50];
    for(int i=0;i < N;i++){
        strcpy(temp,fileName[i].c_str());
        if((fp = fopen(temp,"r"))!= NULL )
        {
            int count = 0;
            while(!feof(fp)){
                fscanf(fp,"%s",buf);
                tableName[i]->array[count] = buf;
                count++;
            }
            tableName[i]->length = count+1;
            fclose(fp);
        }
        else{
            cout<<"文件打开失败!"<<endl;
        }

    }

}

#endif // _READFILE_

 

#include <iostream>
#include <fstream>
#include <string>
#include <Cstdio>
#include <iomanip>
#include "readFile.h"

#define FILENAME "code.txt"
#define N  200

using namespace std;

//保存代码
string code[N];
//保存代码行数
int lineCount = 0;
//加载代码
void loadCode();
//判断字符是否为字母
bool isLetter(char var);
//判断字符是否为数字
bool isDigit(char var);
//判断一个字符是否为分割符
bool isBoundary(char var);
//检测一个字符是否为分界符
bool isDelimiter(char var);
//核心函数,对字符串进行循环处理
void wordAnalyse();

int main()
{
    loadFile();
    loadCode();
    wordAnalyse();
    return 0;
}
//加载代码
void loadCode(){
    ifstream fin;
    string tempStr;
    fin.open(FILENAME,ifstream::in);
    while(!fin.eof()){
        getline(fin,tempStr);
        lineCount +=1;
        code[lineCount] = tempStr;
    }
}
//判断字符是否为字母
bool isLetter(char var){
    //强制转换
    int ascii = (int) var;
    bool bo = ((ascii>=97) && (ascii<=122)) || ((ascii>=65) && (ascii<=90));
    if(bo){
        return true;
    }
    else{
        return false;
    }
}
//判断字符是否为数字
bool isDigit(char var){
    //强制转换
    int ascii = (int) var;
    bool bo = ((ascii>=48) && (ascii<=57));
    if(bo){
        return true;
    }
    else{
        return false;
    }
}
//判断一个字符是否为分割符
bool isBoundary(char var){
    //不是字母、数字、下划线、小数点可认为是分割符
    if((!isLetter(var)) &&(!isDigit(var))&& (var != '_') && (var!= '.') && (var!= '$') && (var!= '@')&& (var!= '#')&& (var!= '&')){
        return true;
    }
    return false;
}
//检测一个字符是否为分界符
bool isDelimiter(char var){
    //将单个字符转化为字符串
    char buf[2] = {var,0};
    string str(buf);
    for(int i =0;i<delimiter.length;i++){
        if(delimiter.array[i] == str){
            return true;
        }
    }
    return false;
}
//核心函数,对字符串进行循环处理
void wordAnalyse(){
    cout<<setw(20)<<"单词"<<setw(20)<<"二元序列"<<setw(20)<<"类 型"<<setw(30)<<"位置(行,列)"<<endl;
    string str;
    char buf[150] ={0};
    char temp[60];
    //定义字符首尾索引
    int start = 0;
    int end = 0;
    //分别对每行代码进行处理
    for(int i=1;i<=lineCount;i++){
        //将字符串转化成字符数组
        strcpy(buf,code[i].c_str());
        //定义字符首尾索引
        start = 0;
        end = 0;
        //保存列数
        int position =0;
        while((int)buf[start] != 0){
            //去掉开始空白符号
            while((int)buf[start] == 32){
                //地址加1
                start++;
                end++;
            }
            bool isKey = true;
            bool flag = false;
            //检测是否为关键字或标识符,首字符是字母或下划线
            if(isLetter(buf[end]) || buf[end] == '_'){
                //如果是下划线,那么一定不是关键字
                if(buf[end] == '_'){
                    //标记不是关键字
                    isKey = false;
                }
                //否则可能是关键字、标识符,也可能是非法标识符

                //字符指针向前移1位
                end++;
                //使end指向分割符
                while(!isBoundary(buf[end])){
                    //如果end指向非法字符(不是字母和数字),则flag标记为1
                    if(!isLetter(buf[end]) && !isDigit(buf[end])){
                        flag = true;
                    }
                    end++;
                }
                str = code[i].substr(start,end-start);
                position++;
                //如果isKey = false,则一定不是关键字
                if(!isKey){
                    //如果flag = false,则一定是标识符
                    if(!flag){
                        cout<<setw(20)<<str<<setw(20)<<(string)"("+"2"+","+str+")"<<setw(20)<<"标识符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                    }
                    //否则为非法标识符
                    else{
                        cout<<setw(20)<<str<<setw(20)<<"Error"<<setw(20)<<"Error"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                    }
                }
                //否则可能是关键字、标识符、非法标识符
                else{
                    //判断是否为关键字
                    for(int j=0;j<key.length;j++){
                        if(str.compare(key.array[j]) == 0){
                            cout<<setw(20)<<str<<setw(20)<<(string)"("+"1"+","+str+")"<<setw(20)<<"关键字"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                            isKey = false;
                            break;
                        }
                    }
                    //flag  == false,则为标识符
                    if(isKey == true && flag == false)
                    {
                        cout<<setw(20)<<str<<setw(20)<<(string)"("+"2"+","+str+")"<<setw(20)<<"标识符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                    }
                    //为非法标识符
                    else if(isKey == true && flag == true){
                        cout<<setw(20)<<str<<setw(20)<<"Error"<<setw(20)<<"Error"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                    }
                    else{
                        //空语句
                    }
                }
            }
            //检测是否为整数或浮点数
            else if(isDigit(buf[end])){
                //字符指针向前移1位
                end++;
                while(isDigit(buf[end])){
                    end++;
                }
                //如果下一个是分割字符,则识别完成(整数识别)
                if(isBoundary(buf[end])){
                    str = code[i].substr(start,end-start);
                    position++;
                    cout<<setw(20)<<str<<setw(20)<<(string)"("+"7"+","+str+")"<<setw(20)<<"常数"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;

                }
               //不是分割符
               else{
                    //如果是小数点
                    if((int)buf[end] == '.'){
                        //字符指针向前移1位
                        end++;
                        while(isDigit(buf[end])){
                            end++;
                        }
                        //如果下一个是分割字符,则识别完成(浮点数识别)
                        if(isBoundary(buf[end])){
                            str = code[i].substr(start,end-start);
                            position++;
                            cout<<setw(20)<<str<<setw(20)<<(string)"("+"7"+","+str+")"<<setw(20)<<"常数"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                        }
                        //不是分隔符,则继续识别
                        else{
                            while(!isBoundary(buf[end])){
                                end++;
                            }
                            str = code[i].substr(start,end-start);
                            position++;
                            cout<<setw(20)<<str<<setw(20)<<"Error"<<setw(20)<<"Error"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                        }
                    }
                    //不是小数点
                    else{
                        while((isLetter(buf[end])) || (isDigit(buf[end]))|| (buf[end] == '_') ){
                                end++;
                        }
                        str = code[i].substr(start,end-start);
                        position++;
                        cout<<setw(20)<<str<<setw(20)<<"Error"<<setw(20)<<"Error"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                        end++;
                    }
               }

            }
            //检测是否为"("或")"或"{"或"}"或","或";"
            else if(isDelimiter(buf[end])){
                //字符指针向前移1位
                position++;
                cout<<setw(20)<<buf[end]<<setw(20)<<(string)"("+"6"+","+buf[end]+")"<<setw(20)<<"分界符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                end++;
            }
            //检测是否为算术运算符+,-,*,%,/,++,--,+=,-=
            else if(((int)buf[end] == 43) ||((int)buf[end] == 45) ||((int)buf[end] == 42) ||((int)buf[end] == 37)||((int)buf[end] == 47)){
                position++;
                if((int)buf[end] == 43){
                    //字符指针向前移1位
                    end++;
                    if((int)buf[end] == 43){
                        cout<<setw(20)<<"++"<<setw(20)<<(string)"("+"3"+","+"++"+")"<<setw(20)<<"算术运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                        //字符指针向前移1位
                        end++;
                    }
                    else if((int)buf[end] == 61){
                        cout<<setw(20)<<"+="<<setw(20)<<(string)"("+"3"+","+"+="+")"<<setw(20)<<"算术运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                        //字符指针向前移1位
                        end++;
                    }
                    else{
                        cout<<setw(20)<<"+"<<setw(20)<<(string)"("+"3"+","+"+"+")"<<setw(20)<<"算术运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                    }
                }
                else if((int)buf[end] == 45){
                    //字符指针向前移1位
                    end++;
                    if((int)buf[end] == 45){
                        cout<<setw(20)<<"--"<<setw(20)<<(string)"("+"3"+","+"--"+")"<<setw(20)<<"算术运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                        //字符指针向前移1位
                        end++;
                    }
                    else if((int)buf[end] == 61){
                        cout<<setw(20)<<"-="<<setw(20)<<(string)"("+"3"+","<<"-="<<")"<<setw(20)<<"算术运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                        //字符指针向前移1位
                        end++;
                    }
                    else{
                        cout<<setw(20)<<"-"<<setw(20)<<(string)"("+"3"+","+"-"+")"<<setw(20)<<"算术运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                    }
                }
                else{
                    cout<<setw(20)<<buf[end]<<setw(20)<<(string)"("+"3"+","+buf[end]+")"<<setw(20)<<"算术运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                    //字符指针向前移1位
                    end++;
                }
            }
            //检测关系运算符<,<=,=,==,>,>=,!=,,,(先判断>,<,=,!)
            else if(((int)buf[end] == 62) ||((int)buf[end] == 60) ||((int)buf[end] == 61) ||((int)buf[end] == 33)){
                position++;
                //判断首字符是否为">"
                if((int)buf[end] == 62){
                    end++;
                    //判断是否为"="
                    if((int)buf[end] == 61){
                        cout<<setw(20)<<">="<<setw(20)<<(string)"("+"5"+","+">="+")"<<setw(20)<<"关系运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                        //向前移一位,使其指向"="的下一个字符
                        end++;
                    }
                    else{
                        cout<<setw(20)<<">"<<setw(20)<<(string)"("+"5"+","+">"+")"<<setw(20)<<"关系运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                    }
                }
                //判断首字符是否为"<"
                else if((int)buf[end] == 60){
                     end++;
                     //判断是否为"="
                    if((int)buf[end] == 61){
                        cout<<setw(20)<<"<="<<setw(20)<<(string)"("+"5"+","+"<="+")"<<setw(20)<<"关系运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                        //向前移一位,使其指向"="的下一个字符
                        end++;
                    }
                    else{
                        cout<<setw(20)<<"<"<<setw(20)<<(string)"("+"5"+","+"<"+")"<<setw(20)<<"关系运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                    }
                }
                //判断首字符是否为"="
                else if((int)buf[end] == 61){
                    end++;
                    //判断是否为"="
                    if((int)buf[end] == 61){
                        cout<<setw(20)<<"=="<<setw(20)<<(string)"("+"5"+","+"=="+")"<<setw(20)<<"关系运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                        //向前移一位,使其指向"="的下一个字符
                        end++;
                    }
                    else{
                        cout<<setw(20)<<"="<<setw(20)<<(string)"("+"5"+","+"="+")"<<setw(20)<<"关系运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                    }
                }
                //否则为字符"!"
                else{
                    end++;
                    //判断是否为"="
                    if((int)buf[end] == 61){
                        cout<<setw(20)<<"!="<<setw(20)<<(string)"("+"5"+","+"!="+")"<<setw(20)<<"关系运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                        //向前移一位,使其指向"="的下一个字符
                        end++;
                    }
                    else{
                        cout<<setw(20)<<"!"<<setw(20)<<(string)"("+"4"+","+"!"+")"<<setw(20)<<"逻辑运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                    }
                }
            }
            //检测逻辑运算符和位运算符,检测"&&","||","!","&","^","|","~"
            else if(((int)buf[end] == 38) ||((int)buf[end] == 124)||((int)buf[end] == 94)||((int)buf[end] == 126)){
                position++;
                //判断是否为"&"
                if((int)buf[end] == 38){
                    //end指向下一位
                    end++;
                    if((int)buf[end] == 38){
                        cout<<setw(20)<<"&&"<<setw(20)<<(string)"("+"4"+","+"&&"+")"<<setw(20)<<"逻辑运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                        //向前移一位,使其指向"="的下一个字符
                        end++;
                    }
                    else{
                        cout<<setw(20)<<"&"<<setw(20)<<(string)"("+"8"+","+"&"+")"<<setw(20)<<"位运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                    }
                }
                //判断是否为"|"
                else if((int)buf[end] == 124){
                    //end指向下一位
                    end++;
                    if((int)buf[end] == 124){
                        cout<<setw(20)<<"||"<<setw(20)<<(string)"("+"4"+","+"||"+")"<<setw(20)<<"逻辑运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                        //向前移一位,使其指向"="的下一个字符
                        end++;
                    }
                    else{
                        cout<<setw(20)<<"|"<<setw(20)<<(string)"("+"8"+","+"|"+")"<<setw(20)<<"位运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                    }
                }
                //否则为"^"或"~"
                else {
                    cout<<setw(20)<<buf[end]<<setw(20)<<(string)"("+"8"+","+buf[end]+")"<<setw(20)<<"位运算符"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                    //向前移一位,使其指向"="的下一个字符
                    end++;
                }
            }
            //否则报错
            else{
                position++;
                cout<<setw(20)<<buf[end]<<setw(20)<<"Error"<<setw(20)<<"Error"<<setw(20)<<"("<<i<<","<<position<<")"<<endl;
                //字符指针向前移1位
                end++;
            }
            start = end;
        }

    }
}

注:arithmeticOperator.txt内容为:+   -   *   %   /   +=    -= (每个运算符占一行)

delimiter.txt内容为:;     ,     (      )      {      } (每个分割符占一行)

key.txtt内容为:asm    do   if   return   typedef   auto   double   inline   short   typeid   bool   dynamic_cast   int   signed   typename   break   else   long   sizeof   union   case    enum   mutable   static   unsigned   catch   explicit   namespace
static_cast   using   char   export   new   struct   virtual   class   extern   operator   switch   void   const   false   private
template   volatile   const_cast   float   protected   this   wchar_t   continue   for   public   throw   while   default   friend
register   true   delete   goto    reinterpret_cast    try  (每个关键词占一行)

logicalOperator.txt内容为:&&   ||   !   &   ^   |    ~ (每个逻辑运算符号占一行)

relationOperator.txt内容为:<   <=   =   ==    >    >=   !=(每个关系运算符号占一行)

code.txt的内容为:

if (i==1.a0ab)
{
    n++;
}
else
{
   n--;
}
%
int _va123r=7a;
double va$r = 56.0;
a = 7 &&8;
a +=2;
while (k | b ){
      return true;
}

  • 程序运行结果如下

 

 

  • 13
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值