SLR文法分析表构造:SLRAnaly()函数与follow集实现
SLR分析表构造与实现
SLR分析表的构造与LR分析表类似,只是在处理移进-归约冲突和归约-归约冲突时需要使用follow集进行判断。具体步骤如下:
-
构造follow集
在SLR分析中,follow集的构造与LR分析类似,只是需要在原有的follow集的基础上,加入所有能够跟随非终结符号A的后继符号。
-
根据follow集处理移进-归约冲突和归约-归约冲突
- 对于移进-归约冲突,只有当follow集中的终结符与当前输入符号相同时,才进行归约操作,否则进行移进操作。 - 对于归约-归约冲突,只有当两个归约项目所对应的follow集没有交集时,才进行归约操作,否则选择优先级更高的归约项目进行归约。
修改后的SLRAnaly()函数C#public void SLRAnaly(){ Table tnode = new Table();
LRAna = new Table[proitemset.Count][]; for (int i = 0; i < proitemset.Count; i++) LRAna[i] = new Table[Echar.Count + Nchar.Count];
for (int i = 0; i < proitemset.Count; i++)//初始化 赋予ERROR属性 for (int j = 0; j < Echar.Count + Nchar.Count; j++)//为终结符加r状态 LRAna[i][j] = tnode;
tnode = new Table('A', 0); LRAna[1][FindID(Echar, '#')] = tnode;//项目集1必定是接受项目 构建[1][#]:acc的情况 先直接赋值好 dfa里没有
for (int i = 0; i < Gy_itemset.Count; i++) { tnode = new Table('r', Find_pro(LRobjNum[proitemset[Gy_itemset[i]].Container[0]]));//归约项目 找到原产生式序号 添加状态r for (int j = 0; j < Echar.Count; j++) { LRAna[Gy_itemset[i]][j] = tnode; } } for (int i = 0; i < Pindex; i++) { if (isFinalsymbol(dfa[i].symbol))//symbol为非终结符 添加状态N { int CID = FindID(Nchar, dfa[i].symbol); tnode = new Table('N', dfa[i].to); LRAna[dfa[i].from][CID + Echar.Count] = tnode; } else //不是归约项目 添加状态S { int CID = FindID(Echar, dfa[i].symbol); if (Gy_obj.Contains(dfa[i].to))//归约-移进冲突 { foreach (char c in Follow[Nchar[CID]])//遍历follow集 { int CID2 = FindID(Echar, c); if (CID2 != -1)//存在交集 { if (LRAna[dfa[i].from][CID2].type == 'r')//优先级更高的归约项目 { tnode = new Table('r', Find_pro(LRobjNum[proitemset[Gy_itemset[LRAna[dfa[i].from][CID2].id]].Container[0]])); } else//移进操作 { tnode = new Table('S', dfa[i].to); } } else//不存在交集,进行归约操作 { tnode = new Table('r', Find_pro(LRobjNum[proitemset[Gy_obj.IndexOf(dfa[i].to)]].Container[0])); } LRAna[dfa[i].from][CID] = tnode; } } else//正常情况,进行移进操作 { tnode = new Table('S', dfa[i].to); LRAna[dfa[i].from][CID] = tnode; } } }}
修改后的follow集构造函数C#public void GetFollow(){ Follow = new List[Nchar.Count]; for (int i = 0; i < Nchar.Count; i++) { Follow[i] = new List(); } Follow[0].Add('#');//起始符号的follow集中加入#
bool changed = true; while (changed)//循环直到follow集不再变化 { changed = false; for (int i = 0; i < SLRproNum.Count; i++) { string right = SLRproNum[i].Right; for (int j = 0; j < right.Length; j++) { if (isFinalsymbol(right[j]))//终结符号,跳过 { continue; } int index = FindID(Nchar, right[j]); if (j == right.Length - 1)//A->αB,将follow(A)加入follow(B) { foreach (char c in Follow[i]) { if (!Follow[index].Contains(c)) { Follow[index].Add(c); changed = true; } } } else//A->αBβ,将first(β)中除ε外的符号加入follow(B),如果ε∈first(β),将follow(A)加入follow(B) { string beta = right.Substring(j + 1); List<char> first_beta = First(beta); foreach (char c in first_beta) { if (c != 'ε' && !Follow[index].Contains(c)) { Follow[index].Add(c); changed = true; } } if (first_beta.Contains('ε')) { foreach (char c in Follow[i]) { if (!Follow[index].Contains(c)) { Follow[index].Add(c); changed = true; } } } } } } }}
其他函数代码
其他函数的代码与LR分析表构造时相同,只是需要在调用SLRAnaly()时先调用GetFollow()函数,生成follow集。
总结
通过修改SLRAnaly()函数和构造follow集,可以将LR分析表转换为SLR分析表,并处理移进-归约冲突和归约-归约冲突。该过程能够有效地生成SLR分析表,为SLR分析器提供必要的解析信息,完成语法分析
原文地址: https://www.cveoy.top/t/topic/f0vm 著作权归作者所有。请勿转载和采集!