SLR1 文法分析器构造错误:ComputeFirst() 和 ComputeFollow() 函数中无法从 'string' 转换为 'char' 错误修复
SLR1 文法分析器构造错误:ComputeFirst() 和 ComputeFollow() 函数中无法从 'string' 转换为 'char' 错误修复
在构建 SLR1 文法分析器时, ComputeFirst() 和 ComputeFollow() 函数中经常会出现“无法从 'string' 转换为 'char'”的错误。该错误通常发生在使用 string 类型来表示产生式右部的符号时,而函数需要使用 char 类型来进行操作。
为了解决这个问题,需要对代码进行以下修改:
-
将产生式右部的字符串拆分成单个字符: 在
ComputeFirst()和ComputeFollow()函数中,遍历产生式右部时,需要将字符串拆分成单个字符进行操作。例如,可以使用foreach (char c in node.Right)循环来遍历每个字符。 -
使用
char类型进行比较: 在判断字符类型(例如终结符或非终结符)时,需要使用char类型进行比较。例如,使用Echar.Contains(c)或Nchar.Contains(c)来判断字符是否是终结符或非终结符。
以下是一个示例代码,展示了如何修改 ComputeFirst() 和 ComputeFollow() 函数以解决该错误。
public class SLRNode
{
public string Left;
public string Right;
public HashSet<char> First;
public HashSet<char> Follow;
public SLRNode(string Left, string Right)
{
this.Left = Left;
this.Right = Right;
First = new HashSet<char>();
Follow = new HashSet<char>();
}
}
//项目集类
public class SLRitemsets
{
public List<int> Container
= new List<int>(100);
//记录项目在项目集合中的序号
public HashSet<char> LookAhead
= new HashSet<char>();
//记录展望符
}
//DFA结点
public struct DFA
{
public int from;
public char symbol;
public int to;
public HashSet<char> LookAhead;
public DFA(int from, char symbol, int to, HashSet<char> LookAhead)
{
this.from = from;
this.symbol = symbol;
this.to = to;
this.LookAhead = LookAhead;
}
}
//分析表 结点
public class Table
{
public bool error;//是否为ERROR
public char type;//结点类型
public int id;//数值
public Table()
{
this.error = true;
}
public Table(char type, int id)
{
this.type = type;
this.id = id;
this.error = false;
}
}
public DFA[] dfa = new DFA[100];
public int Pindex = 0; //dfa数组指针
public Table[][] SLRAna;//分析表
public Analyze Jz;
public bool Success = false;
public List<SLRNode> SLRproNum = new List<SLRNode>(50);//产生式 列表
public List<SLRNode> SLRobjNum = new List<SLRNode>(50);//项目 列表
public List<SLRitemsets> proitemset = new List<SLRitemsets>(100);//项目集合
public List<int> Gy_obj = new List<int>(50);//归约项目序号集合
public List<int> Gy_itemset = new List<int>(50);//含有归约项目的集合的序号 的集合
public List<char> Nchar = new List<char>(50);//非终结符集合
public List<char> Echar = new List<char>(50);//终结符集合
Dictionary<char, HashSet<char>> first = new Dictionary<char, HashSet<char>>();//非终结符的First集
Dictionary<char, HashSet<char>> follow = new Dictionary<char, HashSet<char>>();//非终结符的Follow集
public string RStr = '';
public string RStr_obitemset = '';//输出返回
public string RStr_DFA = '';
public string RStr_ANA = '';
public Table[][] GET_ANA()
{
SLRAnaly();
RStr_ANA += '
SLR1分析表:
';
int i;
for (i = 0; i < Echar.Count; i++)
{
RStr_ANA += Echar[i].ToString() + ' ';
}
for (i = 0; i < Nchar.Count; i++)
{
RStr_ANA += Nchar[i].ToString() + ' ';
}
RStr_ANA += '
';
for (i = 0; i < proitemset.Count; i++)
{
RStr_ANA += i.ToString() + ' ';
for (int j = 0; j < Echar.Count + Nchar.Count; j++)
{
if (SLRAna[i][j].error)
{
RStr_ANA += ' ' + ' ';
}
else if (SLRAna[i][j].type != 'N')
{
RStr_ANA += SLRAna[i][j].type.ToString() + SLRAna[i][j].id.ToString() + ' ';
}
else
RStr_ANA += SLRAna[i][j].id.ToString() + ' ';
}
RStr_ANA += '
';
}
return SLRAna;
}
public void SLRAnaly()
{
//计算First集和Follow集
ComputeFirst();
ComputeFollow();
//构造项目集
CreateItemsets();
//构造DFA
CreateDFA();
//构造分析表
CreateSLRTable();
}
public void ComputeFirst()
{
//初始化 First 集
foreach (char c in Nchar)
{
first.Add(c, new HashSet<char>());
}
foreach (char c in Echar)
{
first.Add(c, new HashSet<char>() { c });
}
//计算 First 集
bool flag = true;
while (flag)
{
flag = false;
foreach (SLRNode node in SLRproNum)
{
HashSet<char> temp = new HashSet<char>();
bool canEpsilon = true;
foreach (char c in node.Right)
{
if (Echar.Contains(c))
{
temp.UnionWith(first[c]);
if (!first[c].Contains('ε'))
{
canEpsilon = false;
break;
}
}
else
{
canEpsilon = false;
temp.UnionWith(first[c]);
break;
}
}
if (canEpsilon)
{
temp.Add('ε');
}
if (!temp.SetEquals(first[node.Left]))
{
first[node.Left].UnionWith(temp);
flag = true;
}
}
}
}
public void ComputeFollow()
{
//初始化 Follow 集
foreach (char c in Nchar)
{
follow.Add(c, new HashSet<char>());
}
follow[SLRproNum[0].Left].Add('#');
//计算 Follow 集
bool flag = true;
while (flag)
{
flag = false;
foreach (SLRNode node in SLRproNum)
{
for (int i = 0; i < node.Right.Length; i++)
{
if (Nchar.Contains(node.Right[i]))
{
HashSet<char> temp = new HashSet<char>();
bool canEpsilon = true;
for (int j = i + 1; j < node.Right.Length; j++)
{
if (Echar.Contains(node.Right[j]))
{
temp.UnionWith(first[node.Right[j]]);
if (!first[node.Right[j]].Contains('ε'))
{
canEpsilon = false;
break;
}
}
else
{
canEpsilon = false;
temp.UnionWith(first[node.Right[j]]);
break;
}
}
if (canEpsilon)
{
temp.UnionWith(follow[node.Left]);
}
if (!temp.SetEquals(follow[node.Right[i]]))
{
follow[node.Right[i]].UnionWith(temp);
flag = true;
}
}
}
if (node.Right.EndsWith(Nchar.ToString()))
{
if (!follow[node.Left].SetEquals(follow[node.Right[node.Right.Length - 1]]))
{
follow[node.Right[node.Right.Length - 1]].UnionWith(follow[node.Left]);
flag = true;
}
}
}
}
}
public void CreateItemsets()
{
//初始化第一个项目集
SLRitemsets itemset0 = new SLRitemsets();
itemset0.Container.Add(0);
itemset0.LookAhead.Add('#');
itemset0 = Closure(itemset0);
proitemset.Add(itemset0);
//构造所有项目集
bool flag = true;
while (flag)
{
flag = false;
for (int i = 0; i < proitemset.Count; i++)
{
for (int j = 0; j < Echar.Count + Nchar.Count; j++)
{
char symbol = j < Echar.Count ? Echar[j] : Nchar[j - Echar.Count];
HashSet<char> lookAhead = new HashSet<char>();
foreach (int index in proitemset[i].Container)
{
if (SLRobjNum[index].Right.Contains('.') && SLRobjNum[index].Right.IndexOf('.') < SLRobjNum[index].Right.Length - 1 && SLRobjNum[index].Right[SLRobjNum[index].Right.IndexOf('.') + 1] == symbol)
{
if (SLRobjNum[index].Right.Length - 1 == SLRobjNum[index].Right.IndexOf('.') + 1)
{
lookAhead.UnionWith(proitemset[i].LookAhead);
}
else
{
bool canEpsilon = true;
for (int k = SLRobjNum[index].Right.IndexOf('.') + 2; k < SLRobjNum[index].Right.Length; k++)
{
if (Echar.Contains(SLRobjNum[index].Right[k]))
{
lookAhead.UnionWith(first[SLRobjNum[index].Right[k]]);
if (!first[SLRobjNum[index].Right[k]].Contains('ε'))
{
canEpsilon = false;
break;
}
}
else
{
canEpsilon = false;
lookAhead.UnionWith(first[SLRobjNum[index].Right[k]]);
break;
}
}
if (canEpsilon)
{
lookAhead.UnionWith(proitemset[i].LookAhead);
}
}
}
}
if (lookAhead.Count > 0)
{
SLRitemsets newItemset = new SLRitemsets();
foreach (int index in proitemset[i].Container)
{
if (SLRobjNum[index].Right.Contains('.') && SLRobjNum[index].Right.IndexOf('.') < SLRobjNum[index].Right.Length - 1 && SLRobjNum[index].Right[SLRobjNum[index].Right.IndexOf('.') + 1] == symbol)
{
SLRNode newNode = new SLRNode(SLRobjNum[index].Left, SLRobjNum[index].Right.Insert(SLRobjNum[index].Right.IndexOf('.') + 2, '$'));
if (!SLRobjNum.Contains(newNode))
{
SLRobjNum.Add(newNode);
newItemset.Container.Add(SLRobjNum.Count - 1);
newItemset.LookAhead.Add(symbol);
}
else
{
int index2 = SLRobjNum.IndexOf(newNode);
newItemset.Container.Add(index2);
newItemset.LookAhead.Add(symbol);
}
}
}
newItemset = Closure(newItemset);
if (!proitemset.Contains(newItemset))
{
proitemset.Add(newItemset);
flag = true;
}
dfa[Pindex++] = new DFA(i, symbol, proitemset.IndexOf(newItemset), lookAhead);
}
}
}
}
}
public void CreateDFA()
{
RStr_DFA += '
SLR1分析器DFA:
';
RStr_DFA += '状态|';
foreach (char c in Echar)
{
RStr_DFA += c + '|';
}
foreach (char c in Nchar)
{
RStr_DFA += c + '|';
}
RStr_DFA += '
';
for (int i = 0; i < Pindex; i++)
{
RStr_DFA += i + ' |';
for (int j = 0; j < Echar.Count + Nchar.Count; j++)
{
if (dfa[i].to == -1)
{
RStr_DFA += ' |';
}
else
{
if (dfa[i].symbol == (j < Echar.Count ? Echar[j] : Nchar[j - Echar.Count]))
{
RStr_DFA += dfa[i].to + ',' + string.Join('', dfa[i].LookAhead) + '|';
}
else
{
RStr_DFA += ' |';
}
}
}
RStr_DFA += '
';
}
}
public void CreateSLRTable()
{
CreateItemsets();
CreateDFA();
SLRAna = new Table[proitemset.Count][];
for (int i = 0; i < proitemset.Count; i++)
{
SLRAna[i] = new Table[Echar.Count + Nchar.Count];
for (int j = 0; j < Echar.Count + Nchar.Count; j++)
{
char symbol = j < Echar.Count ? Echar[j] : Nchar[j - Echar.Count];
int nextState = -1;
HashSet<char> lookAhead = new HashSet<char>();
foreach (DFA d in dfa)
{
if (d.from == i && d.symbol == symbol)
{
nextState = d.to;
lookAhead.UnionWith(d.LookAhead);
break;
}
}
if (nextState == -1)
{
SLRAna[i][j] = new Table();
}
else if (Gy_obj.Contains(nextState))
{
SLRAna[i][j] = new Table('R', Gy_obj.IndexOf(nextState) + 1);
}
else if (proitemset[nextState].LookAhead.Contains('#'))
{
SLRAna[i][j] = new Table('A', 0);
}
else
{
SLRAna[i][j] = new Table('S', nextState);
}
}
foreach (int index in Gy_itemset)
{
if (proitemset[index].Container.Contains(i))
{
foreach (char c in proitemset[index].LookAhead)
{
if (Echar.IndexOf(c) >= 0)
{
SLRAna[i][Echar.IndexOf(c)] = new Table('R', Gy_obj.IndexOf(index) + 1);
}
else if (c == '#')
{
SLRAna[i][Nchar.Count - 1] = new Table('R', Gy_obj.IndexOf(index) + 1);
}
}
}
}
}
Success = true;
}
通过以上修改,可以有效解决 ComputeFirst() 和 ComputeFollow() 函数中的“无法从 'string' 转换为 'char'”错误,并确保 SLR1 文法分析器的正常构建。
注意: 以上代码只是示例,具体的修改方法可能需要根据实际代码进行调整。
原文地址: https://www.cveoy.top/t/topic/f0Ok 著作权归作者所有。请勿转载和采集!