SLR1 分析:错误分析与修正
SLR1 分析:错误分析与修正
问题:
在使用 SLR1 分析方法分析文法时,分析表中缺少了 'r' 状态,导致分析器无法正确识别归约项目。这是因为在 SLRAnaly() 方法中,没有正确处理归约项目。
错误分析:
- **没有处理 Follow 集:**在遍历项目集中的所有项目时,对于归约项目,应该将其左部符号的 Follow 集中的所有终结符加入到对应的分析表格中。
- **没有处理结束符号 #:**当 Follow 集中包含结束符号 '#' 时,需要将所有终结符的分析表格都设为对应产生式的编号 'r'。
修正代码:
public void SLRAnaly()
{
Table tnode = new Table();
SLRAna = new Table[proitemset.Count][];
for (int i = 0; i < proitemset.Count; i++)
SLRAna[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状态
SLRAna[i][j] = tnode;
tnode = new Table('A', 0);
SLRAna[1][FindID(Echar, '#')] = tnode;//项目集1必定是接受项目 构建[1][#]:acc的情况 先直接赋值好 dfa里没有
for (int i = 0; i < proitemset.Count; i++)//遍历所有的项目集
{
foreach (int index in proitemset[i].Container)//遍历项目集中的所有项目
{
SLRNode item = SLRobjNum[index];
if (item.Right == 'd')//归约项目
{
int leftIndex = FindID(Nchar, item.Left[0]);
List<char> follow = Follow[leftIndex];//获取左部符号的follow集
foreach (char c in follow)
{
int CID = FindID(Echar, c);
SLRAna[i][CID] = new Table('r', Find_pro(item));
if (c == '#')
{
foreach (char e in Echar)
{
int EID = FindID(Echar, e);
SLRAna[i][EID] = new Table('r', Find_pro(item));
}
}
}
}
}
}
for (int i = 0; i < Pindex; i++)
{
if (isFinalsymbol(dfa[i].symbol))//symbol为非终结符 添加状态N
{
int CID = FindID(Nchar, dfa[i].symbol);
SLRAna[dfa[i].from][CID + Echar.Count] = new Table('N', dfa[i].to);
}
else //不是归约项目 添加状态S
{
int CID = FindID(Echar, dfa[i].symbol);
SLRAna[dfa[i].from][CID] = new Table('S', dfa[i].to);
}
}
}
修正后的代码主要做了以下改动:
- 在处理归约项目时,使用
Follow集中的所有终结符填充对应的分析表格,将 'r' 状态加入其中。 - 在处理结束符号 '#' 时,将所有终结符的分析表格都设为对应产生式的编号 'r'。
代码说明:
FindID(Echar, c): 获取终结符c在Echar列表中的序号。FindID(Nchar, c): 获取非终结符c在Nchar列表中的序号。Find_pro(item): 获取项目item对应的产生式的编号。isFinalsymbol(c): 判断字符c是否是终结符。
总结:
通过正确处理归约项目和结束符号,我们可以完整构建 SLR1 分析表,并使用该分析表进行语法的识别和分析。
建议:
- 在实现 SLR1 分析方法时,务必仔细处理归约项目,确保分析表完整性。
- 使用调试工具对代码进行测试,确保程序正确性。
- 参考相关资料,深入理解 SLR1 分析的原理和实现细节。
原文地址: https://www.cveoy.top/t/topic/f0J5 著作权归作者所有。请勿转载和采集!