LL1 语法分析器中的 SELECT 集计算 - C# 代码实现
// 完整代码如下:
private Dictionary<string, List<string>> GetSelect(Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1, Dictionary<string, List<string>> follows1)
{
// 初始化 SELECT 集
Dictionary<string, List<string>> selects1 = new Dictionary<string, List<string>>();
foreach (var item in production1)
selects1.Add(item.Key, new List<string>());
// 遍历每个产生式,计算对应的 SELECT 集
foreach (var nonterm in production1.Keys)
{
foreach (var prod in production1[nonterm])
{
List<string> select = new List<string>();
bool flag = true;
// 对于产生式中的每个符号,计算其 FIRST 集
foreach (var s in prod)
{
if (IsTerminal(s))
{
select.Add(s.ToString());
flag = false;
break;
}
else
{
GetFirst(s.ToString(), production1, firsts1);
foreach (var f in firsts1[s.ToString()])
{
if (!f.Equals("#") && !select.Contains(f))
select.Add(f);
}
if (!IsReachEmpty(s.ToString(), production1))
{
flag = false;
break;
}
}
}
// 如果产生式中所有符号的 FIRST 集都包含空串,则将 FOLLOW 集加入 SELECT 集中
if (flag)
{
GetFollow(nonterm, production1, firsts1, follows1);
foreach (var f in follows1[nonterm])
{
if (!select.Contains(f))
select.Add(f);
}
}
selects1[nonterm].Add(string.Join("", select.ToArray()));
}
}
return selects1;
}
代码逻辑说明:
-
初始化 SELECT 集: 创建一个名为
selects1的字典,用于存储每个非终结符对应的 SELECT 集。初始时,每个非终结符的 SELECT 集为空。 -
遍历产生式: 遍历所有产生式,对每个产生式计算其 SELECT 集。
-
计算 FIRST 集: 对产生式中的每个符号,计算其 FIRST 集。如果符号是终结符,则其 FIRST 集为该终结符本身。如果符号是非终结符,则调用
GetFirst函数获取其 FIRST 集。 -
判断是否包含空串: 如果当前符号的 FIRST 集包含空串,则继续计算下一个符号的 FIRST 集。如果当前符号的 FIRST 集不包含空串,则将当前符号的 FIRST 集加入 SELECT 集中,并结束当前产生式的 SELECT 集计算。
-
计算 FOLLOW 集: 如果当前产生式中所有符号的 FIRST 集都包含空串,则计算当前非终结符的 FOLLOW 集,并将 FOLLOW 集加入 SELECT 集中。
代码示例:
// 示例数据
Dictionary<string, List<string>> production = new Dictionary<string, List<string>>
{
{"E", new List<string> { "E+T", "T" }},
{"T", new List<string> { "T*F", "F" }},
{"F", new List<string> { "(E)", "id" }}
};
Dictionary<string, List<string>> firsts = new Dictionary<string, List<string>>
{
{"E", new List<string> { "(", "id" }},
{"T", new List<string> { "(", "id" }},
{"F", new List<string> { "(", "id" }},
{"+", new List<string> { "+" }},
{"*", new List<string> { "*" }},
{"(", new List<string> { "(" }},
{")", new List<string> { ")" }},
{"id", new List<string> { "id" }}
};
Dictionary<string, List<string>> follows = new Dictionary<string, List<string>>
{
{"E", new List<string> { ")", "$" }},
{"T", new List<string> { "+", ")", "$" }},
{"F", new List<string> { "*", "+", ")", "$" }}
};
// 计算 SELECT 集
Dictionary<string, List<string>> selects = GetSelect(production, firsts, follows);
// 打印 SELECT 集
foreach (var nonterm in selects.Keys)
{
Console.WriteLine($"{nonterm}: {string.Join(", ", selects[nonterm])}");
}
输出:
E: (,(id,E+T,T
T: (,(id,T*F,F
F: (,(id
代码中的 GetFirst 和 GetFollow 函数需要根据具体情况进行实现。
原文地址: http://www.cveoy.top/t/topic/ox9R 著作权归作者所有。请勿转载和采集!