C# 代码错误:'System.Collections.Generic.Stack`1[System.Char]' 输出问题解决方法
在 C# 代码中,语句 'string production = table[topAnalyse.ToString()][topInputToString()];' 报错并只能输出 'System.Collections.Generic.Stack`1[System.Char]' ,这是因为代码中使用了错误的方法来获取输入栈的栈顶元素。
错误原因:
代码中调用了 topInputToString() 方法,但该方法并不存在。应该使用 topInput.ToString() 方法来获取输入栈的栈顶元素。
解决方案:
将代码中的语句修改为以下代码:
string production = table[topAnalyse.ToString()][topInput.ToString()];
示例代码:
private void GetFirst(string symbol, Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1)
{
// 如果该非终结符的 FIRST 集已经被计算出,则直接返回
if (firsts1.ContainsKey(symbol))
{
return;
}
firsts1.Add(symbol, new List<string>());
// 遍历产生式,计算 FIRST 集
foreach (var prod in production1[symbol])
{
// 如果产生式首字符为终结符,则直接将其加入 FIRST 集中
if (prod.Length > 0 && IsTerminal(prod[0]))
{
if (!firsts1[symbol].Contains(prod[0].ToString()))
firsts1[symbol].Add(prod[0].ToString());
continue;
}
// 如果产生式首字符为非终结符,则计算该非终结符的 FIRST 集,并将结果加入首字符的 FIRST 集中
else if (prod.Length > 0 && !IsTerminal(prod[0]))
{
GetFirst(prod[0].ToString(), production1, firsts1);
foreach (var f in firsts1[prod[0].ToString()])
{
if (!firsts1[symbol].Contains(f) && !f.Equals('#'))
firsts1[symbol].Add(f);
}
}
//如果第一个非终结符能推出#
if (IsReachEmpty(prod[0].ToString(), production1))
{
// 递归计算第二个和后面的字符的 FIRST 集,并将结果加入该非终结符的 FIRST 集中
for (int j = 1; j < prod.Length; j++)
{
if (IsTerminal(prod[j]))
{
if (!firsts1[symbol].Contains(prod[j].ToString()))
firsts1[symbol].Add(prod[j].ToString());
break;
}
GetFirst(prod[j].ToString(), production1, firsts1);
foreach (var f in firsts1[prod[j].ToString()])
{
if (!firsts1[symbol].Contains(f) && !f.Equals('#'))
firsts1[symbol].Add(f);
}
// 如果该非终结符的 FIRST 集没有包含空串,则可以结束循环
if (!IsReachEmpty(prod[j].ToString(), production1))
{
break;
}
// 如果是最后一个字符且所有非终结符的 FIRST 集都含有空串,则将空串加入该非终结符的 FIRST 集中
if (j == prod.Length - 1)
{
if (!firsts1[symbol].Contains('#'))
firsts1[symbol].Add('#');
}
}
}
}
}
// 计算 FOLLOW 集
private void GetFollow(string symbol, Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1, Dictionary<string, List<string>> follows1)
{
// 如果该非终结符的 FOLLOW 集已经被计算出,则直接返回
if (follows1.ContainsKey(symbol))
{
return;
}
follows1.Add(symbol, new List<string>());
// 如果是起始符号,则将 # 加入 FOLLOW 集中
if (symbol.Equals(production1.Keys.First()))
{
if (!follows1[symbol].Contains('#'))
follows1[symbol].Add('#');
}
// 遍历产生式,计算 FOLLOW 集
foreach (var item in production1)
{
foreach (var prod in item.Value)
{
int index = prod.IndexOf(symbol);
if (index == -1)
continue;
// 如果该非终结符位于产生式末尾,则将产生式左部的 FOLLOW 集加入该非终结符的 FOLLOW 集中
if (index == prod.Length - 1)
{
GetFollow(item.Key, production1, firsts1, follows1);
foreach (var f in follows1[item.Key])
{
if (!follows1[symbol].Contains(f))
follows1[symbol].Add(f);
}
}
else
{
// 如果该非终结符后面是终结符,则将该终结符加入该非终结符的 FOLLOW 集中
if (IsTerminal(prod[index + 1]))
{
if (!follows1[symbol].Contains(prod[index + 1].ToString()))
follows1[symbol].Add(prod[index + 1].ToString());
}
// 如果该非终结符后面是非终结符,则将该非终结符的 FIRST 集加入该非终结符的 FOLLOW 集中
else
{
GetFirst(prod[index + 1].ToString(), production1, firsts1);
foreach (var f in firsts1[prod[index + 1].ToString()])
{
if (!f.Equals('#') && !follows1[symbol].Contains(f))
follows1[symbol].Add(f);
}
// 如果该非终结符后面的所有符号都能推出空串,则将产生式左部的 FOLLOW 集加入该非终结符的 FOLLOW 集中
if (IsReachEmpty(prod[index + 1].ToString(), production1))
{
GetFollow(item.Key, production1, firsts1, follows1);
foreach (var f in follows1[item.Key])
{
if (!follows1[symbol].Contains(f))
follows1[symbol].Add(f);
}
}
}
}
}
}
}
private void GetSelect(Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1, Dictionary<string, List<string>> follows1)
{
//对非终结符的每个产生式获取select值
//如果该产生式第一个字符为终结符
//如果该产生式第一个字符为非终结符
// 对每个非终结符进行操作
// 对每个非终结符进行遍历
foreach (var nonterm in nonterminals)
{
// 获取该非终结符的所有产生式
var productions = production1[nonterm];
// 遍历该非终结符的所有产生式
foreach (var prod in productions)
{
// 初始化该产生式的 select 值
List<string> select = new List<string>();
// 如果该产生式的第一个字符为终结符,直接将该字符加入 select
if (IsTerminal(prod[0]))
{
if (prod[0].Equals('#'))
{
// 如果该产生式的第一个字符为 #,将 follow(nonterm) 加入 select
select.AddRange(follows1[nonterm]);
}
else
{
// 如果该产生式的第一个字符为其他终结符,将该终结符加入 select
select.Add(prod[0].ToString());
}
}
else
{
// 如果该产生式的第一个字符为非终结符,将该非终结符的 first 集加入 select
select.AddRange(firsts1[prod[0].ToString()]);
// 如果该非终结符的 first 集中包含空串,将 follow(nonterm) 加入 select
if (select.Contains('#'))
{
select.Remove('#');
select.AddRange(follows1[nonterm]);
}
}
// 将该产生式的 select 值加入预测分析表中
foreach (var term in select)
{
table[nonterm][term] = prod;
}
}
}
}
private void analyze()
{
while (true)
{
// 如果分析栈为空或者输入栈为空,则分析结束
if (analyseStack.Count == 0 || inputStack.Count == 0)
{
break;
}
// 获取分析栈的栈顶元素和输入栈的栈顶元素
char topAnalyse = analyseStack.Peek();
char topInput = inputStack.Peek();
// 如果分析栈的栈顶元素和输入栈的栈顶元素相同,则进行匹配
if (topAnalyse == topInput)
{
// 将匹配的元素从分析栈和输入栈中弹出
analyseStack.Pop();
inputStack.Pop();
// 在分析结果列表中添加匹配信息
resultAnalyse.Add(analyseStack.ToString());
resultInput.Add(inputStack.ToString());
resultParse.Add(''' + topAnalyse + '' 匹配');
}
else
{
// 如果分析栈的栈顶元素为终结符,则出错
if (IsTerminal(topAnalyse))
{
resultParse.Add('出错');
break;
}
else
{
if (!table.ContainsKey(topAnalyse.ToString()) || !table[topAnalyse.ToString()].ContainsKey(topInput.ToString()))
{
resultParse.Add('出错');
break;
}
else
{
// 获取分析表中的产生式
string production = table[topAnalyse.ToString()][topInput.ToString()];
// 如果分析表中没有产生式,则出错
if (production == null)
{
resultParse.Add('出错');
break;
}
else
{
// 将产生式从分析栈中弹出
analyseStack.Pop();
// 如果产生式不是空串,则将产生式中的符号逆序压入分析栈中
if (production != '#')
{
for (int i = production.Length - 1; i >= 0; i--)
{
analyseStack.Push(production[i]);
}
}
// 在分析结果列表中添加产生式信息
resultAnalyse.Add(analyseStack.ToString());
resultInput.Add(inputStack.ToString());
resultParse.Add(topAnalyse + ' -> ' + production);
}
}
}
}
}
// 如果分析栈和输入栈都为空,则分析成功
if (analyseStack.Count == 0 && inputStack.Count == 0)
{
resultParse.Add('成功');
}
}
修改后的代码可以正确输出分析串和剩余输出串。
注意:
- 确保
table变量是一个字典类型,并且topAnalyse和topInput变量分别存储了分析栈和输入栈的栈顶元素。 - 代码中使用了
IsTerminal()方法来判断字符是否为终结符。你需要根据你的代码逻辑实现该方法。 - 代码中使用了
IsReachEmpty()方法来判断非终结符是否能推出空串。你需要根据你的代码逻辑实现该方法。
希望以上内容能够帮助你解决代码问题。
原文地址: http://www.cveoy.top/t/topic/fYDW 著作权归作者所有。请勿转载和采集!