LL(1) 预测分析表构建:Select 函数实现
private void GetSelect(Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1, Dictionary<string, List<string>> follows1)
{
// 对每个非终结符进行操作
foreach (var nonterm in nonterminals)
{
// 对每个产生式进行操作
foreach (var prod in production1[nonterm])
{
var select = new List<string>();
bool hasEmpty = true;
// 对产生式的每个符号进行操作
for (int i = 0; i < prod.Count(); i++)
{
// 如果该符号是终结符,直接加入select中
if (IsTerminal(prod[i]))
{
select.Add(prod[i]);
hasEmpty = false;
break;
}
// 如果该符号是非终结符,将该非终结符的first集加入select中
else
{
var first = firsts1[prod[i]];
select = select.Union(first).ToList();
// 如果该非终结符的first集中包含空串,则继续往后进行操作
if (!first.Contains('#'))
{
hasEmpty = false;
break;
}
}
}
// 如果产生式中所有符号的first集中都包含空串,则将该非终结符的follow集加入select中
if (hasEmpty)
{
select = select.Union(follows1[nonterm]).ToList();
}
// 将select填入预测分析表中
foreach (var s in select)
{
table[nonterm][s] = prod;
}
}
}
}
代码解释:
-
参数:
production1: 存放文法产生式的字典,键为非终结符,值为该非终结符的所有产生式列表。firsts1: 存放所有非终结符的 first 集的字典,键为非终结符,值为该非终结符的 first 集列表。follows1: 存放所有非终结符的 follow 集的字典,键为非终结符,值为该非终结符的 follow 集列表。
-
遍历非终结符:
- 使用
foreach循环遍历所有非终结符。
- 使用
-
遍历产生式:
- 对于每个非终结符,使用
foreach循环遍历其所有产生式。
- 对于每个非终结符,使用
-
计算 select 集:
- 初始化一个空的
select列表,用于存储该产生式的 select 集。 - 初始化一个布尔变量
hasEmpty,用于记录产生式中是否所有符号的 first 集都包含空串,初始值为true。 - 使用
for循环遍历产生式中的每个符号:- 如果符号是终结符,则将其直接加入
select列表中,并将hasEmpty设置为false,结束循环。 - 如果符号是非终结符,则将该非终结符的 first 集加入
select列表中。 - 如果该非终结符的 first 集不包含空串,则将
hasEmpty设置为false,结束循环。
- 如果符号是终结符,则将其直接加入
- 如果
hasEmpty为true,则表示该产生式中所有符号的 first 集都包含空串,则将该非终结符的 follow 集加入select列表中。
- 初始化一个空的
-
填充预测分析表:
- 使用
foreach循环遍历select列表,将每个符号和对应的产生式填入预测分析表table中。
- 使用
示例代码:
// 假设已知 production1、firsts1、follows1 和 table
GetSelect(production1, firsts1, follows1);
总结:
该代码实现了 LL(1) 预测分析表构建中的 Select 函数,用于计算每个产生式的 select 集。该函数通过遍历产生式中的每个符号,并根据符号类型来判断是否加入 first 集或 follow 集,最终得到该产生式的 select 集。通过该函数,我们可以构建完整的 LL(1) 预测分析表,并利用它进行语法分析。
原文地址: http://www.cveoy.top/t/topic/oyaC 著作权归作者所有。请勿转载和采集!