LL(1) 预测分析表生成算法 - GetSelect 函数实现
private Dictionary<string, Dictionary<int, string>> GetSelect(Dictionary<string, List<string>> production, Dictionary<string, List<string>> firsts, Dictionary<string, List<string>> follows)
{
var selects = new Dictionary<string, Dictionary<int, string>>();
foreach (var nonterm in production.Keys)
{
selects[nonterm] = new Dictionary<int, string>();
for (int i = 0; i < production[nonterm].Count; i++)
{
var prod = production[nonterm][i];
selects[nonterm][i] = '';
for (int j = 0; j < prod.Length; j++)
{
var symbol = prod[j];
if (IsTerminal(symbol))
{
if (symbol == '#')
{
foreach (var follow in follows[nonterm])
{
if (!selects[nonterm][i].Contains(follow))
{
selects[nonterm][i] += follow + ' ';
}
}
}
else if (!selects[nonterm][i].Contains(symbol.ToString()))
{
selects[nonterm][i] += symbol + ' ';
}
break;
}
else
{
var first = firsts[symbol.ToString()];
bool hasEmpty = false;
foreach (var f in first)
{
if (f == '#' )
{
hasEmpty = true;
}
else if (!selects[nonterm][i].Contains(f))
{
selects[nonterm][i] += f + ' ';
}
}
if (!hasEmpty)
{
break;
}
if (j == prod.Length - 1)
{
foreach (var follow in follows[nonterm])
{
if (!selects[nonterm][i].Contains(follow))
{
selects[nonterm][i] += follow + ' ';
}
}
}
}
}
}
}
return selects;
}
该函数接受三个参数:production 表示文法产生式,firsts 表示每个非终结符的 First 集,follows 表示每个非终结符的 Follow 集。函数首先创建了一个字典 selects,用来存储每个产生式的 select 集。然后,对每个非终结符的每个产生式进行遍历,计算该产生式的 select 集。
对于每个产生式,函数首先清空 selects 中对应产生式的 select 集。然后,对该产生式的每个符号进行遍历,判断该符号是终结符还是非终结符。
如果该符号是终结符,则将其加入到 selects 中。如果该符号是非终结符,则将该非终结符的 First 集加入到 selects 中。
如果该产生式的最后一个符号是空字符 '#',则将该非终结符的 Follow 集加入到 selects 中。
最后,函数返回 selects 字典,该字典存储了每个产生式的 select 集。
代码解析
-
selects字典用于存储每个产生式的 select 集,键为非终结符,值为一个字典,键为产生式在production中的索引,值为该产生式的 select 集字符串。 -
foreach (var nonterm in production.Keys)遍历每个非终结符。 -
foreach (var prod in production[nonterm])遍历每个非终结符的产生式。 -
selects[nonterm][i] = '';清空selects中对应产生式的 select 集。 -
foreach (var symbol in prod)遍历产生式中的每个符号。 -
if (IsTerminal(symbol))判断符号是否为终结符。 -
if (symbol == '#')判断符号是否为空字符。 -
foreach (var follow in follows[nonterm])遍历该非终结符的 Follow 集。 -
if (!selects[nonterm][i].Contains(follow))判断 Follow 集中的符号是否已存在于 select 集中。 -
selects[nonterm][i] += follow + ' ';将 Follow 集中的符号加入到 select 集中。 -
else if (!selects[nonterm][i].Contains(symbol.ToString()))判断终结符是否已存在于 select 集中。 -
selects[nonterm][i] += symbol + ' ';将终结符加入到 select 集中。 -
break;结束循环,因为已经找到第一个终结符。 -
else判断符号是否为非终结符。 -
foreach (var f in firsts[symbol.ToString()])遍历该非终结符的 First 集。 -
if (f == '#' )判断 First 集中的符号是否为空字符。 -
if (!selects[nonterm][i].Contains(f))判断 First 集中的符号是否已存在于 select 集中。 -
selects[nonterm][i] += f + ' ';将 First 集中的符号加入到 select 集中。 -
if (j == prod.Length - 1)判断是否到达产生式的最后一个符号。 -
foreach (var follow in follows[nonterm])遍历该非终结符的 Follow 集。 -
if (!selects[nonterm][i].Contains(follow))判断 Follow 集中的符号是否已存在于 select 集中。 -
selects[nonterm][i] += follow + ' ';将 Follow 集中的符号加入到 select 集中。 -
return selects;返回selects字典。
该 GetSelect 函数实现了 LL(1) 预测分析表生成算法中的重要步骤,即计算每个产生式的 select 集。通过该函数,我们可以得到每个产生式对应的预测分析表项,进而构建完整的预测分析表。', 'code': '```C#
private Dictionary<string, Dictionary<int, string>> GetSelect(Dictionary<string, List
原文地址: http://www.cveoy.top/t/topic/oyas 著作权归作者所有。请勿转载和采集!