SLR1 分析表构建错误分析及代码修正 - 归约状态处理问题
错误分析结论:在 SLR1 分析表中没有正确地添加归约状态,对应状态对每个终结符都添加同样的动作。
错误部分:
在 SLRAnaly() 函数中,对于归约状态的处理,只考虑了每个归约状态的 Follow 集,而没有考虑到每个归约状态对应的所有产生式的 First 集。因此,在分析表中对于每个终结符,归约状态都添加了相同的动作。
修改后的代码:
- 在 SLRAnaly() 函数中,修改对于归约状态的处理,考虑到每个归约状态对应的所有产生式的 First 集:
for (int i = 0; i < Gy_itemset.Count; i++)
{
List<int> container = proitemset[Gy_itemset[i]].Container;
foreach (int index in container)
{
SLRNode item = SLRobjNum[index];
List<char> first = GetFirst(item.Right, item.Pos + 1);
foreach (char c in first)
{
int CID = FindID(Echar, c);
SLRAna[Gy_itemset[i]][CID] = new Table('r', index);
}
}
}
- 在 GetFirst() 函数中,添加参数 pos,表示从产生式的第 pos 个字符开始求 First 集:
public List<char> GetFirst(string str, int pos)
{
List<char> first = new List<char>();
if (pos >= str.Length)
{
first.Add('#');
return first;
}
char c = str[pos];
if (isFinalsymbol(c))
first.Add(c);
else
{
foreach (SLRNode node in SLRproNum)
{
if (node.Left[0] == c)
{
if (node.Right[0] == c)
continue;
else if (isFinalsymbol(node.Right[0]))
first.Add(node.Right[0]);
else
{
List<char> subFirst = GetFirst(node.Right, 0);
if (subFirst.Contains('#'))
{
subFirst.Remove('#');
first.AddRange(subFirst);
first.AddRange(GetFirst(node.Right, 1));
}
else
{
first.AddRange(subFirst);
}
}
}
}
}
first = first.Distinct().ToList();
return first;
}
通过以上修改,可以确保 SLR1 分析表中每个归约状态都能正确地根据其 First 集和 Follow 集添加动作,避免了同一个状态对所有终结符都添加相同动作的问题。
原文地址: https://www.cveoy.top/t/topic/f0MS 著作权归作者所有。请勿转载和采集!