实验二——自顶向下分析方法之表驱动LL(1)分析程序
来源:互联网 发布:js正则匹配域名 编辑:程序博客网 时间:2024/06/05 14:18
自顶向下分析方法之表驱动LL(1)分析程序分为三个部分:
- 非LL(1)文法转换为LL(1)文法;
- LL(1)文法的判别;
- 构造预测分析表和对输入符号串进行分析。
程序流程图:
非LL(1)文法转换为LL(1)文法
非LL(1)文法转换为LL(1)文法要分以下三步:
- 消除文法中一切左递归,包括直接左递归和间接左递归。
- 提取左公因子,消除回溯。
- 消除无用表达式。
一.消除文法中一切左递归
1.消除文法中一切左递归的算法
- 把文法中所有的非终结符按某一顺序排序,例如:
A1,A2,⋅⋅⋅,An - FOR
i := 1
TO N DO
BEGIN
FORj := 1
TOi-1
DO
BEGIN
若Aj 的所有产生式为
Aj→δ1 | δ2 |⋅⋅⋅| δk
将其替换形如Ai→Ajr的产生式得到
Aj→δ1r | δ2r |⋅⋅⋅| δkr
END
消除Ai 中的一切直接左递归。
END - 去掉无用产生式。
2.实现思路
因为消除左递归的算法中涉及到了很多插入和删除的操作,因此我选择用链表来实现上述算法。
(1).文法规则的预处理操作
- 首先先将文件中的内容,一行一行读取,将每一行读取到的内容用一个临时字符串字符串保存起来,字符串类型用STL中的string类型。这个字符串是临时保存每一行的规则。然后在声明一个保存字符串链表的链表,即为:
list<list<string> > l;
- 而后在声明一个临时的字符串链表,再对这一行的字符串做拆分处理,将每一个规则右部的每一个产生式均用一个新的临时字符串保存起来,然后再将这个产生式插入到新声明的字符串链表的尾部。当该行的字符串处理到末尾时,再将该临时的字符串数组插入到第一步声明的保存字符串链表的链表中。
- 而后再考虑下一行,并重复第二步直到所有规则均处理完毕。
(2).将文法中所有的间接左递归转换成直接左递归
- 有了前面预处理的过程,从而得知:
- 在保存字符串链表的链表中,从第一个结点到最后一个结点,保存的是文法的第一条规则到最后一条规则。
- 外层循环从上述链表的一个结点开始遍历,内层循环从链表的第二个结点开始遍历,遍历的时候判断:当前外层循环的左边非终结符与内层循环右部产生式有相同的非终结符。有的话则可以用外层循环的右部产生式替换掉该非终结符。
(3).消除文法中的所有直接左递归
- 可用如下思路消除文法中的所有直接左递归:
- 例如,对于文法G:
S -> Sa
S -> b
可改写为:
S -> bS'
S' -> aS' | ε
- 例如,对于文法G:
二.提取左公因子,消除回溯
提取左公因子分为以下两步:
- 将隐式左公因子转换成显式左公因子
- 提取左公因子
(1).将隐式左公因子转换成显式左公因子
如果有产生式的右部是以非终结符开始,那么在这种情况下对右部以非终结符开始的产生式用左部相同而右部以终结符开始的产生式进行替换。重复以上操作,直到所有的右部产生式都是以终结符开始。
(2).提取左公因子的算法
- 将文法写成一般形式:
A→αβ1|αβ2|⋅⋅⋅|αβn - 提取左公因子后变为:
A→α(β1|β2|⋅⋅⋅|βn) - 引进非终结符
A′ 后变为:A→αA′ A′→β1|β2|⋅⋅⋅|βn
若在
LL(1)文法的判别
LL(1)文法的判别要分以下四步:
- 求出能推出
ε 的非终结符。 - 计算FIRST集。
- 计算FOLLOW集。
- 计算SELECT集合。
一.求出能推出ε 的非终结符
计算能推出
(1).声明一个映射容器以存储左部非终结符是否能够推出
map<string, bool> relemptystr;
一开始map容器的映射值均为false。
(2).扫描文法中的产生式。
- 删除所有右部含有终结符的产生式,若这使得以某一非终结符为左部的所有产生式都被删除,说明该非终结符不能推出
ε ,则该非终结符对应的映射值依旧为false,不做修改。 - 若某一非终结符的某一产生式右部为
ε ,则将容器中对应该非终结符的映射值置为true,并从文法中删除该非终结符的所有产生式。
(3).扫描产生式右部的每一符号。
- 若扫描到的非终结符在容器中对应的映射值是“true”,则删去该非终结符;若这使产生式右部为空,则将产生式左部的非终结符在容器中对应的映射值是“true”,并删除以该非终结符为左部的所有产生式。
- 若扫描到的非终结符在容器中对应的映射值是“false”,则删去该产生式;若这使产生式左部非终结符的有关产生式都被删去,则该非终结符对应的映射值依旧为false,不做修改。
(4).重复(3),直到扫描完一遍文法的产生式,map容器中各非终结符对应的映射值再没有改变为止。
二.计算FIRST集
(1).根据
- 若
X∈VT ,则FIRST(X)={X} 。 - 若
X∈VN ,且有产生式X→a⋅⋅⋅,a∈VT ,则a∈FIRST(X) 。 - 若
X∈VN ,X→ε ,则ε∈FIRST(X) 。 - 若
X,Y1,Y2,⋅⋅⋅,Yn∈VN ,而有产生式X→Y1Y2⋅⋅⋅Yn 。当Y1,Y2,⋅⋅⋅,Yi−1⟹∗ε 时(其中1≤i≤n ),则FIRST(Y1)−{ε},FIRST(Y2)−{ε},⋅⋅⋅,FIRST(Yi−1)−{ε},FIRST(Yi) 都包含在FIRST(X) 中。 - 当4中所有
Yi⟹∗ε,(i=1,2,⋅⋅⋅,n) ,则FIRST(X)=FIRST(Y1)⋃FIRST(Y2)⋃⋅⋅⋅⋃FIRST(Yn)⋃{ε}
重复第2到第5步,直到每个符号的FIRST集合不再增大为止。
(2).计算每个产生式的右部符号串的开始符号集合
- 若符号串
α∈V∗,α=X1X2⋅⋅⋅Xn ,当X1 不能⟹∗ε ,则置FIRST(α)=FIRST(X1) 。 - 若对任何
j(1≤j≤i−1,2≤i≤n),ε∈FIRST(Xj),ε∉FIRST(Xi) ,则FIRST(α)=⋃j=1i−1(FIRST(Xj)−{ε})⋃FIRST(Xi) - 若对任何
j(1≤j≤n) ,FIRST(Xj) 都含有ε 时,则FIRST(α)=⋃j=1nFIRST(Xj)⋃{ε}
三.计算FOLLOW集
计算所有非终结符号
- 将#放到
FOLLOW(S) 中,其中S 是开始符号,而#是输入右端的结束标记。 - 如果存在一个产生式
A→αBβ ,那么FIRST(β) 中除ε 之外的所有符号都在FOLLOW(B) 中。 - 如果存在一个产生式
A→αB ,或存在产生式A→αBβ 且FIRST(β) 包含ε ,那么FOLLOW(A) 中的所有符号都在FOLLOW(B) 中。
四.计算SELECT集合
计算一个产生式的选择符号集SELECT。给定上下文无关文法的产生式
如果
构造预测分析表
//以下为构造预测分析表所用数据结构typedef struct node { string nonSym; //非终结符 string terminSym; //终结符 bool operator<(const node &other) const { //运算符重载 if (nonSym[0] == (other.nonSym)[0]) { return terminSym[0] < (other.terminSym)[0]; } return nonSym[0] < (other.nonSym)[0]; }}Node;map<Node, string> analyTable; //预测分析表set<string> nonSymSet; //SELECT集合产生式左部的非终结符集set<string> terminSymSet; //SELECT集合的终结符集
首先对每个终结符或’#’号用字符串存储
string terminSym;
如果终结符
Node node;node.nonSym = A;node.terminSym = a;
然后再把
所有没有定义的analyTable[node]均为出错的状况。为了使表简化,产生式的左部可以不写入表中,表中空白处为出错。经过以上处理之后,可得到如下预测分析表:
对输入符号串进行分析
以下是用预测分析程序、栈和预测分析表对输入串进行分析。栈的变化过程如下表所示:
完整输出:
完整代码:
#include <iostream>#include <fstream>#include <sstream>#include <list>#include <string>#include <vector>#include <map>#include <set>#include <cctype>#include <algorithm>#include <iomanip>#include <stack>using namespace std;const int INF = 0x3f3f3f3f;list< list<string> > gramRule; //用于存放所有的文法规则fstream infile; //读写操作,对打开的文件可进行读写操作vector<string> gramBuf; //暂存从文件中读取的文法规则map<string, bool> nonSymExist; //用于标记该左部非终结符是否已存在map<string, bool> relEmptyStr; //用于记录该左部非终结符是否能推出εmap<string, set<string> > firstSet; //用于记录左部非终结符和右部产生式的FIRST集map<string, set<string> > followSet; //用于记录左部非终结符的FOLLOW集map<string, set<string> > selectSet; //用于记录各产生式的SELECT集//以下为构造预测分析表所用数据结构typedef struct node { string nonSym; //非终结符 string terminSym; //终结符 bool operator<(const node &other) const { //运算符重载 if (nonSym[0] == (other.nonSym)[0]) { return terminSym[0] < (other.terminSym)[0]; } return nonSym[0] < (other.nonSym)[0]; }}Node;map<Node, string> analyTable; //预测分析表set<string> nonSymSet; //SELECT集合产生式左部的非终结符集set<string> terminSymSet; //SELECT集合的终结符集//函数声明部分void to_LL1_rule();void LL1_gram_judgment();void analysis();void open_file(string basePath);void read_file();void split_gram();void remove_left_recursion();void remove_left_common_factor();void merge();void get_release_empty_str();void get_first_set();void get_follow_set();int get_follow_set_size();void get_select_set();void output_all();void output_empty_str_result();string char_to_string(char ch);void output_all_set(string kind);void get_analysis_table();void output_analysis_table();void analysis_str(string input_str);void output_step(int step, stack<string> stk, string remain_str, string production);int main() { to_LL1_rule(); LL1_gram_judgment(); analysis(); return 0;}void to_LL1_rule() { string basePath = "/Users/adherer/Desktop/编译原理实验/实验/实验二——自顶向下分析方法/test/书本93.txt"; open_file(basePath); read_file(); split_gram(); remove_left_recursion(); remove_left_common_factor();}void LL1_gram_judgment() { //test //string basePath = "/Users/adherer/Desktop/编译原理实验/实验/实验二——自顶向下分析方法/test/emptystrtest.txt"; //open_file(basePath); //read_file(); //split_gram(); //merge(); get_release_empty_str(); get_first_set(); get_follow_set(); get_select_set();}void analysis() { string str; get_analysis_table(); cout << "请输入您要进行分析的字符串: " << endl; getline(cin, str); analysis_str(str);}void open_file(string basePath) { string testFilename = ""; //cout << "请输入要分析的文法所在txt文件(默认路径为test文件夹): "; //getline(cin, testFilename); infile.open(basePath + testFilename); while (!infile.is_open()) { cout << "文件不存在或者不可读!请重新输入" << endl; cout << "请输入测试文件名(默认路径为test文件夹):"; getline(cin, testFilename); infile.open(basePath + testFilename); }}void read_file() { string tempStr; while (getline(infile, tempStr)) { //getline读取有问题,要去搞清楚问题 //cout << "tempStr: " << tempStr << endl; if (tempStr.length() > 0) { gramBuf.push_back(tempStr); } }}void split_gram() { int gramSum = gramBuf.size(); int strLen = -1, start = -1; string tempStr = ""; for (int i = 0;i < gramSum; i++) { tempStr = gramBuf[i]; strLen = tempStr.size(); //cout << "tempStr: " << tempStr << endl; list<string> tempList; //声明一个临时链表以存放每个非终结符的右部产生式 //寻找右部产生式的开始标志 -> for (int j = 0;j < strLen;j++) { if (tempStr[j] == '>') { tempList.push_back(tempStr.substr(0, j - 1)); //加入文法左部的非终结符 nonSymExist[tempStr.substr(0, j - 1)] = true; start = j + 1; break; } } //根据|拆分每个右部产生式 for (int j = start;j < strLen;j++) { if (tempStr[j] == '|') { tempList.push_back(tempStr.substr(start, j - start)); start = j + 1; } } //加入最后一个右部产生式 //cout << "最后一个右部产生式: " << tempStr.substr(start) << endl; tempList.push_back(tempStr.substr(start)); gramRule.push_back(tempList); //将新拆分好的文法规则插至链表最后 } cout << "------------------------" << endl; cout << "拆分好的文法规则为: " << endl; output_all(); cout << "------------------------" << endl;}/* * 消除左递归 */void remove_left_recursion() { list< list<string> >::iterator it_i, it_j; //分别为外层循环和内层循环的临时变量 list<string>::iterator it_k, it_temp; for (it_i = gramRule.begin(); it_i != gramRule.end(); it_i++) { for (it_j = gramRule.begin(); it_j != it_i; it_j++) { it_k = it_i -> begin(); /** * 遍历查找外层循环对应的链表的右部产生式,查找是否有Ai->Ajr形式的右部产生式 */ for (it_k++; it_k != it_i -> end();) { string searchStr = *it_k; string srcStr = it_j -> front(); bool isfind = false; if (isupper(searchStr[0])) { //右部产生式的首字母为非终结符时,才可能出现左递归的情况 for (int i = 0;i < searchStr.length();i++) { if (isupper(searchStr[i])) { if(searchStr.substr(i, srcStr.size()) == srcStr) { //找到了Ai->Ajr形式的右部产生式,则将其替换Ai的右部产生式 isfind = true; it_temp = it_j -> begin(); //用Aj的右部产生式替换Ai->Ajr形式的右部产生式 for (it_temp++; it_temp != it_j -> end(); it_temp++) { //前插法 it_i -> insert(it_k, searchStr.substr(0, i) + *it_temp + searchStr.substr(i+1)); } it_k = it_i -> erase(it_k); //删除替换前的结点,返回删除结点的后一个结点的迭代器 } } } } if (!isfind) { //没有找到可替换的非终结符,则迭代器自增,继续向后查找 it_k++; } } } /** * 判断替换后的规则是否存在直接左递归,若存在,则将左递归转换成右递归 */ bool hasRecur = false; it_temp = it_i -> begin(); vector<string> tempStrs; //用于存放左递归部分的右部产生式,即E -> E + T,则存放+T for (it_temp++; it_temp != it_i -> end(); ) { //查找是否有E -> E...形式的左递归 if (it_temp -> substr(0, (it_i -> front()).size()) == it_i -> front()) { hasRecur = true; //表示规则中存在左递归 tempStrs.push_back(it_temp -> substr((it_i -> front()).size())); it_temp = it_i -> erase(it_temp); //删除含有左递归的结点 } else { it_temp++; } } if (hasRecur) { //如果含有左递归,则将其转化成右递归再存入文法规则中 it_temp = it_i -> begin(); for (it_temp++; it_temp != it_i -> end(); it_temp++) { //引入新的非终结符 *it_temp += it_i -> front() + "'"; } for (int i = 0; i < tempStrs.size(); i++) { tempStrs[i] += it_i -> front() + "'"; } list<string> newGram; //引入新的右递归规则 string tempnonsym = it_i -> front() + "'"; while (nonSymExist[tempnonsym]) { tempnonsym += "'"; //该非终结符已经存在,因此要用新的终结符 } newGram.push_back(tempnonsym); nonSymExist[tempnonsym] = true; for (int i = 0; i < tempStrs.size(); i++) { newGram.push_back(tempStrs[i]); } newGram.push_back("ε"); list< list<string> >::iterator insert_temp = it_i; gramRule.insert(++insert_temp, newGram); } } cout << "------------------------" << endl; cout << "消除左递归后的文法规则为: " << endl; output_all(); cout << "------------------------" << endl;}/** * 提取左公因子 */void remove_left_common_factor() { list< list<string> >::iterator it_i, it_j; //分别为外层循环和内层循环的临时变量 list<string>::iterator it_k, it_temp; bool isrecursion = false; for (it_i = gramRule.begin(); it_i != gramRule.end(); it_i++) { it_k = it_i -> begin(); //左部非终结符 //cout << "左部非终结符*it_k = " << *it_k << endl; for(it_k++; it_k != it_i -> end(); ) { string srcStr = *it_k; bool isfind = false, hassym = false; int symindex = -1; if (isupper(srcStr[0])) { string searchStr; if (srcStr.size() > 1 && !isalpha(srcStr[1])) { hassym = true; for (int i = 1;i < srcStr.size();i++) { //寻找最后一个"'"的下标 if (srcStr[i] != '\'') { symindex = i; break; } } symindex = symindex == -1 ? srcStr.size() : symindex; //正常遍历完字符串,说明最后一个字符是"'" searchStr = srcStr.substr(0, symindex); //右部以非终结符开头的产生式(带') } else { searchStr = srcStr.substr(0, 1); //右部以非终结符开头的产生式(不带') } //cout << "symindex = " << symindex << endl; //cout << "srcStr = " << srcStr << endl; //cout << "searchStr = " << searchStr << endl; for (it_j = gramRule.begin(); it_j != gramRule.end(); it_j++) { it_temp = it_j -> begin(); //cout << "左部非终结符*it_temp = " << *it_temp << endl; if (*it_temp == searchStr) { //找到了与上述非终结符相同的左部非终结符 for(it_temp++; it_temp != it_j -> end(); it_temp++) { string tempStr = *it_temp; //cout << "右部产生式tempStr = " << tempStr << endl; if (!isupper(tempStr[0])) { //找到了该非终结符右部以终结符开始的表达式 isrecursion = true; isfind = true; //用左部非终结符的以终结符开始的右部产生式替换上述右部的非终结符 it_i -> insert(it_k, tempStr + srcStr.substr(hassym ? symindex : 1)); } } } } } if (isfind) { //找到了并替换成该非终结符右部以终结符开始的表达式 it_k = it_i -> erase(it_k); //删除替换前的结点,返回删除结点的后一个结点的迭代器 } else { //没有替换该非终结符右部以终结符开始的表达式,则继续下一个寻找 it_k++; } } } merge(); /** * 提取左公因子 */ for (it_i = gramRule.begin(); it_i != gramRule.end();it_i++) { it_k = it_i -> begin(); for (it_k++; it_k != it_i -> end(); it_k++) { vector<string> tempStrs; //用于存放左公因子右部产生式除公因子外的剩余部分 bool issamefind = false; map<string, bool> tempsign; it_temp = it_k; int commonlen = it_k -> size(); /* 提取左公因子部分出现了一点小的bug: * 1.左公因子的长度可能大于1,刚开始写的时候没有考虑到这个问题 * 2.可能存在如下的情况,但自己的程序无法解决: A->abcdS|abcS'|aB|c * 这样的话要先找到提取的左公因子长度(最短的),再进行提取操作 * 还要考虑到这种情况: A->abcS|abS' */ //查找有左公因子的右部产生式,并求出他们的最短左公因子长度 for (it_temp++; it_temp != it_i -> end(); it_temp++) { if ((*it_temp)[0] == (*it_k)[0]) { bool issubstr = true; for (int i = 0; i < min(it_temp -> size(), it_k -> size()); i++) { //左公因子长度可能大于1 if ((*it_temp)[i] != (*it_k)[i]) { issubstr = false; //取所有左公因子最短的部分提取 commonlen = min(commonlen, i); break; } } if (issubstr) { //正常遍历结束,说明其中一个产生式是另外一个产生式的子串 int sublen = min(it_temp -> size(), it_k -> size()); commonlen = min(commonlen, sublen); } issamefind = true; tempsign[*it_temp] = true; //用于标记要提取左公因子的右部产生式 //cout << "*it_temp = " << *it_temp << endl; } } if (issamefind) { //提取左公因子操作 for (list<string>::iterator iter = it_k; iter != it_i -> end();) { if (tempsign[*iter]) { tempStrs.push_back(iter -> substr(commonlen) == "" ? "ε" : iter -> substr(commonlen)); iter = it_i -> erase(iter); //删除该结点,并将迭代器指针后移 } else { iter++; } } list<string> newGram; //引入新的非终结符规则 string tempnonsym = it_i -> front() + "'"; while (nonSymExist[tempnonsym]) { tempnonsym += "'"; //该非终结符已经存在,因此要用新的终结符 } //将旧规则的公因子部分提取 tempStrs.push_back(it_k -> substr(commonlen) == "" ? "ε" : it_k -> substr(commonlen)); //旧的规则引入新的非终结符,取max防止越界或者旧规则非公因子部分有剩余 it_k -> replace(commonlen, max(tempnonsym.length(), it_k -> size() - commonlen), tempnonsym); //cout << "*it_k = " << *it_k << endl; newGram.push_back(tempnonsym); nonSymExist[tempnonsym] = true; for (int i = 0; i < tempStrs.size(); i++) { newGram.push_back(tempStrs[i]); } list< list<string> >::iterator insert_temp = it_i; gramRule.insert(++insert_temp, newGram); //前插法,插在当前结点的后一位 } } } if (isrecursion) { remove_left_common_factor(); //递归执行 } else { cout << "------------------------" << endl; cout << "提取左公因子后的文法规则为: " << endl; output_all(); cout << "------------------------" << endl; }}/** * 左部产生式相同的文法规则合并,方便下一步的提取左公因子 */void merge() { list< list<string> >::iterator it_i, it_j; list<string>::iterator it_k, it_temp; for (it_i = gramRule.begin(); it_i != gramRule.end(); it_i++) { it_j = it_i; for(it_j++; it_j != gramRule.end();) { if (it_j -> front() == it_i -> front()) { //合并操作 it_k = it_i -> begin(); //cout << "*it_k = " << *it_k << endl; it_k++; //指向右部的第一个产生式 it_temp = it_j -> begin(); for (it_temp++; it_temp != it_j -> end(); it_temp++) { //前插法 it_i -> insert(it_k, *it_temp); } it_j = gramRule.erase(it_j); } else { it_j++; } } } cout << "------------------------" << endl; cout << "合并后的文法规则为: " << endl; output_all(); cout << "------------------------" << endl;}//求出能推出ε的非终结符void get_release_empty_str() { int count_Result = 0; list< list<string> > copyGramRule = gramRule; list< list<string> >::iterator it_i; list<string>::iterator it_k, it_temp; for (it_i = copyGramRule.begin(); it_i != copyGramRule.end();) { it_k = it_i -> begin(); //左部非终结符 for (it_k++; it_k != it_i -> end();) { string tempStr = *it_k; bool isdellower = false; if (tempStr.compare("ε") == 0) { count_Result++; relEmptyStr[it_i -> front()] = true; //cout << it_i -> front() << " 对应 " << relEmptyStr[it_i -> front()] << endl; it_temp = it_i -> begin(); for (it_temp++; it_temp != it_i -> end(); ) { //删除该非终结符的所有产生式 it_temp = it_i -> erase(it_temp); } break; } for (int i = 0;i < tempStr.length();i++) { if (!isupper(tempStr[i])) { isdellower = true; it_k = it_i -> erase(it_k); //删除所有右部含有终结符的产生式 break; } } if (!isdellower) { it_k++; } } //如果该左部非终结符无ε右部产生式,并且右部产生式全部被删除,则说明该左部产生式不能推出ε,并删除该左部产生式 if (it_i -> size() == 1 && relEmptyStr.find(it_i -> front()) == relEmptyStr.end()) { count_Result++; relEmptyStr[it_i -> front()] = false; //cout << it_i -> front() << " 对应 " << relEmptyStr[it_i -> front()] << endl; it_i = copyGramRule.erase(it_i); } else if ((relEmptyStr.find(it_i -> front())) -> second == true) { it_i = copyGramRule.erase(it_i); } else { it_i++; } } //接下来是第(3)、(4)步的处理 //output_empty_str_result(); //cout << "count_Result = " << count_Result << endl; //cout << "还剩下" << copyGramRule.size() << "条文法规则" << endl; //cout << "relEmptyStr的映射数量为: " << relEmptyStr.size() << endl; while (count_Result != gramRule.size()) { //循环终止条件,直到所有的非终结符都处理完毕 for (it_i = copyGramRule.begin(); it_i != copyGramRule.end();) { it_k = it_i -> begin(); //左部非终结符 for (it_k++; it_k != it_i -> end();) { string::iterator iter = it_k -> begin(); int count_times = 0, strLen = it_k -> size(); for (; iter != it_k -> end();) { string nonStr = char_to_string(*iter); //非终结符,字符转换成字符串 if ((relEmptyStr.find(nonStr)) -> second == true) { count_times++; iter = it_k -> erase(iter); //true则删去该非终结符 } else { it_k = it_i -> erase(it_k); //false则删去该产生式 break; } } if (count_times == strLen) { //最终产生式右部为空,说明该产生式的每个非终结符都能够推出ε count_Result++; relEmptyStr[it_i -> front()] = true; //cout << it_i -> front() << " 对应 " << relEmptyStr[it_i -> front()] << endl; it_temp = it_i -> begin(); for (it_temp++; it_temp != it_i -> end(); ) { //删除该非终结符的所有产生式 it_temp = it_i -> erase(it_temp); } break; } } //如果该左部非终结符无能推出ε的右部产生式,并且右部产生式全部被删除,则说明该左部产生式不能推出ε if (it_i -> size() == 1 && relEmptyStr.find(it_i -> front()) == relEmptyStr.end()) { count_Result++; relEmptyStr[it_i -> front()] = false; //cout << it_i -> front() << " 对应 " << relEmptyStr[it_i -> front()] << endl; it_i = copyGramRule.erase(it_i); } else if ((relEmptyStr.find(it_i -> front())) -> second == true) { it_i = copyGramRule.erase(it_i); } else { it_i++; } } } output_empty_str_result();}//计算文法的FIRST集void get_first_set() { void output_set(set<string> s); list< list<string> >::iterator it_i; list<string>::iterator it_k, it_temp; list< list<string> > copyGramRule = gramRule; map <string, bool> isCountFirst; //用于记录左部非终结符是否已经计算完开始符号集 //计算左部非终结符的开始符号集 while (copyGramRule.size() > 0) { for (it_i = copyGramRule.begin(); it_i != copyGramRule.end();) { //cout << "it_i -> front() = " << it_i -> front() << endl; set<string> tempSet; //第(3)步的处理 if ((relEmptyStr.find(it_i -> front())) -> second == true) { //如果该非终结符能够推出ε,则将ε加入集合 tempSet.insert("ε"); } it_k = it_i -> begin(); for (it_k++; it_k != it_i -> end();) { string tempStr = *it_k; //cout << "tempStr = " << tempStr << endl; if (tempStr.size() == 0) { it_k = it_i -> erase(it_k); } else if (tempStr.compare("ε") == 0) { it_k = it_i -> erase(it_k); //如果遍历到的右部产生式为ε,则跳过不继续以下操作 } else if (!isupper(tempStr[0])) { //右部产生式以终结符开头,则将该终结符以字符串的形式加入集合,并删除该右部产生式 tempSet.insert(char_to_string(tempStr[0])); //cout << "插入的是: " << char_to_string(tempStr[0]) << endl; it_k = it_i -> erase(it_k); } else { //右部产生式以非终结符开头 //flag用于记录从头开始非终结符的个数,times用于记录产生式中前flag非终结符能够推出ε的非终结符个数 int flag = -1, times = 0; for (int i = 0; i < tempStr.size(); i++) { if (!isupper(tempStr[i])) { flag = i; } } flag = (flag == -1 ? tempStr.size() : flag); //正常遍历结束则说明都是非终结符 //cout << "flag = " << flag << endl; for (int i = 0; i < flag; i++) { string nonStr = char_to_string(tempStr[i]); //非终结符,字符转换成字符串 if ((relEmptyStr.find(nonStr)) -> second == true) { times++; } else { break; } } //cout << "times = " << times << endl; //第(5)步的处理 if (times == tempStr.size()) { string::iterator str_iter = it_k -> begin(); //迭代器遍历string for (; str_iter != it_k -> end();) { string nonStr = char_to_string(*str_iter); //非终结符,字符转换成字符串 if ((isCountFirst.find(nonStr)) -> second == true) { //已经计算过FIRST集 //cout << "大满贯nonStr = " << nonStr << endl; set<string>::iterator set_it = firstSet[nonStr].begin(); for (; set_it != firstSet[nonStr].end(); set_it++) { tempSet.insert(*set_it); } str_iter = it_k -> erase(str_iter); //该非终结符已经参与过"计算",因此删去 } else { str_iter++; //尚未计算过FIRST集,则指针前移 } } tempSet.insert("ε"); } else { //第(4)步的处理 string::iterator str_iter = it_k -> begin(); //迭代器遍历string for (int i = 0;i < times;i++) { string nonStr = char_to_string(*str_iter); //非终结符,字符转换成字符串 //cout << "里面的nonStr = " << nonStr << endl; if ((isCountFirst.find(nonStr)) -> second == true) { //已经计算过FIRST集 set<string>::iterator set_it = firstSet[nonStr].begin(); for (; set_it != firstSet[nonStr].end(); set_it++) { //cout << "后面的*set_it = " << *set_it << endl; if (set_it -> compare("ε") == 0) { //实现FIRST(...) - {ε}操作 continue; } else { tempSet.insert(*set_it); } } //cout << "*it_k = " << *it_k << endl; //cout << "*str_iter = " << *str_iter << endl; str_iter = it_k -> erase(str_iter); //该非终结符已经参与过"计算",因此删去 cout << *str_iter << endl; } else { str_iter++; } } //最后加入Yi的FIRST集 string nonStr = char_to_string(tempStr[times]); //非终结符,字符转换成字符串 //cout << "外面的nonStr = " << nonStr << endl; //有隐患>_< if ((isCountFirst.find(nonStr)) -> second == true) { set<string>::iterator set_it = firstSet[nonStr].begin(); for (; set_it != firstSet[nonStr].end(); set_it++) { tempSet.insert(*set_it); } str_iter = it_k -> erase(it_k -> begin() + tempStr.find(tempStr[times])); //Yi参与完"计算",删去 } } if (tempStr.size() == 0) { //该右部产生式全部计算完毕 it_k = it_i -> erase(it_k); } else { it_k++; } } } //尚未保存任何关于该非终结符的结果,则直接插入即可. if (firstSet.find(it_i -> front()) == firstSet.end()) { firstSet[it_i -> front()] = tempSet; } else { //已经有保存结果,则接在后面 set<string>::iterator temp_set_it = tempSet.begin(); for (; temp_set_it != tempSet.end(); temp_set_it++) { firstSet[it_i -> front()].insert(*temp_set_it); } } if (it_i -> size() == 1) { //左部非终结符的右部产生式全部计算完毕 //cout << "it_i -> front()的FIRST集已计算完毕: " << it_i -> front() << endl; //output_set(tempSet); isCountFirst[it_i -> front()] = true; it_i = copyGramRule.erase(it_i); } else { it_i++; } } } cout << "------------------------" << endl; cout << "所有左部非终结符的FIRST集为: " << endl; output_all_set("FIRST"); cout << "------------------------" << endl; //计算右部符号串的FIRST集合 copyGramRule = gramRule; for (it_i = copyGramRule.begin(); it_i != copyGramRule.end();it_i++) { it_k = it_i -> begin(); for (it_k++; it_k != it_i -> end(); it_k++) { set<string> tempSet; string tempStr = *it_k; string firstStr = char_to_string(tempStr[0]); //考虑第(1)种情况 if (tempStr.compare("ε") == 0) { //空串则为自身 //cout << "tempStr = " << tempStr << endl; tempSet.insert("ε"); } else if (!isupper(tempStr[0])) { //以终结符开头 tempSet.insert(firstStr); } else if ((relEmptyStr.find(firstStr)) -> second == false) { set<string>::iterator iter = (firstSet[firstStr]).begin(); for (; iter != (firstSet[firstStr]).end(); iter++) { tempSet.insert(*iter); } } else { int times = 0; //标记从头开始有多少个连续的非终结符可以推出ε for (int i = 0;i < tempStr.size(); i++) { string nonStr = char_to_string(tempStr[i]); //非终结符,字符转换成字符串 if ((relEmptyStr.find(nonStr)) -> second == true) { times++; } else { break; } } //考虑第(3)种情况 if (times == tempStr.size()) { string::iterator str_iter = it_k -> begin(); //迭代器遍历string for (; str_iter != it_k -> end(); str_iter++) { string nonStr = char_to_string(*str_iter); //非终结符,字符转换成字符串 set<string>::iterator set_it = firstSet[nonStr].begin(); for (; set_it != firstSet[nonStr].end(); set_it++) { tempSet.insert(*set_it); } } tempSet.insert("ε"); } else { //考虑第(2)种情况 string::iterator str_iter = it_k -> begin(); //迭代器遍历string for (int i = 0;i < times;i++) { string nonStr = char_to_string(*str_iter); //非终结符,字符转换成字符串 set<string>::iterator set_it = firstSet[nonStr].begin(); for (; set_it != firstSet[nonStr].end(); set_it++) { if (set_it -> compare("ε") == 0) { //实现FIRST(...) - {ε}操作 continue; } else { tempSet.insert(*set_it); } } str_iter++; } //最后加入Xi的FIRST集(Xi可能是终结符也可能是非终结符) string nonStr = char_to_string(tempStr[times]); //字符转换成字符串 if (!isupper(tempStr[times])) { tempSet.insert(nonStr); } else { set<string>::iterator set_it = firstSet[nonStr].begin(); for (; set_it != firstSet[nonStr].end(); set_it++) { tempSet.insert(*set_it); } } } } //cout << "tempStr的集合如下: " << tempStr << endl; //output_set(tempSet); firstSet[tempStr] = tempSet; } } cout << "------------------------" << endl; cout << "所有左部非终结符和每个产生式的右部符号串的FIRST集为: " << endl; output_all_set("FIRST"); cout << "------------------------" << endl;}/** * 想不出好的实现方式T_T,硬上>_< */void get_follow_set() { vector<string> nonSymStr; //用于存放所有需要求解FOLLOW集的非终结符 list< list<string> >::iterator it_i; list<string>::iterator it_temp; set<string> tempSet; for (it_i = gramRule.begin(); it_i != gramRule.end(); it_i++) { nonSymStr.push_back(it_i -> front()); } tempSet.insert("#"); followSet[nonSymStr[0]] = tempSet; int oldsize = -1, newsize = INF; while (oldsize != newsize) { oldsize = get_follow_set_size(); for (it_i = gramRule.begin(); it_i != gramRule.end(); it_i++) { it_temp = it_i -> begin(); for (it_temp++;it_temp != it_i -> end(); it_temp++) { int bound_value = 2; string tempStr = *it_temp; if (tempStr.find("'") < tempStr.size()) { //右部产生式有' bound_value += 1; } if (tempStr.size() < bound_value) { continue; } else if (tempStr.size() == bound_value) { //考虑A→αB的情况 if (relEmptyStr[tempStr.substr(1)] == true) { //考虑=>ε的情况 set<string> s = followSet[it_i -> front()]; set<string>::iterator set_it; //FOLLOW(A)加入FOLLOW(B) for (set_it = s.begin(); set_it != s.end(); set_it++) { (followSet[it_i -> front()]).insert(*set_it); } } } else { //拆分字符 vector<string> symbols; for (int i = 0; i < tempStr.size(); i++) { if (tempStr[i + 1] == '\'') { symbols.push_back(tempStr.substr(i, 2)); i++; } else { symbols.push_back(tempStr.substr(i, 1)); } } //cout << "symbols.size() = " << symbols.size() << endl; //for (int i = 0; i < symbols.size(); i++) { // cout << symbols[i] << " "; //} //cout << endl; for (int i = 0; i < symbols.size() - 1; i++) { for (int j = i + 1; j < symbols.size(); j++) { if (!isupper(symbols[j][0])) { //终结符不考虑FOLLOW集 break; } bool relEmpty = false; if (j + 1 < symbols.size()) { //考虑A→αBβ的情况 if (!isupper(symbols[j + 1][0])) { (followSet[symbols[j]]).insert(symbols[j + 1]); } else { set<string> s = firstSet[symbols[j + 1]]; set<string>::iterator set_it; for (set_it = s.begin(); set_it != s.end(); set_it++) { //加入FIRST(β)的非空元素 if (set_it -> compare("ε") == 0) { continue; } else { (followSet[symbols[j]]).insert(*set_it); } } if (relEmptyStr[symbols[j + 1]] == true) { //考虑=>ε的情况 relEmpty = true; } } } if ((j + 1 == symbols.size()) || (relEmpty == true)) { //考虑A→αB的情况 set<string> s = followSet[it_i -> front()]; set<string>::iterator set_it; //FOLLOW(A)加入FOLLOW(B) for (set_it = s.begin(); set_it != s.end(); set_it++) { (followSet[symbols[j]]).insert(*set_it); } } } } } } } newsize = get_follow_set_size(); //cout << "oldsize = " << oldsize << "newsize = " << newsize << endl; } cout << "------------------------" << endl; cout << "各非终结符的FOLLOW集合计算如下: " << endl; output_all_set("FOLLOW"); cout << "------------------------" << endl;}int get_follow_set_size() { int sum = 0; map<string, set<string> >::iterator fol_it; for (fol_it = followSet.begin(); fol_it != followSet.end(); fol_it++) { sum += (fol_it -> second).size(); } return sum;}void get_select_set() { list< list<string> >::iterator it_i; list<string>::iterator it_k; for (it_i = gramRule.begin(); it_i != gramRule.end();it_i++) { it_k = it_i -> begin(); for (it_k++; it_k != it_i -> end(); it_k++) { set<string> tempSet; bool relempty = false; string tempStr = *it_k; //cout << "tempStr = " << tempStr << endl; int times = 0; //记录右部产生式能够推出空串的字符数量 if (tempStr.compare("ε") == 0) { //考虑规则(2) relempty = true; } else { for (int i = 0;i < tempStr.size(); i++) { string str; if (i < tempStr.size() - 1 && tempStr[i+1] == '\'') { str = tempStr.substr(i, 2); i++; } else { str = char_to_string(tempStr[i]); } //cout << "str = " << str << endl; map<string, bool>::iterator temp_it = relEmptyStr.find(str); if (temp_it != relEmptyStr.end()) { if (temp_it -> second == true) { times++; } } } } if (times == tempStr.size() || relempty == true) { //考虑规则(2) //cout << "规则(2)的tempStr: " << tempStr << endl; //cout << "times = " << times << endl; //cout << (relEmptyStr.find("i")) -> second << endl; set<string>::iterator set_it = firstSet[tempStr].begin(); for (; set_it != firstSet[tempStr].end(); set_it++) { if (set_it -> compare("ε") == 0) { //实现FIRST(...) - {ε}操作 continue; } else { tempSet.insert(*set_it); } } set_it = followSet[it_i -> front()].begin(); for (; set_it != followSet[it_i -> front()].end(); set_it++) { tempSet.insert(*set_it); //实现+FOLLOW集的操作 } } else { set<string>::iterator set_it = firstSet[tempStr].begin(); for (; set_it != firstSet[tempStr].end(); set_it++) { //cout << *set_it << endl; tempSet.insert(*set_it); } } string expression = it_i -> front() + "->" + tempStr; //cout << "expression = " << expression << endl; selectSet[expression] = tempSet; } } cout << "------------------------" << endl; cout << "每个产生式的SELECT集合计算如下: " << endl; output_all_set("SELECT"); cout << "------------------------" << endl;}//根据SELECT()集合构造预测分析表void get_analysis_table() { map<string, set<string> >::iterator sel_it; for (sel_it = selectSet.begin(); sel_it != selectSet.end(); sel_it++) { string ruleStr = sel_it -> first; set<string> nonSet = sel_it -> second; string nonStr, proStr; //cout << "ruleStr = " << ruleStr << endl; if (ruleStr[1] != '\'') { //不含有'的左部表达式 nonStr = ruleStr.substr(0, 1); //非终结符 } else { nonStr = ruleStr.substr(0, 2); //非终结符 } nonSymSet.insert(nonStr); proStr = ruleStr.substr(ruleStr.find("-")); //产生式部分 //cout << "proStr = " << proStr << endl; for (set<string>::iterator iter = nonSet.begin(); iter != nonSet.end(); iter++) { Node temp; temp.nonSym = nonStr; temp.terminSym = *iter; analyTable[temp] = proStr; terminSymSet.insert(*iter); } } cout << "------------------------" << endl; cout << "根据SELECT集构造的预测分析表如下: " << endl; output_analysis_table(); cout << "------------------------" << endl;}//对输入串进行分析void analysis_str(string input_str) { map<Node, string>::iterator temp_it; stack<string> analy_stk; int step = 1, i; analy_stk.push("#"); analy_stk.push("E"); cout << std::left << setfill(' ') << setw(15) << "步骤"; cout << std::left << setfill(' ') << setw(15) << "分析栈"; cout << std::left << setfill(' ') << setw(20) << "剩余输入串"; cout << std::left << setfill(' ') << setw(25) << "推导所用产生式或匹配" << endl; //分析过程 for (i = 0;i < input_str.size();) { if (analy_stk.size() == 1) { break; } string topStr = analy_stk.top(); //cout << "topStr = " << topStr << endl; if (topStr[0] == input_str[i]) { //匹配的情况 output_step(step++, analy_stk, input_str.substr(i), topStr + "匹配"); analy_stk.pop(); i++; } else { bool isfind = false; for (temp_it = analyTable.begin(); temp_it != analyTable.end(); temp_it++) { Node tempnode = temp_it -> first; if (tempnode.nonSym == topStr && tempnode.terminSym == char_to_string(input_str[i])) { string proStr = temp_it -> second; //cout << "proStr = " << proStr << endl; output_step(step++, analy_stk, input_str.substr(i), topStr + proStr); isfind = true; analy_stk.pop(); if (proStr.substr(2).compare("ε") == 0) { //空串则不执行下面的步骤 break; } for (int i = proStr.size() - 1; proStr[i] != '>' ;i--) { //推导所用产生式 if (proStr[i] == '\'') { analy_stk.push(proStr.substr(i - 1, 2)); i--; } else { analy_stk.push(char_to_string(proStr[i])); } } break; } } if (!isfind) { //出错的情况 break; } } } if (analy_stk.top() == "#" && i == input_str.size() - 1) { output_step(step++, analy_stk, "#", "接受"); } else { output_step(step++, analy_stk, input_str.substr(i), "出错!"); }}void output_step(int step, stack<string> stk, string remain_str, string production) { string stkStr = ""; while (!stk.empty()) { stkStr += stk.top(); stk.pop(); } string reverseStr = ""; for (int i = stkStr.size() - 1; i >= 0;i--) { if (stkStr[i] == '\'') { reverseStr += stkStr.substr(i - 1, 2); i--; } else { reverseStr += stkStr.substr(i, 1); } } cout << std::left << setfill(' ') << setw(15) << step; cout << std::left << setfill(' ') << setw(15) << reverseStr; cout << std::left << setfill(' ') << setw(20) << remain_str; cout << std::left << setfill(' ') << setw(25) << production << endl;}/* * 去除无用表达式 * 该功能未实现 */void remove_unnecessary_rule() {}void output_all() { list< list<string> >::iterator iter; for (iter = gramRule.begin(); iter != gramRule.end(); iter++) { list<string> tempList = *iter; cout << tempList.front() << "->"; tempList.pop_front(); while (!tempList.empty()) { cout << tempList.front(); tempList.pop_front(); if (!tempList.empty()) { cout << "|"; } } cout << endl; } }void output_empty_str_result() { map<string, bool>::iterator iter = relEmptyStr.begin(); for (; iter != relEmptyStr.end(); iter++) { cout << iter -> first << " " << iter -> second << endl; }}string char_to_string(char ch) { stringstream stream; stream << ch; return stream.str();}void output_all_set(string kind) { map<string, set<string> >::iterator it_i; map<string, set<string> > tempSet; if (kind.compare("FIRST") == 0) { tempSet = firstSet; } else if (kind.compare("FOLLOW") == 0) { tempSet = followSet; } else { tempSet = selectSet; } for (it_i = tempSet.begin(); it_i != tempSet.end(); it_i++) { //cout << "我的size = " << (it_i -> second).size(); cout << kind << "( " << it_i -> first << " ) = { "; set<string>::iterator it_temp = (it_i -> second).begin(); for(; it_temp != (it_i -> second).end(); it_temp++) { if (it_temp == (it_i -> second).begin()) { cout << *it_temp; } else { cout << ", " << *it_temp; } } cout << " }" << endl; }}void output_set(set<string> s) { set<string>::iterator iter = s.begin(); for (; iter != s.end();iter++) { cout << *iter << " "; } cout << endl;}void output_analysis_table() { map<Node, string>::iterator temp_it; set<string>::iterator nonset_it, terminset_it; cout << setiosflags(ios::left); //文本左对齐 cout << std::left << setfill(' ') << setw(10) << ""; for (terminset_it = terminSymSet.begin(); terminset_it != terminSymSet.end(); terminset_it++) { cout << std::left << setfill(' ') << setw(10) << *terminset_it; } cout << endl; for (nonset_it = nonSymSet.begin(); nonset_it != nonSymSet.end(); nonset_it++) { cout << std::left << setfill(' ') << setw(10) << *nonset_it; for (terminset_it = terminSymSet.begin(); terminset_it != terminSymSet.end(); terminset_it++) { bool isfind = false; for (temp_it = analyTable.begin(); temp_it != analyTable.end(); temp_it++) { Node tempnode = temp_it -> first; if (tempnode.nonSym == *nonset_it && tempnode.terminSym == *terminset_it) { isfind = true; cout << std::left << setfill(' ') << setw(10) << analyTable[tempnode]; break; } } if (!isfind) { cout << std::left << setfill(' ') << setw(10) << ""; } } cout << endl; }}
- 实验二——自顶向下分析方法之表驱动LL(1)分析程序
- 自顶向下语法分析方法:LL(1)文法的判别
- LL(1)文法分析,自上向下
- 编译原理之自顶向下分析
- 语法分析 自顶向下分析
- 自顶向下深入分析Netty(二)--线程模型
- python自顶向下的设计方法进行体育竞技分析
- 自顶向下分析Binder【1】—— Binder实例篇
- 自顶向下学搜索引擎——北大天网搜索引擎TSE分析及完全注释[6]倒排索引的建立的程序分析(1)
- 计算机网络自顶向下方法之一一一第一章 之二
- 不确定的自顶向下的分析思想和确定的自顶向下的分析方法
- 计算机网络—自顶向下方法 翻译(1)
- 自顶向下学搜索引擎——北大天网搜索引擎TSE分析及完全注释[2]路过查询处理程序
- 自顶向下的语法分析LL(1)
- 自顶向下深入分析Netty(四)--EventLoop-1
- 语法分析笔记自顶向下分析
- 《数据结构与算法分析》详细对比自顶向下与自底向上红黑树——C实现自顶向下插入与删除
- 自顶向下学搜索引擎——北大天网搜索引擎TSE分析及完全注释[3]来到关键字分词及相关性分析程序
- linux下开机自动启动tomcat
- dui UIDesigner代码问题修改与使用方法
- spring单例解析以及多线程安全分析
- 状态模式State(对象行为型)
- struct timeval和gettimeofday()用法
- 实验二——自顶向下分析方法之表驱动LL(1)分析程序
- ssh登陆慢/xhell访问主机慢
- Linux安装mysql环境(32位)
- UE(虚幻)4 蓝图可视化编程 01 变量类型
- JQuery:使用 toggle 切换 css 时,checkbox不能选中的解决方法;在checkbox中"放入"文字
- 3.3V与5V单片机通讯电路原理图
- JavaWeb 17-6-2
- win10 vpn 安装手册
- Linux操作命令