S语言词法分析器设计

简介: 还有很多需要优化的地方,作为小白发出了也和大家一起交流下,这次我是分文件写的,因为考虑到以后的实验都用这一套代码,分文件写方便一点,用的是C++14标准

正题开始

最近老师让做一次实验,一直没有关注过,但是明天要验收了(危),所以今天开始新建文件夹,写的很急,还有很多需要优化的地方,作为小白发出了也和大家一起交流下,这次我是分文件写的,因为考虑到以后的实验都用这一套代码,分文件写方便一点,用的是C++14标准

compilerwork.h

首先是一个库文件,声明各种函数以及定义常量

//

// Created by NorthS on 2022/3/20.

//

#ifndef COMPILERW_COMPILERWORK_H

#define COMPILERW_COMPILERWORK_H

#include <bits/stdc++.h>

using namespace std;

/*

* 判断字符是否是数字

*/

bool isNumber(char a);

/*

* 判断字符是否为字母

*/

bool isAlp(char a);

/*

* 去除字符串头部空格

*/

string trim(string str);

/*

* 判断是否为保留字

*/

bool isKeyWords(string str);

/*

* 判断标识符表中是否已存在该标识符

*/

bool isExistInr(vector<string> ins,string str);

/*

* 查找标识符在标识符中的位置

*/

int searchInrInInrs(vector<string> ins,string str);

/*

* 查找常数在常数表中的位置

*/

int searchCsatInCsats(vector<string> csats,string str);

#endif //COMPILER_COMPILERS_H

handle.cpp

这个handle里面是各种函数的实现

//

// Created by NorthS on 2022/3/20.

//

#include "compilerwork.h"

//保留字表

vector<string> words={"int","char","float","void","const","for","if","else","then","while","switch","break","begin","end"};

bool isNumber(char a) {

   return a >= '0' && a <= '9';

}

bool isAlp(char a) {

   return a >= 'a' && a < 'z' || a >= 'A' && a <= 'Z';

}

string trim(string str) {

   str.erase(0, str.find_first_not_of(" \t"));

   return str;

}

bool isKeyWords(string str){

   for(int i=0;i<words.size();i++){

       if(!words[i].compare(str)){

           return true;

       }

   }

   return false;

}

bool isExistInr(vector<string> ins,string str){

   for(int i=0;i<ins.size();i++){

       if(!ins[i].compare(str)){

           return true;

       }

   }

   return false;

}

int searchInrInInrs(vector<string> ins,string str){

   for(int i=0;i<ins.size();i++){

       if(!ins[i].compare(str)){

           return i;

       }

   }

}

int searchCsatInCsats(vector<string> csats,string str){

   for(int i=0;i<csats.size();i++){

       if(!csats[i].compare(str)){

           return i;

       }

   }

}

main.cpp

主函数,感觉耦合度太高了(别忘了换路径!!!)


#include "compilerwork.h"

//二元式

string mode;

//标识符表

vector<string> infrs;

//常数表

vector<string> constant;

//注释记录表

string noteErr[1000];

//非法字符记录表

string charError;

