1 语法分析程序设计与实现
任选一种有代表性的语法分析方法,如算符优先法、递归下降法、LL(1)、 SLR(1)、LR(1)等,通过设计、编制、调试实现一个典型的语法分析程序,对 实验一所得扫描器提供的单词序列进行语法检查和结构分析,实现并进一步 掌握常用的语法分析方法。
选择对各种常见高级程序设计语言都较为通用的语法结构——算术表达式的一个简化子集——作为分析对象,根据如下描述其语法结构的 BNF 定义 G2[<算术表达式>],任选一种学过的语法分析方法,针对运算对象为无符号 常数和变量的四则运算,设计并实现一个语法分析程序。
2 语法结构范围及文法定义
G2[算术表达式>]: <算术表达式> → <项> |
<算术表达式>+<项> |
<算术表达式>-<项> <项> → <因式> |
<项>*<因式> |
<项>/<因式> <因式> → <运算对象> |
(<算术表达式>)
若将语法范畴<算术表达式>、<项>、<因式>和<运算对象>分别用 E、T、 F 和 i 代表,则 G2 可写成:
G2[E]:E → T | E+T | E-T
T → F | T*F | T/F
F → i | (E)
输入:由实验一输出的单词串,例如:UCON,PL,UCON,MU,ID ...
输出:若输入源程序中的符号串是给定文法的句子,则输出“RIGHT”, 并且给出每一步分析过程;若不是句子,即输入串有错误,则输出“ERROR”, 并且显示分析至此所得的中间结果,如分析栈、符号栈中的信息等,以及必 要的出错说明信息。
3 语法分析器设计
3.1 SLR(1)分析表
首先,我没有采用传统的二维数组的形势去构造分析表,原因如下:
①二维数组去构造的话,数据类型不好选择
②假定数据类型,例如:整型、字符型等,之后在语法分析过程中,新字符与文法中的字符对应起来较困难
所以,这次的建表过程,我采取了一种全新的图结构map,首先构建一个枚举类型的四种动作以及包括该动作序号的结构体
enum action{S,r,acc,error};//枚举四种动作,移进、规约、接受、拒绝
struct actionGo {
action action;
int s;//移进动作的编号
int r;//规约动作的编号
};
其次,建表过程中我采用了map<pair<int,char>,actionGo>类型的图结构,意在将表的结构联系紧密且容易分析。
class SLR {
public:
map<pair<int,char>,actionGo> actiontable;//action子表
map<pair<int,char>,int> gototable;//goto子表
vector<char> txttoken;//余留符号串
stack<int> now_num;//状态栈
stack<char> now_id;//符号
};
优点:
①:数据类型明确、直观,不需要为数据类型的对应匹配而花费精力
②:表中的表头以及各项都与文法中的符号一模一样,不需要额外去对应,节省了一部分空间
3.2 分析过程
首先,0状态入栈,’#’入栈,作为初始状态,开始移进第一个文本符号,移进之后首先判断是否是合法输入,若不是合法输入直接结束分析,若是合法输入则继续分析。通过当前符号和状态的联系,得出actionGo的一个实例ag,通过分析ag的动作(S,r,acc,error)继而执行下面的过程
移进动作(s):
当前状态入栈、当前符号入栈、将指针指向下一个文本信息
规约动作(r):
统计对应产生式右部的符号个数,按照统计的个数对应符号栈弹栈、状态栈弹栈,之后产生式左部入栈,通过栈顶状态和栈顶符号匹配新的GOTO状态,将GOTO状态入栈
接受动作(acc):
将分析结果flag=1,表示分析成功
拒绝动作(error):
将分析结果flag=0,表示分析失败
4 语法分析器程序设计
4.1 数据结构分析
本程序的数据结构有:
一个枚举类型的移进规约动作集合
enum action{S,r,acc,error};//枚举四种动作,移进、规约、接受、拒绝
struct actionGo {
action action;
int s;//移进动作的编号
int r;//规约动作的编号
};
产生式结构体(为了方便规约动作的操作):
struct V {//产生式的结构体
char left;
vector<char> right;
}v[ALL_V];
SLR的分析表:
class SLR {
public:
map<pair<int,char>,actionGo> actiontable;//action子表
map<pair<int,char>,int> gototable;//goto子表
vector<char> txttoken;//余留符号串
stack<int> now_num;//状态栈
stack<char> now_id;//符号
};
4.2 函数分析
产生式初始化函数:
void Init_V() {//初始化产生式
v[0].left = 'S',v[0].right.resize(1),v[0].right[0] = 'E';
v[1].left = 'E',v[1].right.resize(3),v[1].right[0]='E',v[1].right[1]='+',v[1].right[2]='T';
v[2].left = 'E',v[2].right.resize(3),v[2].right[0] = 'E',v[2].right[1]='-',v[2].right[2]='T';
v[3].left = 'E',v[3].right.resize(1),v[3].right[0] = 'T';
v[4].left = 'T',v[4].right.resize(3),v[4].right[0] = 'T',v[4].right[1] = '*',v[4].right[2] = 'F';
v[5].left = 'T',v[5].right.resize(3),v[5].right[0] = 'T',v[5].right[1] = '/',v[5].right[2] = 'F';
v[6].left = 'T',v[6].right.resize(1),v[6].right[0] = 'F';
v[7].left = 'F',v[7].right.resize(3),v[7].right[0] = '(',v[7].right[1] = 'E',v[7].right[2] = ')';
v[8].left = 'F',v[8].right.resize(1),v[8].right[0] = 'i';
}
填表函数(SLR1):
void fixtable(SLR &slr,actionGo &actiongo) {
slr.actiontable[make_pair(0,')')] = {error,0,0};
slr.actiontable[make_pair(0,'+')] = {error,0,0};
slr.actiontable[make_pair(0,'-')] = {error,0,0};
slr.actiontable[make_pair(0,'*')] = {error,0,0};
slr.actiontable[make_pair(0,'/')] = {error,0,0};
slr.actiontable[make_pair(0,'(')] = {S,4,-1};
slr.actiontable[make_pair(0,'#')] = {error,0,0};
slr.actiontable[make_pair(0,'i')] = {S,5,-1};
slr.actiontable[make_pair(1,'+')] = {S,6,-1};
slr.actiontable[make_pair(1,'-')] = {S,7,-1};
slr.actiontable[make_pair(1,'#')] = {acc,-1,-1};
slr.actiontable[make_pair(1,'(')] = {error,0,0};
slr.actiontable[make_pair(1,')')] = {error,0,0};
slr.actiontable[make_pair(1,'i')] = {error,0,0};
slr.actiontable[make_pair(1,'*')] = {error,0,0};
slr.actiontable[make_pair(1,'/')] = {error,0,0};
slr.actiontable[make_pair(2,')')] = {r,-1,3};
slr.actiontable[make_pair(2,'+')] = {r,-1,3};
slr.actiontable[make_pair(2,'-')] = {r,-1,3};
slr.actiontable[make_pair(2,'*')] = {S,8,-1};
slr.actiontable[make_pair(2,'/')] = {S,9,-1};
slr.actiontable[make_pair(2,'#')] = {r,-1,3};
slr.actiontable[make_pair(2,'(')] = {error,0,0};
slr.actiontable[make_pair(2,'i')] = {error,0,0};
slr.actiontable[make_pair(3,')')] = {r,-1,6};
slr.actiontable[make_pair(3,'+')] = {r,-1,6};
slr.actiontable[make_pair(3,'-')] = {r,-1,6};
slr.actiontable[make_pair(3,'*')] = {r,-1,6};
slr.actiontable[make_pair(3,'/')] = {r,-1,6};
slr.actiontable[make_pair(3,'#')] = {r,-1,6};
slr.actiontable[make_pair(3,'(')] = {error,0,0};
slr.actiontable[make_pair(3,'i')] = {error,0,0};
slr.actiontable[make_pair(4,')')] = {error,0,0};
slr.actiontable[make_pair(4,'+')] = {error,0,0};
slr.actiontable[make_pair(4,'-')] = {error,0,0};
slr.actiontable[make_pair(4,'*')] = {error,0,0};
slr.actiontable[make_pair(4,'/')] = {error,0,0};
slr.actiontable[make_pair(4,'#')] = {error,0,0};
slr.actiontable[make_pair(4,'(')] = {S,4,-1};
slr.actiontable[make_pair(4,'i')] = {S,5,-1};
slr.actiontable[make_pair(5,'(')] = {error,0,0};
slr.actiontable[make_pair(5,'i')] = {error,0,0};
slr.actiontable[make_pair(5,')')] = {r,-1,8};
slr.actiontable[make_pair(5,'+')] = {r,-1,8};
slr.actiontable[make_pair(5,'-')] = {r,-1,8};
slr.actiontable[make_pair(5,'*')] = {r,-1,8};
slr.actiontable[make_pair(5,'/')] = {r,-1,8};
slr.actiontable[make_pair(5,'#')] = {r,-1,8};
slr.actiontable[make_pair(6,')')] = {error,0,0};
slr.actiontable[make_pair(6,'+')] = {error,0,0};
slr.actiontable[make_pair(6,'-')] = {error,0,0};
slr.actiontable[make_pair(6,'*')] = {error,0,0};
slr.actiontable[make_pair(6,'/')] = {error,0,0};
slr.actiontable[make_pair(6,'#')] = {error,0,0};
slr.actiontable[make_pair(6,'(')] = {S,4,-1};
slr.actiontable[make_pair(6,'i')] = {S,5,-1};
slr.actiontable[make_pair(7,')')] = {error,0,0};
slr.actiontable[make_pair(7,'+')] = {error,0,0};
slr.actiontable[make_pair(7,'-')] = {error,0,0};
slr.actiontable[make_pair(7,'*')] = {error,0,0};
slr.actiontable[make_pair(7,'/')] = {error,0,0};
slr.actiontable[make_pair(7,'#')] = {error,0,0};
slr.actiontable[make_pair(7,'(')] = {S,4,-1};
slr.actiontable[make_pair(7,'i')] = {S,5,-1};
slr.actiontable[make_pair(8,')')] = {error,0,0};
slr.actiontable[make_pair(8,'+')] = {error,0,0};
slr.actiontable[make_pair(8,'-')] = {error,0,0};
slr.actiontable[make_pair(8,'*')] = {error,0,0};
slr.actiontable[make_pair(8,'/')] = {error,0,0};
slr.actiontable[make_pair(8,'#')] = {error,0,0};
slr.actiontable[make_pair(8,'(')] = {S,4,-1};
slr.actiontable[make_pair(8,'i')] = {S,5,-1};
slr.actiontable[make_pair(9,')')] = {error,0,0};
slr.actiontable[make_pair(9,'+')] = {error,0,0};
slr.actiontable[make_pair(9,'-')] = {error,0,0};
slr.actiontable[make_pair(9,'*')] = {error,0,0};
slr.actiontable[make_pair(9,'/')] = {error,0,0};
slr.actiontable[make_pair(9,'#')] = {error,0,0};
slr.actiontable[make_pair(9,'(')] = {S,4,-1};
slr.actiontable[make_pair(9,'i')] = {S,5,-1};
slr.actiontable[make_pair(10,'#')] = {error,0,0};
slr.actiontable[make_pair(10,'i')] = {error,0,0};
slr.actiontable[make_pair(10,'/')] = {error,0,0};
slr.actiontable[make_pair(10,'*')] = {error,0,0};
slr.actiontable[make_pair(10,'(')] = {error,0,0};
slr.actiontable[make_pair(10,')')] = {S,15,-1};
slr.actiontable[make_pair(10,'+')] = {S,6,-1};
slr.actiontable[make_pair(10,'-')] = {S,7,-1};
slr.actiontable[make_pair(11,'(')] = {error,0,0};
slr.actiontable[make_pair(11,'i')] = {error,0,0};
slr.actiontable[make_pair(11,')')] = {r,-1,1};
slr.actiontable[make_pair(11,'+')] = {r,-1,1};
slr.actiontable[make_pair(11,'-')] = {r,-1,1};
slr.actiontable[make_pair(11,'*')] = {S,8,-1};
slr.actiontable[make_pair(11,'/')] = {S,8,-1};
slr.actiontable[make_pair(11,'#')] = {r,-1,1};
slr.actiontable[make_pair(12,'(')] = {error,0,0};
slr.actiontable[make_pair(12,'i')] = {error,0,0};
slr.actiontable[make_pair(12,')')] = {r,-1,2};
slr.actiontable[make_pair(12,'+')] = {r,-1,2};
slr.actiontable[make_pair(12,'-')] = {r,-1,2};
slr.actiontable[make_pair(12,'*')] = {S,8,-1};
slr.actiontable[make_pair(12,'/')] = {S,9,-1};
slr.actiontable[make_pair(12,'#')] = {r,-1,2};
slr.actiontable[make_pair(13,'(')] = {error,0,0};
slr.actiontable[make_pair(13,'i')] = {error,0,0};
slr.actiontable[make_pair(13,')')] = {r,-1,4};
slr.actiontable[make_pair(13,'+')] = {r,-1,4};
slr.actiontable[make_pair(13,'-')] = {r,-1,4};
slr.actiontable[make_pair(13,'*')] = {r,-1,4};
slr.actiontable[make_pair(13,'/')] = {r,-1,4};
slr.actiontable[make_pair(13,'#')] = {r,-1,4};
slr.actiontable[make_pair(14,'(')] = {error,0,0};
slr.actiontable[make_pair(14,'i')] = {error,0,0};
slr.actiontable[make_pair(14,')')] = {r,-1,5};
slr.actiontable[make_pair(14,'+')] = {r,-1,5};
slr.actiontable[make_pair(14,'-')] = {r,-1,5};
slr.actiontable[make_pair(14,'*')] = {r,-1,5};
slr.actiontable[make_pair(14,'/')] = {r,-1,5};
slr.actiontable[make_pair(14,'#')] = {r,-1,5};
slr.actiontable[make_pair(15,'(')] = {error,0,0};
slr.actiontable[make_pair(15,'i')] = {error,0,0};
slr.actiontable[make_pair(15,')')] = {r,-1,7};
slr.actiontable[make_pair(15,'+')] = {r,-1,7};
slr.actiontable[make_pair(15,'-')] = {r,-1,7};
slr.actiontable[make_pair(15,'*')] = {r,-1,7};
slr.actiontable[make_pair(15,'/')] = {r,-1,7};
slr.actiontable[make_pair(15,'#')] = {r,-1,7};
slr.gototable[make_pair(0,'E')] = 1;
slr.gototable[make_pair(0,'T')] = 2;
slr.gototable[make_pair(0,'F')] = 3;
slr.gototable[make_pair(4,'E')] = 10;
slr.gototable[make_pair(4,'T')] = 2;
slr.gototable[make_pair(4,'F')] = 3;
slr.gototable[make_pair(6,'T')] = 11;
slr.gototable[make_pair(6,'F')] = 3;
slr.gototable[make_pair(7,'T')] = 12;
slr.gototable[make_pair(7,'F')] = 3;
slr.gototable[make_pair(8,'F')] = 13;
slr.gototable[make_pair(9,'F')] = 14;
}
SLR1分析过程函数:
void doSLR(SLR &slr) {
//设置初始状态和最终的acc的#号
slr.now_num.push(0);//状态栈->0
slr.now_id.push('#');//符号栈->#
int i = 0;
int r_length = -1;//规约时代表产生式右部的符号数量
char l_char;//规约时代表产生式左部的符号
while (true) {//开始循环分析
int now_state = slr.now_num.top();//当前的状态符号 = 符号栈栈顶符号
char now_id = NULL;
if(txt[i] != NULL) {
now_id = txt[i];//当前匹配的符号
}
if(now_id != 'i' && now_id != '+' && now_id != '-' && now_id != '*'&&now_id != '/'&&now_id != '('&&now_id != ')'&&now_id != '#' && now_id != NULL) {
cout<<"有不合法的输入,分析终止!"<<endl;
break;
}
actionGo ag = slr.actiontable[make_pair(now_state,now_id)];//匹配当前的状态与符号,找动作
if(ag.action == S) {
//根据不同的动作开始分析
slr.now_num.push(ag.s);//状态进栈
slr.now_id.push(now_id);//当前符号进符号栈
i++;//指向下一个待匹配的符号
}else if(ag.action == r) {
r_length = v[ag.r].right.size();//统计产生式右部的符号个数
for(int j = 0;j<r_length;++j) {
slr.now_num.pop();//状态栈弹栈
slr.now_id.pop();//符号栈弹栈
}
l_char = v[ag.r].left;//产生式左部的符号
slr.now_id.push(l_char);//左部符号入栈
int go_to = slr.gototable[make_pair(slr.now_num.top(),l_char)];//找goto的状态
slr.now_num.push(go_to);//新状态入栈
}else if(ag.action == acc) {
flag = 1;
cout<<"分析成功!"<<endl;
break;
}else{
cout<<"分析失败!"<<endl;
break;
}
}
}
文本转换函数(将BEGIN\EDN等字符转换为该文法的字符):
void txt_cin(ifstream &fin) {//输入文本,并转换为该文法
fin.open("D:/Class_Code/bianyiyuanli_Code/shiyan1_to_2.txt");
string s;
int i = 0;
txt.resize(50);
while (getline(fin,s)) {
if(s == "ID" || s == "DATA_INT" || s == "DATA_FLOAT") {
txt[i++] = 'i';
}else if(s == "PL") {
txt[i++] = '+';
}else if(s == "MI") {
txt[i++] = '-';
}else if(s == "MU") {
txt[i++] = '*';
}else if(s == "DI") {
txt[i++] = '/';
}else if(s == "IS") {
txt[i++] = '=';
}else if(s == "LEFT") {
txt[i++] = '(';
}else if(s == "RIGHT") {
txt[i++] = ')';
}
}
txt[i] = '#';
fin.close();
}
打印函数(打印最终结果):
void print(string s) {//输出结果
if(flag == 1) {
cout<<s<<endl;
cout<<"该句子是该文法的句型!";
}else {
cout<<s<<endl;
cout<<"该句子不是该文法的句型!";
}
}
主函数:
void test() {
ifstream fin;
txt_cin(fin);//从文件中获取单词
string s = get_s();//将单词->句子
Init_V();//初始化产生式
SLR slr;//创建一张SLR分析表
actionGo actiongo;//创建一个动作表
fixtable(slr,actiongo);//填表
doSLR(slr);//做SLR分析
print(s);//打印最终结果
}
4.3 程序结构
4.4 程序源码
#include<iostream>
#include<fstream>
#include<vector>
#include<map>
#include <stack>
#include<string>
#define ALL_V 9//产生式的个数,为了r操作
using namespace std;
int flag = 0;//分析成功与否0->失败,1->成功
vector<char> txt;
enum action{S,r,acc,error};//枚举四种动作,移进、规约、接受、拒绝
struct actionGo {
action action;
int s;//移进动作的编号
int r;//规约动作的编号
};
struct V {//产生式的结构体
char left;
vector<char> right;
}v[ALL_V];
class SLR {
public:
map<pair<int,char>,actionGo> actiontable;//action子表
map<pair<int,char>,int> gototable;//goto子表
vector<char> txttoken;//余留符号串
stack<int> now_num;//状态栈
stack<char> now_id;//符号
};
class LL1 {//这是LL1分析法的实现,将在扩展实验中展示
};
void Init_V() {//初始化产生式
v[0].left = 'S',v[0].right.resize(1),v[0].right[0] = 'E';
v[1].left = 'E',v[1].right.resize(3),v[1].right[0]='E',v[1].right[1]='+',v[1].right[2]='T';
v[2].left = 'E',v[2].right.resize(3),v[2].right[0] = 'E',v[2].right[1]='-',v[2].right[2]='T';
v[3].left = 'E',v[3].right.resize(1),v[3].right[0] = 'T';
v[4].left = 'T',v[4].right.resize(3),v[4].right[0] = 'T',v[4].right[1] = '*',v[4].right[2] = 'F';
v[5].left = 'T',v[5].right.resize(3),v[5].right[0] = 'T',v[5].right[1] = '/',v[5].right[2] = 'F';
v[6].left = 'T',v[6].right.resize(1),v[6].right[0] = 'F';
v[7].left = 'F',v[7].right.resize(3),v[7].right[0] = '(',v[7].right[1] = 'E',v[7].right[2] = ')';
v[8].left = 'F',v[8].right.resize(1),v[8].right[0] = 'i';
}
void fixtable(SLR &slr,actionGo &actiongo) {
slr.actiontable[make_pair(0,')')] = {error,0,0};
slr.actiontable[make_pair(0,'+')] = {error,0,0};
slr.actiontable[make_pair(0,'-')] = {error,0,0};
slr.actiontable[make_pair(0,'*')] = {error,0,0};
slr.actiontable[make_pair(0,'/')] = {error,0,0};
slr.actiontable[make_pair(0,'(')] = {S,4,-1};
slr.actiontable[make_pair(0,'#')] = {error,0,0};
slr.actiontable[make_pair(0,'i')] = {S,5,-1};
slr.actiontable[make_pair(1,'+')] = {S,6,-1};
slr.actiontable[make_pair(1,'-')] = {S,7,-1};
slr.actiontable[make_pair(1,'#')] = {acc,-1,-1};
slr.actiontable[make_pair(1,'(')] = {error,0,0};
slr.actiontable[make_pair(1,')')] = {error,0,0};
slr.actiontable[make_pair(1,'i')] = {error,0,0};
slr.actiontable[make_pair(1,'*')] = {error,0,0};
slr.actiontable[make_pair(1,'/')] = {error,0,0};
slr.actiontable[make_pair(2,')')] = {r,-1,3};
slr.actiontable[make_pair(2,'+')] = {r,-1,3};
slr.actiontable[make_pair(2,'-')] = {r,-1,3};
slr.actiontable[make_pair(2,'*')] = {S,8,-1};
slr.actiontable[make_pair(2,'/')] = {S,9,-1};
slr.actiontable[make_pair(2,'#')] = {r,-1,3};
slr.actiontable[make_pair(2,'(')] = {error,0,0};
slr.actiontable[make_pair(2,'i')] = {error,0,0};
slr.actiontable[make_pair(3,')')] = {r,-1,6};
slr.actiontable[make_pair(3,'+')] = {r,-1,6};
slr.actiontable[make_pair(3,'-')] = {r,-1,6};
slr.actiontable[make_pair(3,'*')] = {r,-1,6};
slr.actiontable[make_pair(3,'/')] = {r,-1,6};
slr.actiontable[make_pair(3,'#')] = {r,-1,6};
slr.actiontable[make_pair(3,'(')] = {error,0,0};
slr.actiontable[make_pair(3,'i')] = {error,0,0};
slr.actiontable[make_pair(4,')')] = {error,0,0};
slr.actiontable[make_pair(4,'+')] = {error,0,0};
slr.actiontable[make_pair(4,'-')] = {error,0,0};
slr.actiontable[make_pair(4,'*')] = {error,0,0};
slr.actiontable[make_pair(4,'/')] = {error,0,0};
slr.actiontable[make_pair(4,'#')] = {error,0,0};
slr.actiontable[make_pair(4,'(')] = {S,4,-1};
slr.actiontable[make_pair(4,'i')] = {S,5,-1};
slr.actiontable[make_pair(5,'(')] = {error,0,0};
slr.actiontable[make_pair(5,'i')] = {error,0,0};
slr.actiontable[make_pair(5,')')] = {r,-1,8};
slr.actiontable[make_pair(5,'+')] = {r,-1,8};
slr.actiontable[make_pair(5,'-')] = {r,-1,8};
slr.actiontable[make_pair(5,'*')] = {r,-1,8};
slr.actiontable[make_pair(5,'/')] = {r,-1,8};
slr.actiontable[make_pair(5,'#')] = {r,-1,8};
slr.actiontable[make_pair(6,')')] = {error,0,0};
slr.actiontable[make_pair(6,'+')] = {error,0,0};
slr.actiontable[make_pair(6,'-')] = {error,0,0};
slr.actiontable[make_pair(6,'*')] = {error,0,0};
slr.actiontable[make_pair(6,'/')] = {error,0,0};
slr.actiontable[make_pair(6,'#')] = {error,0,0};
slr.actiontable[make_pair(6,'(')] = {S,4,-1};
slr.actiontable[make_pair(6,'i')] = {S,5,-1};
slr.actiontable[make_pair(7,')')] = {error,0,0};
slr.actiontable[make_pair(7,'+')] = {error,0,0};
slr.actiontable[make_pair(7,'-')] = {error,0,0};
slr.actiontable[make_pair(7,'*')] = {error,0,0};
slr.actiontable[make_pair(7,'/')] = {error,0,0};
slr.actiontable[make_pair(7,'#')] = {error,0,0};
slr.actiontable[make_pair(7,'(')] = {S,4,-1};
slr.actiontable[make_pair(7,'i')] = {S,5,-1};
slr.actiontable[make_pair(8,')')] = {error,0,0};
slr.actiontable[make_pair(8,'+')] = {error,0,0};
slr.actiontable[make_pair(8,'-')] = {error,0,0};
slr.actiontable[make_pair(8,'*')] = {error,0,0};
slr.actiontable[make_pair(8,'/')] = {error,0,0};
slr.actiontable[make_pair(8,'#')] = {error,0,0};
slr.actiontable[make_pair(8,'(')] = {S,4,-1};
slr.actiontable[make_pair(8,'i')] = {S,5,-1};
slr.actiontable[make_pair(9,')')] = {error,0,0};
slr.actiontable[make_pair(9,'+')] = {error,0,0};
slr.actiontable[make_pair(9,'-')] = {error,0,0};
slr.actiontable[make_pair(9,'*')] = {error,0,0};
slr.actiontable[make_pair(9,'/')] = {error,0,0};
slr.actiontable[make_pair(9,'#')] = {error,0,0};
slr.actiontable[make_pair(9,'(')] = {S,4,-1};
slr.actiontable[make_pair(9,'i')] = {S,5,-1};
slr.actiontable[make_pair(10,'#')] = {error,0,0};
slr.actiontable[make_pair(10,'i')] = {error,0,0};
slr.actiontable[make_pair(10,'/')] = {error,0,0};
slr.actiontable[make_pair(10,'*')] = {error,0,0};
slr.actiontable[make_pair(10,'(')] = {error,0,0};
slr.actiontable[make_pair(10,')')] = {S,15,-1};
slr.actiontable[make_pair(10,'+')] = {S,6,-1};
slr.actiontable[make_pair(10,'-')] = {S,7,-1};
slr.actiontable[make_pair(11,'(')] = {error,0,0};
slr.actiontable[make_pair(11,'i')] = {error,0,0};
slr.actiontable[make_pair(11,')')] = {r,-1,1};
slr.actiontable[make_pair(11,'+')] = {r,-1,1};
slr.actiontable[make_pair(11,'-')] = {r,-1,1};
slr.actiontable[make_pair(11,'*')] = {S,8,-1};
slr.actiontable[make_pair(11,'/')] = {S,8,-1};
slr.actiontable[make_pair(11,'#')] = {r,-1,1};
slr.actiontable[make_pair(12,'(')] = {error,0,0};
slr.actiontable[make_pair(12,'i')] = {error,0,0};
slr.actiontable[make_pair(12,')')] = {r,-1,2};
slr.actiontable[make_pair(12,'+')] = {r,-1,2};
slr.actiontable[make_pair(12,'-')] = {r,-1,2};
slr.actiontable[make_pair(12,'*')] = {S,8,-1};
slr.actiontable[make_pair(12,'/')] = {S,9,-1};
slr.actiontable[make_pair(12,'#')] = {r,-1,2};
slr.actiontable[make_pair(13,'(')] = {error,0,0};
slr.actiontable[make_pair(13,'i')] = {error,0,0};
slr.actiontable[make_pair(13,')')] = {r,-1,4};
slr.actiontable[make_pair(13,'+')] = {r,-1,4};
slr.actiontable[make_pair(13,'-')] = {r,-1,4};
slr.actiontable[make_pair(13,'*')] = {r,-1,4};
slr.actiontable[make_pair(13,'/')] = {r,-1,4};
slr.actiontable[make_pair(13,'#')] = {r,-1,4};
slr.actiontable[make_pair(14,'(')] = {error,0,0};
slr.actiontable[make_pair(14,'i')] = {error,0,0};
slr.actiontable[make_pair(14,')')] = {r,-1,5};
slr.actiontable[make_pair(14,'+')] = {r,-1,5};
slr.actiontable[make_pair(14,'-')] = {r,-1,5};
slr.actiontable[make_pair(14,'*')] = {r,-1,5};
slr.actiontable[make_pair(14,'/')] = {r,-1,5};
slr.actiontable[make_pair(14,'#')] = {r,-1,5};
slr.actiontable[make_pair(15,'(')] = {error,0,0};
slr.actiontable[make_pair(15,'i')] = {error,0,0};
slr.actiontable[make_pair(15,')')] = {r,-1,7};
slr.actiontable[make_pair(15,'+')] = {r,-1,7};
slr.actiontable[make_pair(15,'-')] = {r,-1,7};
slr.actiontable[make_pair(15,'*')] = {r,-1,7};
slr.actiontable[make_pair(15,'/')] = {r,-1,7};
slr.actiontable[make_pair(15,'#')] = {r,-1,7};
slr.gototable[make_pair(0,'E')] = 1;
slr.gototable[make_pair(0,'T')] = 2;
slr.gototable[make_pair(0,'F')] = 3;
slr.gototable[make_pair(4,'E')] = 10;
slr.gototable[make_pair(4,'T')] = 2;
slr.gototable[make_pair(4,'F')] = 3;
slr.gototable[make_pair(6,'T')] = 11;
slr.gototable[make_pair(6,'F')] = 3;
slr.gototable[make_pair(7,'T')] = 12;
slr.gototable[make_pair(7,'F')] = 3;
slr.gototable[make_pair(8,'F')] = 13;
slr.gototable[make_pair(9,'F')] = 14;
}
void doSLR(SLR &slr) {
//设置初始状态和最终的acc的#号
slr.now_num.push(0);//状态栈->0
slr.now_id.push('#');//符号栈->#
int i = 0;
int r_length = -1;//规约时代表产生式右部的符号数量
char l_char;//规约时代表产生式左部的符号
while (true) {//开始循环分析
int now_state = slr.now_num.top();//当前的状态符号 = 符号栈栈顶符号
char now_id = NULL;
if(txt[i] != NULL) {
now_id = txt[i];//当前匹配的符号
}
if(now_id != 'i' && now_id != '+' && now_id != '-' && now_id != '*'&&now_id != '/'&&now_id != '('&&now_id != ')'&&now_id != '#' && now_id != NULL) {
cout<<"有不合法的输入,分析终止!"<<endl;
break;
}
actionGo ag = slr.actiontable[make_pair(now_state,now_id)];//匹配当前的状态与符号,找动作
if(ag.action == S) {
//根据不同的动作开始分析
slr.now_num.push(ag.s);//状态进栈
slr.now_id.push(now_id);//当前符号进符号栈
i++;//指向下一个待匹配的符号
}else if(ag.action == r) {
r_length = v[ag.r].right.size();//统计产生式右部的符号个数
for(int j = 0;j<r_length;++j) {
slr.now_num.pop();//状态栈弹栈
slr.now_id.pop();//符号栈弹栈
}
l_char = v[ag.r].left;//产生式左部的符号
slr.now_id.push(l_char);//左部符号入栈
int go_to = slr.gototable[make_pair(slr.now_num.top(),l_char)];//找goto的状态
slr.now_num.push(go_to);//新状态入栈
}else if(ag.action == acc) {
flag = 1;
cout<<"分析成功!"<<endl;
break;
}else{
cout<<"分析失败!"<<endl;
break;
}
}
}
void txt_cin(ifstream &fin) {//输入文本,并转换为该文法
fin.open("D:/Class_Code/bianyiyuanli_Code/shiyan1_to_2.txt");
string s;
int i = 0;
txt.resize(50);
while (getline(fin,s)) {
if(s == "ID" || s == "DATA_INT" || s == "DATA_FLOAT") {
txt[i++] = 'i';
}else if(s == "PL") {
txt[i++] = '+';
}else if(s == "MI") {
txt[i++] = '-';
}else if(s == "MU") {
txt[i++] = '*';
}else if(s == "DI") {
txt[i++] = '/';
}else if(s == "IS") {
txt[i++] = '=';
}else if(s == "LEFT") {
txt[i++] = '(';
}else if(s == "RIGHT") {
txt[i++] = ')';
}
}
txt[i] = '#';
fin.close();
}
string get_s() {//组成句子
string s;
for(int i = 0;i<txt.size();i++) {
if(txt[i] != NULL && txt[i]!='#') {
s = s+txt[i];
}
}
return s;
}
void print(string s) {//输出结果
if(flag == 1) {
cout<<s<<endl;
cout<<"该句子是该文法的句型!";
}else {
cout<<s<<endl;
cout<<"该句子不是该文法的句型!";
}
}
void test() {
ifstream fin;
txt_cin(fin);//从文件中获取单词
string s = get_s();//将单词->句子
Init_V();//初始化产生式
SLR slr;//创建一张SLR分析表
actionGo actiongo;//创建一个动作表
fixtable(slr,actiongo);//填表
doSLR(slr);//做SLR分析
print(s);//打印最终结果
}
int main(void) {
test();
return 0;
}
5 扩展实验(LL1分析法实现语法分析器)
5.1 扩展分析
5.1.1 消除左递归
E->TE’
E’-> +TE’ | -TE’ | ɜ
T->FT’
T’->*FT’ | /FT’ | ɜ
F->(E) F->i
5.1.2 求FIRST集与FOLLOW集
5.1.3 建立LL1分析表
5.2 扩展程序分析
新增数据结构:
LL1分析类:
其中包含各个非终结符号的FIRST集合与FOLLOW集合、一个图类型的LL1分析表、一个stack类型的符号栈、一个初始化LL1分析表的方法、一个开始分析的方法
class LL1 {
public:
char FIRST_E[2] = {'(','i'};
char FIRST_e[3] = {'+','-','!'};//'!' -> ?
char FIRST_T[2] = {'(','i'};
char FIRST_F[2] = {'(','i'};
char FIRST_t[3]={'*','/','!'};
char FOLLOW_E[2] = {'#',')'};
char FOLLOW_e[2] = {'#',')'};
char FOLLOW_t[4] = {'+','-','#',')'};
char FOLLOW_F[6] = {'+','-','*','/','#',')'};
char FOLLOW_T[4] = {'+','-','#',')'};
map<pair<char,char>,int> LL1_table;
stack<char> simple;
void init_LL1(LL1 &LL1);//填表
void doLL1(LL1 &LL1);//开始分析
};
新增函数:
LL1分析表初始化函数,器内容与SLR分析表的填表过程类似(-1表示分析失败的情况):
void LL1::init_LL1(LL1 &LL1) {
LL1.LL1_table[make_pair('E','i')] = 1;
LL1.LL1_table[make_pair('E','(')] = 1;
LL1.LL1_table[make_pair('E','+')] = -1;
LL1.LL1_table[make_pair('E','-')] = -1;
LL1.LL1_table[make_pair('E','*')] = -1;
LL1.LL1_table[make_pair('E','/')] = -1;
LL1.LL1_table[make_pair('E',')')] = -1;
LL1.LL1_table[make_pair('E','#')] = -1;
LL1.LL1_table[make_pair('e','+')] = 2;
LL1.LL1_table[make_pair('e','-')] = 3;
LL1.LL1_table[make_pair('e',')')] = 4;
LL1.LL1_table[make_pair('e','#')] = 4;
LL1.LL1_table[make_pair('e','i')] = -1;
LL1.LL1_table[make_pair('e','*')] = -1;
LL1.LL1_table[make_pair('e','/')] = -1;
LL1.LL1_table[make_pair('e','(')] = -1;
LL1.LL1_table[make_pair('T','i')] = 5;
LL1.LL1_table[make_pair('T','(')] = 5;
LL1.LL1_table[make_pair('T','+')] = -1;
LL1.LL1_table[make_pair('T','-')] = -1;
LL1.LL1_table[make_pair('T','*')] = -1;
LL1.LL1_table[make_pair('T','/')] = -1;
LL1.LL1_table[make_pair('T',')')] = -1;
LL1.LL1_table[make_pair('T','#')] = -1;
LL1.LL1_table[make_pair('t','+')] = 8;
LL1.LL1_table[make_pair('t','-')] = 8;
LL1.LL1_table[make_pair('t','*')] = 6;
LL1.LL1_table[make_pair('t','/')] = 7;
LL1.LL1_table[make_pair('t',')')] = 8;
LL1.LL1_table[make_pair('t','#')] = 8;
LL1.LL1_table[make_pair('t','i')] = -1;
LL1.LL1_table[make_pair('t','(')] = -1;
LL1.LL1_table[make_pair('F','i')] = 10;
LL1.LL1_table[make_pair('F','(')] = 9;
LL1.LL1_table[make_pair('F','#')] = -1;
LL1.LL1_table[make_pair('F','+')] = -1;
LL1.LL1_table[make_pair('F','-')] = -1;
LL1.LL1_table[make_pair('F','*')] = -1;
LL1.LL1_table[make_pair('F','/')] = -1;
LL1.LL1_table[make_pair('F',')')] = -1;
}
新增doLL1函数,该函数为LL1分析法的总控程序,首先先将初始符号’#’与’E’压栈,之后根据LL1类中的LL1分析表进行栈顶元素与输入文本的首字符进行匹配,找到相应的产生式,进而再对符号栈simple进行操作:
void LL1::doLL1(LL1 &LL1) {
int index = 0;//用于指向txt的下一个符号
/*开始匹配*/
int now_state;
/*先压栈开始符# 与初始状态E*/
LL1.simple.push('#');
LL1.simple.push('E');
while (true){
if(simple.top() == txt[index]) {//栈顶元素与当前符号匹配,直接消除
if(simple.top() == '#') {//分析成功的情况
cout<<"分析成功!"<<endl;
flag = 1;
break;
}else {
simple.pop();
index++;
}
}
now_state = LL1.LL1_table[make_pair(LL1.simple.top(),txt[index])];
if(now_state == -1) {
cout<<"分析失败"<<endl;
flag = 0;
break;
}else {
switch (now_state) {
case 1:
simple.pop();//当前符号弹栈
/*反向压栈*/
simple.push('e');
simple.push('T');
break;
case 2:
simple.pop();
simple.push('e');
simple.push('T');
simple.push('+');
break;
case 3:
simple.pop();
simple.push('e');
simple.push('T');
simple.push('+');
break;
case 4:
simple.pop();
break;
case 5:
simple.pop();
simple.push('t');
simple.push('F');
break;
case 6:
simple.pop();
simple.push('t');
simple.push('F');
simple.push('*');
break;
case 7:
simple.pop();
simple.push('t');
simple.push('F');
simple.push('/');
break;
case 8:
simple.pop();
break;
case 9:
simple.pop();
simple.push(')');
simple.push('E');
simple.push('(');
break;
case 10:
simple.pop();
simple.push('i');
}
}
}
}
6 整体源码
#include<iostream>
#include<fstream>
#include<vector>
#include<map>
#include <stack>
#include<string>
#define ALL_V 9//产生式的个数,为了r操作
using namespace std;
int flag = 0;//分析成功与否0->失败,1->成功
vector<char> txt;
enum action{S,r,acc,error};//枚举四种动作,移进、规约、接受、拒绝
struct actionGo {
action action;
int s;//移进动作的编号
int r;//规约动作的编号
};
struct V {//产生式的结构体
char left;
vector<char> right;
}v[ALL_V];
class SLR {
public:
map<pair<int,char>,actionGo> actiontable;//action子表
map<pair<int,char>,int> gototable;//goto子表
vector<char> txttoken;//余留符号串
stack<int> now_num;//状态栈
stack<char> now_id;//符号
};
class LL1 {
public:
char FIRST_E[2] = {'(','i'};
char FIRST_e[3] = {'+','-','!'};//'!' -> ?
char FIRST_T[2] = {'(','i'};
char FIRST_F[2] = {'(','i'};
char FIRST_t[3]={'*','/','!'};
char FOLLOW_E[2] = {'#',')'};
char FOLLOW_e[2] = {'#',')'};
char FOLLOW_t[4] = {'+','-','#',')'};
char FOLLOW_F[6] = {'+','-','*','/','#',')'};
char FOLLOW_T[4] = {'+','-','#',')'};
map<pair<char,char>,int> LL1_table;
stack<char> simple;
void init_LL1(LL1 &LL1);//填表
void doLL1(LL1 &LL1);//开始分析
};
void Init_V() {//初始化产生式
v[0].left = 'S',v[0].right.resize(1),v[0].right[0] = 'E';
v[1].left = 'E',v[1].right.resize(3),v[1].right[0]='E',v[1].right[1]='+',v[1].right[2]='T';
v[2].left = 'E',v[2].right.resize(3),v[2].right[0] = 'E',v[2].right[1]='-',v[2].right[2]='T';
v[3].left = 'E',v[3].right.resize(1),v[3].right[0] = 'T';
v[4].left = 'T',v[4].right.resize(3),v[4].right[0] = 'T',v[4].right[1] = '*',v[4].right[2] = 'F';
v[5].left = 'T',v[5].right.resize(3),v[5].right[0] = 'T',v[5].right[1] = '/',v[5].right[2] = 'F';
v[6].left = 'T',v[6].right.resize(1),v[6].right[0] = 'F';
v[7].left = 'F',v[7].right.resize(3),v[7].right[0] = '(',v[7].right[1] = 'E',v[7].right[2] = ')';
v[8].left = 'F',v[8].right.resize(1),v[8].right[0] = 'i';
}
void fixtable(SLR &slr,actionGo &actiongo) {
slr.actiontable[make_pair(0,')')] = {error,0,0};
slr.actiontable[make_pair(0,'+')] = {error,0,0};
slr.actiontable[make_pair(0,'-')] = {error,0,0};
slr.actiontable[make_pair(0,'*')] = {error,0,0};
slr.actiontable[make_pair(0,'/')] = {error,0,0};
slr.actiontable[make_pair(0,'(')] = {S,4,-1};
slr.actiontable[make_pair(0,'#')] = {error,0,0};
slr.actiontable[make_pair(0,'i')] = {S,5,-1};
slr.actiontable[make_pair(1,'+')] = {S,6,-1};
slr.actiontable[make_pair(1,'-')] = {S,7,-1};
slr.actiontable[make_pair(1,'#')] = {acc,-1,-1};
slr.actiontable[make_pair(1,'(')] = {error,0,0};
slr.actiontable[make_pair(1,')')] = {error,0,0};
slr.actiontable[make_pair(1,'i')] = {error,0,0};
slr.actiontable[make_pair(1,'*')] = {error,0,0};
slr.actiontable[make_pair(1,'/')] = {error,0,0};
slr.actiontable[make_pair(2,')')] = {r,-1,3};
slr.actiontable[make_pair(2,'+')] = {r,-1,3};
slr.actiontable[make_pair(2,'-')] = {r,-1,3};
slr.actiontable[make_pair(2,'*')] = {S,8,-1};
slr.actiontable[make_pair(2,'/')] = {S,9,-1};
slr.actiontable[make_pair(2,'#')] = {r,-1,3};
slr.actiontable[make_pair(2,'(')] = {error,0,0};
slr.actiontable[make_pair(2,'i')] = {error,0,0};
slr.actiontable[make_pair(3,')')] = {r,-1,6};
slr.actiontable[make_pair(3,'+')] = {r,-1,6};
slr.actiontable[make_pair(3,'-')] = {r,-1,6};
slr.actiontable[make_pair(3,'*')] = {r,-1,6};
slr.actiontable[make_pair(3,'/')] = {r,-1,6};
slr.actiontable[make_pair(3,'#')] = {r,-1,6};
slr.actiontable[make_pair(3,'(')] = {error,0,0};
slr.actiontable[make_pair(3,'i')] = {error,0,0};
slr.actiontable[make_pair(4,')')] = {error,0,0};
slr.actiontable[make_pair(4,'+')] = {error,0,0};
slr.actiontable[make_pair(4,'-')] = {error,0,0};
slr.actiontable[make_pair(4,'*')] = {error,0,0};
slr.actiontable[make_pair(4,'/')] = {error,0,0};
slr.actiontable[make_pair(4,'#')] = {error,0,0};
slr.actiontable[make_pair(4,'(')] = {S,4,-1};
slr.actiontable[make_pair(4,'i')] = {S,5,-1};
slr.actiontable[make_pair(5,'(')] = {error,0,0};
slr.actiontable[make_pair(5,'i')] = {error,0,0};
slr.actiontable[make_pair(5,')')] = {r,-1,8};
slr.actiontable[make_pair(5,'+')] = {r,-1,8};
slr.actiontable[make_pair(5,'-')] = {r,-1,8};
slr.actiontable[make_pair(5,'*')] = {r,-1,8};
slr.actiontable[make_pair(5,'/')] = {r,-1,8};
slr.actiontable[make_pair(5,'#')] = {r,-1,8};
slr.actiontable[make_pair(6,')')] = {error,0,0};
slr.actiontable[make_pair(6,'+')] = {error,0,0};
slr.actiontable[make_pair(6,'-')] = {error,0,0};
slr.actiontable[make_pair(6,'*')] = {error,0,0};
slr.actiontable[make_pair(6,'/')] = {error,0,0};
slr.actiontable[make_pair(6,'#')] = {error,0,0};
slr.actiontable[make_pair(6,'(')] = {S,4,-1};
slr.actiontable[make_pair(6,'i')] = {S,5,-1};
slr.actiontable[make_pair(7,')')] = {error,0,0};
slr.actiontable[make_pair(7,'+')] = {error,0,0};
slr.actiontable[make_pair(7,'-')] = {error,0,0};
slr.actiontable[make_pair(7,'*')] = {error,0,0};
slr.actiontable[make_pair(7,'/')] = {error,0,0};
slr.actiontable[make_pair(7,'#')] = {error,0,0};
slr.actiontable[make_pair(7,'(')] = {S,4,-1};
slr.actiontable[make_pair(7,'i')] = {S,5,-1};
slr.actiontable[make_pair(8,')')] = {error,0,0};
slr.actiontable[make_pair(8,'+')] = {error,0,0};
slr.actiontable[make_pair(8,'-')] = {error,0,0};
slr.actiontable[make_pair(8,'*')] = {error,0,0};
slr.actiontable[make_pair(8,'/')] = {error,0,0};
slr.actiontable[make_pair(8,'#')] = {error,0,0};
slr.actiontable[make_pair(8,'(')] = {S,4,-1};
slr.actiontable[make_pair(8,'i')] = {S,5,-1};
slr.actiontable[make_pair(9,')')] = {error,0,0};
slr.actiontable[make_pair(9,'+')] = {error,0,0};
slr.actiontable[make_pair(9,'-')] = {error,0,0};
slr.actiontable[make_pair(9,'*')] = {error,0,0};
slr.actiontable[make_pair(9,'/')] = {error,0,0};
slr.actiontable[make_pair(9,'#')] = {error,0,0};
slr.actiontable[make_pair(9,'(')] = {S,4,-1};
slr.actiontable[make_pair(9,'i')] = {S,5,-1};
slr.actiontable[make_pair(10,'#')] = {error,0,0};
slr.actiontable[make_pair(10,'i')] = {error,0,0};
slr.actiontable[make_pair(10,'/')] = {error,0,0};
slr.actiontable[make_pair(10,'*')] = {error,0,0};
slr.actiontable[make_pair(10,'(')] = {error,0,0};
slr.actiontable[make_pair(10,')')] = {S,15,-1};
slr.actiontable[make_pair(10,'+')] = {S,6,-1};
slr.actiontable[make_pair(10,'-')] = {S,7,-1};
slr.actiontable[make_pair(11,'(')] = {error,0,0};
slr.actiontable[make_pair(11,'i')] = {error,0,0};
slr.actiontable[make_pair(11,')')] = {r,-1,1};
slr.actiontable[make_pair(11,'+')] = {r,-1,1};
slr.actiontable[make_pair(11,'-')] = {r,-1,1};
slr.actiontable[make_pair(11,'*')] = {S,8,-1};
slr.actiontable[make_pair(11,'/')] = {S,8,-1};
slr.actiontable[make_pair(11,'#')] = {r,-1,1};
slr.actiontable[make_pair(12,'(')] = {error,0,0};
slr.actiontable[make_pair(12,'i')] = {error,0,0};
slr.actiontable[make_pair(12,')')] = {r,-1,2};
slr.actiontable[make_pair(12,'+')] = {r,-1,2};
slr.actiontable[make_pair(12,'-')] = {r,-1,2};
slr.actiontable[make_pair(12,'*')] = {S,8,-1};
slr.actiontable[make_pair(12,'/')] = {S,9,-1};
slr.actiontable[make_pair(12,'#')] = {r,-1,2};
slr.actiontable[make_pair(13,'(')] = {error,0,0};
slr.actiontable[make_pair(13,'i')] = {error,0,0};
slr.actiontable[make_pair(13,')')] = {r,-1,4};
slr.actiontable[make_pair(13,'+')] = {r,-1,4};
slr.actiontable[make_pair(13,'-')] = {r,-1,4};
slr.actiontable[make_pair(13,'*')] = {r,-1,4};
slr.actiontable[make_pair(13,'/')] = {r,-1,4};
slr.actiontable[make_pair(13,'#')] = {r,-1,4};
slr.actiontable[make_pair(14,'(')] = {error,0,0};
slr.actiontable[make_pair(14,'i')] = {error,0,0};
slr.actiontable[make_pair(14,')')] = {r,-1,5};
slr.actiontable[make_pair(14,'+')] = {r,-1,5};
slr.actiontable[make_pair(14,'-')] = {r,-1,5};
slr.actiontable[make_pair(14,'*')] = {r,-1,5};
slr.actiontable[make_pair(14,'/')] = {r,-1,5};
slr.actiontable[make_pair(14,'#')] = {r,-1,5};
slr.actiontable[make_pair(15,'(')] = {error,0,0};
slr.actiontable[make_pair(15,'i')] = {error,0,0};
slr.actiontable[make_pair(15,')')] = {r,-1,7};
slr.actiontable[make_pair(15,'+')] = {r,-1,7};
slr.actiontable[make_pair(15,'-')] = {r,-1,7};
slr.actiontable[make_pair(15,'*')] = {r,-1,7};
slr.actiontable[make_pair(15,'/')] = {r,-1,7};
slr.actiontable[make_pair(15,'#')] = {r,-1,7};
slr.gototable[make_pair(0,'E')] = 1;
slr.gototable[make_pair(0,'T')] = 2;
slr.gototable[make_pair(0,'F')] = 3;
slr.gototable[make_pair(4,'E')] = 10;
slr.gototable[make_pair(4,'T')] = 2;
slr.gototable[make_pair(4,'F')] = 3;
slr.gototable[make_pair(6,'T')] = 11;
slr.gototable[make_pair(6,'F')] = 3;
slr.gototable[make_pair(7,'T')] = 12;
slr.gototable[make_pair(7,'F')] = 3;
slr.gototable[make_pair(8,'F')] = 13;
slr.gototable[make_pair(9,'F')] = 14;
}
void doSLR(SLR &slr) {
//设置初始状态和最终的acc的#号
slr.now_num.push(0);//状态栈->0
slr.now_id.push('#');//符号栈->#
int i = 0;
int r_length = -1;//规约时代表产生式右部的符号数量
char l_char;//规约时代表产生式左部的符号
while (true) {//开始循环分析
int now_state = slr.now_num.top();//当前的状态符号 = 符号栈栈顶符号
char now_id = NULL;
if(txt[i] != NULL) {
now_id = txt[i];//当前匹配的符号
}
if(now_id != 'i' && now_id != '+' && now_id != '-' && now_id != '*'&&now_id != '/'&&now_id != '('&&now_id != ')'&&now_id != '#' && now_id != NULL) {
cout<<"有不合法的输入,分析终止!"<<endl;
break;
}
actionGo ag = slr.actiontable[make_pair(now_state,now_id)];//匹配当前的状态与符号,找动作
if(ag.action == S) {
//根据不同的动作开始分析
slr.now_num.push(ag.s);//状态进栈
slr.now_id.push(now_id);//当前符号进符号栈
i++;//指向下一个待匹配的符号
}else if(ag.action == r) {
r_length = v[ag.r].right.size();//统计产生式右部的符号个数
for(int j = 0;j<r_length;++j) {
slr.now_num.pop();//状态栈弹栈
slr.now_id.pop();//符号栈弹栈
}
l_char = v[ag.r].left;//产生式左部的符号
slr.now_id.push(l_char);//左部符号入栈
int go_to = slr.gototable[make_pair(slr.now_num.top(),l_char)];//找goto的状态
slr.now_num.push(go_to);//新状态入栈
}else if(ag.action == acc) {
flag = 1;
cout<<"分析成功!"<<endl;
break;
}else{
cout<<"分析失败!"<<endl;
break;
}
}
}
void LL1::init_LL1(LL1 &LL1) {
LL1.LL1_table[make_pair('E','i')] = 1;
LL1.LL1_table[make_pair('E','(')] = 1;
LL1.LL1_table[make_pair('E','+')] = -1;
LL1.LL1_table[make_pair('E','-')] = -1;
LL1.LL1_table[make_pair('E','*')] = -1;
LL1.LL1_table[make_pair('E','/')] = -1;
LL1.LL1_table[make_pair('E',')')] = -1;
LL1.LL1_table[make_pair('E','#')] = -1;
LL1.LL1_table[make_pair('e','+')] = 2;
LL1.LL1_table[make_pair('e','-')] = 3;
LL1.LL1_table[make_pair('e',')')] = 4;
LL1.LL1_table[make_pair('e','#')] = 4;
LL1.LL1_table[make_pair('e','i')] = -1;
LL1.LL1_table[make_pair('e','*')] = -1;
LL1.LL1_table[make_pair('e','/')] = -1;
LL1.LL1_table[make_pair('e','(')] = -1;
LL1.LL1_table[make_pair('T','i')] = 5;
LL1.LL1_table[make_pair('T','(')] = 5;
LL1.LL1_table[make_pair('T','+')] = -1;
LL1.LL1_table[make_pair('T','-')] = -1;
LL1.LL1_table[make_pair('T','*')] = -1;
LL1.LL1_table[make_pair('T','/')] = -1;
LL1.LL1_table[make_pair('T',')')] = -1;
LL1.LL1_table[make_pair('T','#')] = -1;
LL1.LL1_table[make_pair('t','+')] = 8;
LL1.LL1_table[make_pair('t','-')] = 8;
LL1.LL1_table[make_pair('t','*')] = 6;
LL1.LL1_table[make_pair('t','/')] = 7;
LL1.LL1_table[make_pair('t',')')] = 8;
LL1.LL1_table[make_pair('t','#')] = 8;
LL1.LL1_table[make_pair('t','i')] = -1;
LL1.LL1_table[make_pair('t','(')] = -1;
LL1.LL1_table[make_pair('F','i')] = 10;
LL1.LL1_table[make_pair('F','(')] = 9;
LL1.LL1_table[make_pair('F','#')] = -1;
LL1.LL1_table[make_pair('F','+')] = -1;
LL1.LL1_table[make_pair('F','-')] = -1;
LL1.LL1_table[make_pair('F','*')] = -1;
LL1.LL1_table[make_pair('F','/')] = -1;
LL1.LL1_table[make_pair('F',')')] = -1;
}
void LL1::doLL1(LL1 &LL1) {
int index = 0;//用于指向txt的下一个符号
/*开始匹配*/
int now_state;
/*先压栈开始符# 与初始状态E*/
LL1.simple.push('#');
LL1.simple.push('E');
while (true){
if(simple.top() == txt[index]) {//栈顶元素与当前符号匹配,直接消除
if(simple.top() == '#') {//分析成功的情况
cout<<"分析成功!"<<endl;
flag = 1;
break;
}else {
simple.pop();
index++;
}
}
now_state = LL1.LL1_table[make_pair(LL1.simple.top(),txt[index])];
if(now_state == -1) {
cout<<"分析失败"<<endl;
flag = 0;
break;
}else {
switch (now_state) {
case 1:
simple.pop();//当前符号弹栈
/*反向压栈*/
simple.push('e');
simple.push('T');
break;
case 2:
simple.pop();
simple.push('e');
simple.push('T');
simple.push('+');
break;
case 3:
simple.pop();
simple.push('e');
simple.push('T');
simple.push('+');
break;
case 4:
simple.pop();
break;
case 5:
simple.pop();
simple.push('t');
simple.push('F');
break;
case 6:
simple.pop();
simple.push('t');
simple.push('F');
simple.push('*');
break;
case 7:
simple.pop();
simple.push('t');
simple.push('F');
simple.push('/');
break;
case 8:
simple.pop();
break;
case 9:
simple.pop();
simple.push(')');
simple.push('E');
simple.push('(');
break;
case 10:
simple.pop();
simple.push('i');
}
}
}
}
void txt_cin(ifstream &fin) {//输入文本,并转换为该文法
fin.open("D:/Class_Code/bianyiyuanli_Code/shiyan1_to_2.txt");
string s;
int i = 0;
txt.resize(50);
while (getline(fin,s)) {
if(s == "ID" || s == "DATA_INT" || s == "DATA_FLOAT") {
txt[i++] = 'i';
}else if(s == "PL") {
txt[i++] = '+';
}else if(s == "MI") {
txt[i++] = '-';
}else if(s == "MU") {
txt[i++] = '*';
}else if(s == "DI") {
txt[i++] = '/';
}else if(s == "IS") {
txt[i++] = '=';
}else if(s == "LEFT") {
txt[i++] = '(';
}else if(s == "RIGHT") {
txt[i++] = ')';
}
}
txt[i] = '#';
fin.close();
}
string get_s() {//组成句子
string s;
for(int i = 0;i<txt.size();i++) {
if(txt[i] != NULL && txt[i]!='#') {
s = s+txt[i];
}
}
return s;
}
void print(string s) {//输出结果
if(flag == 1) {
cout<<s<<endl;
cout<<"该句子是该文法的句型!";
}else {
cout<<s<<endl;
cout<<"该句子不是该文法的句型!";
}
}
void test() {
ifstream fin;
txt_cin(fin);//从文件中获取单词
string s = get_s();//将单词->句子
Init_V();//初始化产生式
SLR slr;//创建一张SLR分析表
actionGo actiongo;//创建一个动作表
fixtable(slr,actiongo);//填表
doSLR(slr);//做SLR分析
print(s);//打印最终结果
}
void test2() {
ifstream fin;
txt_cin(fin);//从文件中获取单词
string s = get_s();//将单词->句子
LL1 LL1;//创建LL1对象
LL1.init_LL1(LL1);//初始化LL1
LL1.doLL1(LL1);
print(s);//打印最终结果
}
int main(void) {
//test();
test2();
return 0;
}