正题开始
最近老师让做一次实验,一直没有关注过,但是明天要验收了(危),所以今天开始新建文件夹,写的很急,还有很多需要优化的地方,作为小白发出了也和大家一起交流下,这次我是分文件写的,因为考虑到以后的实验都用这一套代码,分文件写方便一点,用的是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
可优化
- 二元式拼接过程那可以定义成一个函数
- 对识别出的数字字符串进行转化,判断其是否是”真“数字
- 对于每一种字符串的判别可以单独出来
- 对注释的判别不用太过复杂,我这有点类似于语法分析了(老师指正)
- 还有什么想法欢迎一起交流!