实验5《LR(1)分析法设计与实现》
一、实验目的
构造LR(1)分析程序,利用它进行语法分析,判断给出的符号串是否为该文法识别的句子,了解LR(K)分析方法是严格的从左向右扫描,和自底向上的语法分析方法。
二、实验内容
程序输入/输出示例(以下仅供参考):
对下列文法,用LR(1)分析法对任意输入的符号串进行分析:
(1)E-E+T
(2)E-E—T
(3)T-T*F
(4)T-T/F
(5)F-(E)
(6)F-i
输出的格式如下:
(1)LR(1)分析程序,编制人:姓名,学号,班级
(2)输入一个以#结束的符号串(包括+—*/()i#):在此位置输入符号串
(3)输出过程如下:
步骤 | 状态栈 | 符号栈 | 剩余输入串 | 动作 |
---|---|---|---|---|
1 | 0 | # | i+i*i# | 移进 |
(4)输入符号串为非法符号串(或者为合法符号串)
备注:
1.在“所用产生式”一列中如果对应有推导则写出所用产生式;如果为匹配终结符则写明匹配的终结符;如分析异常出错则写为“分析出错”;若成功结束则写为“分析成功”。
2.在此位置输入符号串为用户自行输入的符号串。
注意:
1.表达式中允许使用运算符(±*/)、分割符(括号)、字符i,结束符#;
2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);
3.对学有余力的同学,测试用的表达式事先放在文本文件中,一行存放一个表达式,同时以分号分割。同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照。
三、实验方法
1.实验采用C++程序语言进行设计,文法写入程序中,用户可以自定义输入语句;
2.实验开发工具为Visual Studio Code。
四、实验步骤
1.定义LR(1)分析法实验设计思想及算法
①若ACTION[sm , ai] = s则将s移进状态栈,并把输入符号加入符号栈,则三元式变成为:(s0s1…sm s , #X1X2…Xm ai , ai+1…an#);
②若ACTION[sm , ai] = rj则将第j个产生式A->β进行归约。此时三元式变为(s0s1…sm-r s , #X1X2…Xm-rA , aiai+1…an#);
③若ACTION[sm , ai]为“接收”,则三元式不再变化,变化过程终止,宣布分析成功;
④若ACTION[sm , ai]为“报错”,则三元式的变化过程终止,报告错误。
2.定义语法构造的代码,与主代码分离,写为头文件LR.h。
3.编写主程序利用上文描述算法实现本实验要求。
五、实验结果
1. 实验文法为程序既定的文法,写在头文件LR.h中,运行程序,用户可以自由输入测试语句。
2. 实验测试结果:
测试结果符合预期结果,程序能够对用户的语句利用LR(1)分析法构建分析表,利用分析栈进行正误分析。实验截图如下所示:
六、实验结论
1.实验利用自定义的源程序进行测试,结果正确,符合预期结果,测试源码及结果截图和说明如上所示。
2.实验源码码分为头文件(LR.h)和主文件(test5.cpp)。均如下所示:
LR.h
#ifndef _LR_
#define _LR_
using namespace std;
class Grammar{
public:
//产生式的个数
int grammarNum ;
//定义产生式数组
string formula[100] = {
" ","E->E+T","E->T","T->T*F","T->F","F->(E)","F->i"};
Grammar(){
grammarNum = 6;
}
};
//定义LR文法的分析表
class LRAnalyseTable{
public:
char terminalChar[100]={
'i','+','*','(',')','#'};
//定义终结符的个数
int terNum =6;
char nonTerminalChar[100]={
'E','T','F'};
//定义非终结符的个数
int nonTerNum = 3;
//定义状态数
int statusNum = 12;
string action[12][6]={
{
"s5","","","s4","",""},{
"","s6","","","","acc"},{
"","r2","s7","","r2","r2"},{
"","r4","r4","","r4","r4"},{
"s5","","","s4","",""},{
"","r6","r6","","r6","r6"},{
"s5","",