int main() {

   ifstream in("D:\\CLion\\CProjects\\CompilerW\\data.txt");

   string line;

   int i=0;

   int lineNum=0;

   if(in){

       while(getline(in,line)){

           line=trim(line);

           lineNum++;

           i=0;

           string strs="";

           while(i<line.length()){

               if(line[i]=='/'){

                   if(line[i+1]=='/'){

                       break;

                   }

                  //  /*的情况

                   if(line[i+1]=='*'){

                       noteErr[lineNum]="/*";

                   }

               }

              // */的情况

               if(line[i]=='*'){

                   if(line[i+1]=='/'){

                       int flag=1;

                      //删除noteErr容器中所有他前面的/* 也不添加*/

                       for(int k=lineNum;k>=0;k--){

                           if(!noteErr[k].compare("/*")){

                               noteErr[k]="";

                               flag=0;

                           }

                       }

                      //状态没变,说明容器里没有/* 添加*/

                       if(flag){

                           noteErr[lineNum]="*/";

                       }

                   }

               }

               if(isAlp(line[i])){

                   strs="";

                   while(i<line.length()&&(isAlp(line[i]) || isNumber(line[i]))){

                       strs.append(1,line[i]);

                       i++;

                   }

                  // 是保留字

                   if(isKeyWords(strs)){

                       mode.append(1,'(');

                       mode.append(strs);

                       mode.append(",-)");

                   }else{//不是保留字(标识符)

                      // 如果标识符表里没有该标识符则添加标识符

                       if(!isExistInr(infrs,strs)){

                           infrs.push_back(strs);

                       }

                       int place=searchInrInInrs(infrs,strs);

                       mode.append("(id,");

                       mode.append(to_string(place));

                       mode.append(")");

                   }

               }

               if(isNumber(line[i])){

                   strs="";

                   while(i<line.length()&&(isNumber(line[i])||line[i]=='.')){

                       strs.append(1,line[i]);

                       i++;

                   }

                   constant.push_back(strs);

                   int place=searchCsatInCsats(constant,strs);

                   mode.append("(num,");

                   mode.append(to_string(place));

                   mode.append(1,')');

               }

               if((!isNumber(line[i]))&&(!isAlp(line[i]))){

                   switch(line[i]){

                       case '(':

                           mode.append("(");

                           mode.append(1,line[i]);

                           mode.append(",-)");

                           break;

                       case ')':

                           mode.append("(");

                           mode.append(1,line[i]);

                           mode.append(",-)");

                           break;

                       case '+':

                           if(line[i+1]!='='){

                               mode.append("(");

                               mode.append(1,line[i]);

                               mode.append(",-)");

                           }

                          // +=的情况

                           if(line[i+1]=='='){

                               mode.append("(");

                               mode.append(1,line[i]);

                               mode.append(1,line[i+1]);

                               mode.append(",-)");

                               i++;

                           }

                           break;

                       case '-':

                           if(line[i+1]!='='){

                               mode.append("(");

                               mode.append(1,line[i]);

                               mode.append(",-)");

                           }

                          // -=的情况

                           if(line[i+1]=='='){

                               mode.append("(");

                               mode.append(1,line[i]);

                               mode.append(1,line[i+1]);

                               mode.append(",-)");

                               i++;

                           }

                           break;

                       case '*':

                          // 排除*/ /* *= 的情况

                           if(line[i-1]!='/'&&line[i+1]!='/'&&line[i+1]!='='){

                               mode.append("(");

                               mode.append(1,line[i]);

                               mode.append(",-)");

                           }

                          // *=的情况

                           if(line[i+1]=='='){

                               mode.append("(");

                               mode.append(1,line[i]);

                               mode.append(1,line[i+1]);

                               mode.append(",-)");

                               i++;

                           }

                           break;

                       case '/':

                          //排除 // /* /= */

                           if(line[i+1]!='/'&&line[i+1]!='*'&&line[i+1]!='='&&line[i-1]!='*'){

                               mode.append("(");

                               mode.append(1,line[i]);

                               mode.append(",-)");

                           }

                          // /= 的情况

                           if(line[i+1]=='='){

                               mode.append("(");

                               mode.append(1,line[i]);

                               mode.append(1,line[i+1]);

                               mode.append(",-)");

                               i++;

                           }

                           break;

                       case '=':

                          // =的情况 else: ==的情况

                           if(line[i+1]!='='){

                              //cout<<line[i]<<endl;

                               mode.append("(");

                               mode.append(1,line[i]);

                               mode.append(",-)");

                           }

                           else{

                              //cout<<line[i]+line[i+1]<<endl;

                               mode.append("(relop,");

                               mode.append(1,line[i]);

                               mode.append(1,line[i+1]);

                               mode.append(")");

                               i++;

                           }

                           break;

                       case '<':

                          // <=的情况

                           if(line[i+1]=='='){

                               mode.append("(relop,");

                               mode.append(1,line[i]);

                               mode.append(1,line[i+1]);

                               mode.append(")");

                               i++;

                           }else{

                               mode.append("(relop,");

                               mode.append(1,line[i]);

                               mode.append(")");

                           }

                           break;

                       case '>':

                          // >=的情况

                           if(line[i+1]=='='){

                               mode.append("(relop,");

                               mode.append(1,line[i]);

                               mode.append(1,line[i+1]);

                               mode.append(")");

                               i++;

                           }else{

                               mode.append("(relop,");

                               mode.append(1,line[i]);

                               mode.append(")");

                           }

                           break;

                       case ';':

                           mode.append("(");

                           mode.append(1,line[i]);

                           mode.append(",-)");

                           break;

                       case ',':

                           mode.append("(");

                           mode.append(1,line[i]);

                           mode.append(",-)");

                           break;

                       case '[':

                           mode.append("(");

                           mode.append(1,line[i]);

                           mode.append(",-)");

                           break;

                       case ']':

                           mode.append("(");

                           mode.append(1,line[i]);

                           mode.append(",-)");

                           break;

                       case '%':

                           mode.append("(");

                           mode.append(1,line[i]);

                           mode.append(",-)");

                           break;

                       case '!':

                          // !=的情况

                           if(line[i+1]=='='){

                               mode.append("(relop,");

                               mode.append(1,line[i]);

                               mode.append(")");

                               i++;

                           }

                           break;

                       default:

                           if(line[i]!=' '&&line[i]!='\0'){

                               charError.append("非法字符");

                               charError.append(1,line[i]);

                               charError.append(":"+to_string(lineNum)+"\n");

                               }

                           break;

                   }

                   i++;

               }

           }

       }

      //输出二元式

       cout<<"二元式如下:"<<endl;

       cout<<mode<<endl;

      //输出标识符表

       cout<<"标识符表如下:"<<endl;

       for(int i=0;i<infrs.size();i++){

           cout<<i<<"-----"<<infrs[i]<<endl;

       }

      //输出常数表

       cout<<"常数表如下:"<<endl;

       for(int i=0;i<constant.size();i++){

           cout<<i<<"-----"<<constant[i]<<endl;

       }

      //输出错误信息

       cout<<"错误信息如下:"<<endl;

       int errst=0;

       int errsts=0;

      //错误行数

       int errline=0;

       int errlines=0;

       for(int k=0;k<=lineNum;k++){

           if(!noteErr[k].compare("/*")){

               errline=k;

               errst=1;

              //break;

           }

           if(!noteErr[k].compare("*/")){

               errlines=k;

               errsts=1;

              //break;

           }

       }

       if(errst==1){

           cout<<"注释未结束:"<<errline<<endl;

       }

       if(errsts==1){

           cout<<"注释未开始:"<<errlines<<endl;

       }

       if(errst==0&&errsts==0){

           cout<<"无"<<endl;

       }

       cout<<charError<<endl;

   }else{

       cout<<"没有找到该文件!"<<endl;

       exit(0);

   }

   return 0;

}

