语法分析程序的设计与实现
目录
语法分析程序的设计与实现 1
一. 实验题目 1
二. 实验要求 2
方法1:编写递归调用程序实现自顶向下的分析. 2
方法2:编写LL(1)语法分析程序,要求如下. (必做) 2
方法3:编写语法分析程序实现自底向上的分析,要求如下.(必做) 2
方法4:利用YACC自动生成语法分析程序,调用LEX自动生成的词法分析程序. 2
三. 程序设计说明 2
(一) LL(1)语法分析程序 2
- 数据结构与函数说明 2
2. 程序分析前的数据操作 4
3. 构造预测分析表 4
4. 构造预测分析程序 5
(二) LR分析程序 6
1. 数据结构及函数说明 6
2. 构造识别该文法所有活前缀的DFA 7
3. First集合与follow集合,构造该文法的LR分析表 7
4. 编程实现算法4.3,构造LR分析程序 8
四. 源程序 8
五. 可执行程序 8
六. 测试报告 9 - LL(1)程序测试 9
(1) 第一组测试 9
(2) 第二组测试 10 - SLR(1)程序测试 11
(1) 第一组测试 11
(2) 第二组测试 13
(3) 第三组测试 15
一.实验题目
1.语法分析程序的设计与实现
2.编写语法分析程序,实现对算术表达式的语法分析。要求所分析
算数表达式由如下的文法产生。
E->E+T | E–T | T
T->T*F | T/F | F
F->(E) | num
二.实验要求
在对输入的算术表达式进行分析的过程中,依次输出所采用的产生式.
方法1:编写递归调用程序实现自顶向下的分析.
方法2:编写LL(1)语法分析程序,要求如下. (必做)
(1) 编程实现算法4.2,为给定文法自动构造预测分析表.
(2) 编程实现算法4.1,构造LL(1)预测分析程序 .
方法3:编写语法分析程序实现自底向上的分析,要求如下.(必做)
(3)构造识别该文法所有活前缀的DFA.
(4)构造该文法的LR分析表.
(5)编程实现算法4.3,构造LR分析程序.
方法4:利用YACC自动生成语法分析程序,调用LEX自动生成的词法分 析程序.
三.程序设计说明
(一)LL(1)语法分析程序
1.数据结构与函数说明
① 设置class CAnalysisTable类
class CAnalysisTable{
private:
string** AnalysisTable; //存储预测分析表
string StackString; //栈字符串
int AnalysisTableRow = 5; //行数
int AnalysisTableCol = 8; //列数
vector<string> Terminator; //存储终结符
map<string, vector<string> > FirstSet; //存储first集合
map<string, vector<string> > FollowSet; //存储follow集合
//分析程序
stack<string> SymbolStack; //符号栈
string OutputResults; //输出使用的表达式
string CurrentString; //当前字串
map<string, int> NonterminalMap; //非终结符对应预测分析表的行号
map<string, int> TerminalMap; //终结符对应预测分析表的列号
protected:
//表达式的存储(一对多的形式)
map<string, vector<string> > expression; //每个父表达式对应的全部子表达式
public:
string CalculationEstr; //待分析符号串
vector<string> DealData(string str, string split); //字符串的处理
void Init(); //文件读取内容,进行初始化存储变量
void StructuralAnalysisTable(); //分析表的构造
void ShowAnalysisTable(); //输出分析表
//分析程序
void init(); //栈的初始化
void LIAnalysisPExe(); //预测分析函数
void CalNonOrTerminalMap(); //计算非终结符分别对应的预测分析表的行号
};
②函数实现说明
1)void Init();
在本程序中,所有的内容采取文件读取。
fstream Einfile("expression.txt", ios::in); //读取表达式
fstream Tinfile("Terminator.txt", ios::in); //读取终结符
fstream NTinfile("Nonterminal.txt", ios::in); //读取非终结符
fstream Firstinfile("FirstSet.txt", ios::in); //读取first集合
fstream Followinfile("FollowSet.txt", ios::in); //读取follow集合
2)vector<string> DealData(string str, string split);
文件读取出的数据进行处理的函数。
其中str是待切割的字符串,split字符串是进行切割的标志符号。
3)void StructuralAnalysisTable();
构造分析表,主体实现过程按照算法4.2进行实现。
4)void init();
栈的初始化
将栈初始化为存有”$“状态。
5)void CAnalysisTable::LIAnalysisPExe();
预测分析过程,主体实现过程按照算法4.1进行实现。
6)void CalNonOrTerminalMap();
计算非终结符分别对应的预测分析表的行号.
采用map类型进行存储,便于每次查找时,可以不使用循环就可以进行定位表格中的某个格子。
2.程序分析前的数据操作
(1)消除左递归
(2)找出元素的first集合与follow集合
3.构造预测分析表
根据算法4.2实现预测分析表的构造,并且加入了同步信息。
程序实现时输出的预测分析表如下所示:
其中空串使用“~”表示。
4.构造预测分析程序
(1) 根据算法4.1实现预测分析程序
(2)带有同步信息的分析表的错误处理
针对于两种情况的错误进行处理。
①分析栈的栈顶符号是终结符,但却与当前输入符号不匹配。
本程序中的处理方法:直接将栈顶的符号弹出。
②分析栈栈顶符号是非终结符号A,当前输入的符号a。
本程序中的处理方法:
a.若M[A,a]
是”error”
,那么移动指向字符的指针,识别下一个字符;
b.若M[A,a]
是”synch”
,那么从栈顶弹出A
。
实现的程序代码见附录。
(二)LR分析程序
1.数据结构及函数说明
//global variable
① map<string, int> title
; //首行符号
② map<string, int> States
; //状态符号
③ int actionendpos = 8, gotoendpos = 11;
//结束位置
④ string** LRTable;
//分析表
⑤ stack<string> StatesStack, SymbolStack;
//状态栈,符号栈
⑥ vector<string> ExpressionVec;
//存储表达式
⑦ vector<string> VecStatesStackStr, ``VecSymbolStackStr;
//存储状态栈的字符和字符栈的字符
//Function Description
⑧ map<int,string> DealData(string &str);
//数据读取处理函数
该函数用于处理文件读取的时,进行数据的提取,因为在文件格式中表格的存储方式是
按照格式:状态序号 + “:” + [num,S1][(,S5][E,2][T,3][F,4]的形式存储
经过此函数的处理之后,返回map<int,string>
类型的变量,键值对为key = 非终结符或者终结符,value = 分析动作或者非终结符号。
⑨ void ShowLRTable();
该函数用于输出LR分析表,遍历即可实现。
⑩ string StrInput();
待分析的字符串的输入,其中进行输入字串的末尾加上”$”结束标识符。
⑪ void InitStack()
状态栈与符号栈的初始化。
状态栈首先入栈”0”,开始状态
符号栈首先入栈”-”,开始符号
⑫ void ShowProcess(string & currentstr,string &expre,int Cptr)
分析过程的输出
⑬ void LRAnalysisFunction(string &str)
LR分析函数,该函数按照算法4.3进行实现。
2. 构造识别该文法所有活前缀的DFA
3.First集合与follow集合,构造该文法的LR分析表
4.编程实现算法4.3,构造LR分析程序
四.源程序
见附件(“LL(1).cpp”是方法二的程序实现源代码,”LR(0).cpp”是方法三的程序实现源代码)
五.可执行程序
1.见附件
2.由于许多数据不是采用直接在代码中赋值的操作,而是采用文件读取的方式,所以“LL(1)可执行文件”这个文件夹包含exe文件和执行文件需要进行数据读取的文本文件,必须保证这些文本文件与exe文件在同一个目录下才能运行。
3.由于许多数据不是采用直接在代码中赋值的操作,而是采用文件读取的方式,所以“LR(0)可执行文件”这个文件夹包含exe文件和执行文件需要进行数据读取的文本文件,必须保证这些文本文件与exe文件在同一个目录下才能运行。
4.“LL(1)可执行文件”中每一个文本作用:
(1)“expression.txt”存储的是生成式
(2)“FirstSet.txt”存储的是非终结符的first集合
(3)“FollowSet.txt”存储的是非终结符的follow集合
(4)“Nonterminal.txt”存储的是非终结符
(5)“Terminator.txt”存储的是终结符
5.“LR(0)可执行文件”中每一个文本的作用:
(1)“Action.txt”存储的是第一行action中的符号
(2)“Goto.txt”存储的是第一行goto中的符号
(3)“Expression.txt”存储的是生成式集合
(4)“LRAnalysisTable.txt”存储的是LR分析表
六.测试报告
测试时的注意事项:
需要注意的是,输入的字符串中,数字是阿拉伯数字输入,不是num。
比如:输入字符串“2+3*3/3(90-1)”进行验证分析即可。
1.LL(1)程序测试
(1)第一组测试
输入:
运行结果:
结果分析:
所给的测试样例是正确的样例。
经过手工验证可知,该分析过程正确。
(2)第二组测试
输入:
运行结果:
结果分析:
此测试样例为输入错误,进行错误处理的检测。
1.在”1+”的后面,第二个”+”使用到同步信息处理,分析表中的该位置为”synch”,那么弹出栈顶的符号,执行正确。
2.num(19)的后面缺少运算符,那么分析表中该位置是error,那么移动向前指针,执行正确。
2.SLR(1)程序测试
(1)第一组测试
输入:
运行结果:
结果分析:
测试样例符合文法规则,正确识别出字符,然后正常结束程序。
(2)第二组测试
输入:
运行结果:
结果分析:
测试样例符合文法规则,正确识别出字符,然后正常结束程序。
(3)第三组测试
输入:
运行结果:
结果分析:
该测试样例为错误的,不符合文法规则。
“2**1”,由于第二个”*”的后面缺少了运算的数值或者括号,那么导致程序中止运行。
下载源码和数据,请点击跳转 下载连接