更多内容关注博客新址https://song-10.gitee.io
说明
- 实验代码采用多文件的形式,即包含三部分:
lex.h
: 结构体以及类(成员函数等)的声明lex.cpp
: 类的成员函数的实现main.cpp
: 主调函数,主要为交互的逻辑代码
- 此外程序还要一个必须文件,即
lib_local.txt
, 用于存放用户新增字符(关键字、边界符、运算符) test.txt
为测试文件,即内容为编写的“c代码”
实验流程图
实验代码
lex.h
#include <iostream>
using namespace std;
#ifndef LEX_H
#define LEX_H
#define CURRENT_K 7; // 关键字当前最大下标
#define CURRENT_B 20; // 分界符当前最大下标
#define CURRENT_C 9; //算数运算符当前最大下标
// 存储字符
struct t
{
int i;
int type; // 内部码
string value;
};
// 储存结果
struct result
{
string value; // 原字符
int type_num; // 类别编号
int type_code; // 类部码
string type; // 类别
int row; // 行号
int column; //列号
result *next;
};
class LEX
{
public:
LEX(); // 初始化关键字表、边界符表等
void add(int i,int type, char value[]); // 新增关键字,边界符以及运算符
void add2list(); // 将用户新增的关键字添加到字符表中
void help(); // 显示帮助
void scaner(string content,int len);
bool isLetter(char ch); // 判断是否为字母
bool isDigit(char ch); // 判断是否为数字
bool isKey(string ch); // 判断是否为关键字,成功匹配返回对应的数组下标,否则返回-1
int isDelimiter(char ch);//判断是否为分界符,成功匹配返回对应的数组下标,否则返回-1
int isOpreator(char ch); // 判断是否为运算符,成功匹配返回对应的数组下标,否则返回-1
void doNum(string value, int row, int column); // 处理常数
void doKey(string value, int row, int column); // 处理关键字
void doId(string value, int row, int column); // 处理标识符
void doDelimiter(int row, int column,int num); // 处理边界符
void doOpreator(int row, int column, int num); // 处理运算符
bool doOther(string value, int row, int column); // 处理关系符以及非法字符
void show(); // 打印结果
private:
t k[40],s[30];
// 数组容量比初始化定义的大,支持扩展
char input[20]; //输入缓冲,此处采用行缓冲即遇到换行符刷新缓冲区
result *res,*p;// 单链表存储结果
int k_num,c_num,b_num;//记录用户新增的关键字、分界符、运算符
};
#endif
lex.cpp
#include "lex.h"
#include<cstring>
result *res = new result;// 单链表存储结果
void LEX::show()
{
result *q;
q = res->next;
cout<<"value\t\ttype_num\ttype_code\ttpye\t\t\trow\t\tcolumn"<<endl;
do{
cout<<q->value<<"\t\t"<<q->type_num<<"\t\t"\
<<q->type_code<<"\t\t"<<q->type\
<<"\t"<<q->row<<"\t\t"<<q->column<<endl;
q = q->next;
}while(q);
}
bool LEX::doOther(string value, int row, int colum){
result *r = new result;
for(int i = 0; i<6 ;i++){
if(s[i].va