测试数据

这也是实验中给出的测试数据

//aa.c

void  aa( )

begin

   float  rate,circle;

   rate=3;

   circle=3.14*rate*rate;

end

可优化

  1. 二元式拼接过程那可以定义成一个函数
  2. 对识别出的数字字符串进行转化,判断其是否是”真“数字
  3. 对于每一种字符串的判别可以单独出来
  4. 对注释的判别不用太过复杂,我这有点类似于语法分析了(老师指正)
  5. 还有什么想法欢迎一起交流!

 


目录
相关文章
|
4月前
|
JavaScript 前端开发 安全
什么是编程语言分类中的弱类型语言
什么是编程语言分类中的弱类型语言
|
自然语言处理 前端开发 算法
编译原理 (二)词法分析、语法分析、语义分析以及中间代码生成器的基本概念
编译原理 (二)词法分析、语法分析、语义分析以及中间代码生成器的基本概念
697 0
|
25天前
|
Linux C# C语言
C 语言与嵌入汇编
C 语言与嵌入汇编
16 0
|
4月前
根据文法求对应的语言
根据文法求对应的语言
36 0
|
自然语言处理 数据库连接
编译原理(五) 语言的定义
编译原理(五) 语言的定义
125 0
|
12月前
|
自然语言处理 IDE 开发工具
【编译原理】第三章语法分析
【编译原理】第三章语法分析
编译原理(四) 语言及其文法的基本概念
编译原理(四) 语言及其文法的基本概念
|
自然语言处理 C语言 C++
编译原理 实验二:词法分析器的手动实现(基于状态机的词法分析器)
编译原理 实验二:词法分析器的手动实现(基于状态机的词法分析器)
943 0
编译原理 实验二:词法分析器的手动实现(基于状态机的词法分析器)
|
自然语言处理 Go
Go语言学习编程实践:实现简易计算器(包含词法器、语法树构建)
Go语言学习编程实践:实现简易计算器(包含词法器、语法树构建)
146 0