C# 实现 LL(1) 文法预测分析表
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace LL1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// ... 其他代码 ...
private void button6_Click(object sender, EventArgs e)
{
// 获取产生式、非终结符、终结符
var LL1Item = new LL1Item();
LL1Item.GetLL1Item(listView1);
// 获取 First 集
var first = new First(LL1Item.getproduction());
first.GetFirst();
// 获取 Follow 集
var follow = new Follow(LL1Item.getproduction(), first.getfirsts());
follow.GetFollow();
// 获取 Select 集
var select = new Select(LL1Item, first, follow);
var selects = select.getselects();
// 构造预测分析表
var terminals = LL1Item.getterminals();
var nofinals = LL1Item.nofinal;
var production = LL1Item.getproduction();
var table = new Dictionary<string, Dictionary<string, string>>();
foreach (var nofinal in nofinals)
{
table.Add(nofinal, new Dictionary<string, string>());
foreach (var terminal in terminals)
{
table[nofinal].Add(terminal, '');
}
table[nofinal].Add('#', '');
}
foreach (var nofinal in nofinals)
{
foreach (var f in production[nofinal])
{
var selectset = selects[nofinal][f];
foreach (var s in selectset)
{
if (s.Equals('#'))
{
foreach (var fol in follow.getfollows()[nofinal])
{
table[nofinal][fol] = f;
}
}
else
{
table[nofinal][s] = f;
}
}
}
}
// 输出预测分析表
listView3.Clear();
listView3.Columns.Add('', 40, HorizontalAlignment.Center);
foreach (var terminal in terminals)
{
listView3.Columns.Add(terminal, 40, HorizontalAlignment.Center);
}
listView3.Columns.Add('#', 40, HorizontalAlignment.Center);
foreach (var nofinal in nofinals)
{
var item = new ListViewItem(nofinal);
foreach (var terminal in terminals)
{
item.SubItems.Add(table[nofinal][terminal]);
}
item.SubItems.Add(table[nofinal]['#']);
listView3.Items.Add(item);
}
}
// ... 其他代码 ...
}
class Select
{
LL1Item LL1Item;
First first;
Follow follow;
Dictionary<string, Dictionary<string, List<string>>> selects;
public Select(LL1Item LL1Item, First first, Follow follow)
{
this.LL1Item = LL1Item;
this.first = first;
this.follow = follow;
selects = new Dictionary<string, Dictionary<string, List<string>>>();
GetSelect();
}
public void GetSelect()
{
var production = LL1Item.getproduction();
foreach (var nofinal in LL1Item.nofinal)
{
selects.Add(nofinal, new Dictionary<string, List<string>>());
// 对非终结符的每个产生式获取 select 值
foreach (var f in production[nofinal])
{
selects[nofinal].Add(f, new List<string>());
for (int i = 0; i < f.Length; i++)
{
// 如果该产生式第一个字符为终结符
if (IsTerminal(f[i]))
{
if (f[i].Equals('#'))
{
foreach (var fol in follow.getfollows()[nofinal])
selects[nofinal][f].Add(fol);
}
else if (!selects[nofinal][f].Contains(f[i].ToString()))
selects[nofinal][f].Add(f[i].ToString());
break;
}
// 如果该产生式第一个字符为非终结符
else
{
int flag = 0;
foreach (var fir in first.getfirsts()[f[i].ToString()])
{
if (fir.Equals('#'))
flag = 1;
else
{
if (!selects[nofinal][f].Contains(fir))
selects[nofinal][f].Add(fir);
}
}
if (flag == 0) break;
}
if (i == f.Length - 1)
{
foreach (var fol in follow.getfollows()[nofinal])
if (!selects[nofinal][f].Contains(fol))
selects[nofinal][f].Add(fol);
}
}
}
}
}
static bool IsTerminal(char symbol)
{
return !char.IsUpper(symbol);
}
public Dictionary<string, Dictionary<string, List<string>>> getselects()
{
return selects;
}
}
// ... 其他代码 ...
}
代码说明:
-
button6_Click函数:- 获取用户输入的文法信息,并构建 LL(1) 分析表所需的数据结构,包括 First 集、Follow 集和 Select 集。
- 使用嵌套循环遍历所有非终结符和终结符,根据 Select 集填充预测分析表。
- 将生成的预测分析表显示在 ListView 控件中,方便用户查看。
-
Select类:- 实现了计算 LL(1) 文法 Select 集的逻辑。
- 使用字典存储 Select 集,键值对分别为非终结符和对应的 Select 集。
SEO 优化说明:
- 标题和描述中包含了与 LL(1) 文法分析相关的关键词,方便搜索引擎收录。
- 代码注释清晰,方便开发者理解代码逻辑。
- 使用了 C# 代码块,方便开发者复制代码并运行。
- 提供了代码说明,方便开发者快速了解代码的功能和实现方式。
希望以上信息能够帮到您! 😊
原文地址: https://www.cveoy.top/t/topic/fXGl 著作权归作者所有。请勿转载和采集!