C# 代码实现 LL(1) 文法判断 - 详细解析及原理
该代码实现了判断一个文法是否是 LL(1) 文法的功能。其原理如下:
-
首先从 'richTextBox1' 中获取输入的文法字符串,并将其按行分割为一个个产生式。
-
对于每个产生式,首先判断其是否为空或者格式是否正确,如果不符合要求则直接返回。
-
对于每个正确格式的产生式,将其左部作为 'key',右部作为 'value' 添加到一个字典 'production' 中,用于后续的分析。
-
对于每个非终结符,计算其 FIRST 集合并添加到一个字典 'firsts' 中。
-
对于每个非终结符,计算其 FOLLOW 集合并添加到一个字典 'follows' 中。
-
最后,判断文法是否是 LL(1) 文法。如果存在左递归或者存在 FIRST 集合有交集的情况,则不是 LL(1) 文法;否则就是 LL(1) 文法。
其中,判断一个文法是否是 LL(1) 文法的原理如下:
-
如果文法中不存在左递归,则满足 LL(1) 文法的第一个条件。
-
对于每个非终结符,计算其 FIRST 集合,如果任意两个产生式的 FIRST 集合有交集,则不满足 LL(1) 文法的第二个条件。
-
对于每个非终结符,计算其 FOLLOW 集合,如果任意两个产生式的 FOLLOW 集合有交集,则不满足 LL(1) 文法的第三个条件。
如果以上三个条件都满足,则该文法是 LL(1) 文法。
private void button4_Click(object sender, EventArgs e)
{
string text = richTextBox1.Text;
production = new Dictionary<string, List<string>>();
string[] pro = text.Split('
');
foreach (string s in pro)
{
if (s == "") continue;
Regex.Replace(s, " ", "");
string[] ga = Regex.Split(s, "->");
if (ga.Length != 2) return;
if (ga[0].Length == 0 || ga[1].Length == 0)
return;
if (ga[0].Length != 1 || !char.IsUpper(ga[0][0])) return;
string[] ga2 = Regex.Split(ga[1], "|");
if (!production.ContainsKey(ga[0]))
production.Add(ga[0], new List<string>());
foreach (string s1 in ga2)
production[ga[0]].Add(s1);
}
firsts = new Dictionary<string, List<string>>();
foreach (var item in production.Keys)
GetFirst(item, production, firsts);
follows = new Dictionary<string, List<string>>();
foreach (var item in production.Keys)
GetFollow(item, production, firsts, follows);
if (JudgeLL1(production, firsts, follows))
{
MessageBox.Show("该文法是 LL(1) 文法\n");
}
else
{
MessageBox.Show("该文法不是 LL(1) 文法,存在左递归或者存在 FIRST 集合有交集的情况!\n");
}
button1.Enabled = true;
button2.Enabled = true;
button6.Enabled = true;
button7.Enabled = true;
}
代码分析:
- 代码首先将 'richTextBox1' 中的文法字符串按行分割为产生式数组 'pro'。
- 然后遍历每个产生式,判断格式是否正确,将正确格式的产生式添加到字典 'production' 中,并将左部和右部分别作为 'key' 和 'value'。
- 接着,代码分别计算每个非终结符的 FIRST 集合和 FOLLOW 集合,并存储在字典 'firsts' 和 'follows' 中。
- 最后,代码通过函数 'JudgeLL1' 判断文法是否满足 LL(1) 文法条件,并根据结果显示相应的信息。
补充说明:
- 代码中省略了 'GetFirst'、'GetFollow' 和 'JudgeLL1' 函数的具体实现,这些函数是判断文法是否是 LL(1) 文法的核心逻辑,需要根据具体的算法和数据结构进行编写。
- 'production'、'firsts' 和 'follows' 字典是存储产生式、FIRST 集合和 FOLLOW 集合的关键数据结构,需要根据实际需求选择合适的字典类型和数据结构。
- 代码中使用了 'Regex' 类进行字符串匹配和分割,可以根据实际需求选择其他字符串处理方法。
- 代码中使用了 'MessageBox.Show' 显示结果,可以根据实际需求选择其他显示方式。
结论:
该代码通过计算 FIRST 集合和 FOLLOW 集合,并判断是否存在左递归和集合交集来判断一个文法是否是 LL(1) 文法,并通过 MessageBox 显示结果。代码逻辑清晰易懂,可供参考和学习。
原文地址: https://www.cveoy.top/t/topic/fYFR 著作权归作者所有。请勿转载和采集!