using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace LL1Grammar
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Dictionary<string, List<string>> production;
        Dictionary<string, List<string>> firsts;
        Dictionary<string, List<string>> follows;
        List<string> nonterminals;
        List<string> terminals;

        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;
            button3.Enabled = true;
        }

        // ... 其他函数 (GetFirst, GetFollow, JudgeLL1) ...

        private void button1_Click(object sender, EventArgs e)
        {
            // 获取所有的符号集合
            List<string> symbols = new List<string>();
            foreach (var item in production.Keys)
            {
                if (!symbols.Contains(item))
                    symbols.Add(item);
                foreach (var prod in production[item])
                {
                    foreach (var c in prod)
                    {
                        if (!symbols.Contains(c.ToString()))
                            symbols.Add(c.ToString());
                    }
                }
            }
            // 将符号集合按照终结符和非终结符分开
            nonterminals = new List<string>();
            terminals = new List<string>();
            foreach (var s in symbols)
            {
                if (char.IsUpper(s[0]))
                    nonterminals.Add(s);
                else
                    terminals.Add(s);
            }
            // 判断终结符集合中是否包含 '#'
            if (terminals.IndexOf('#') == -1)
            {
                terminals.Add('#');
            }


            listView1.Columns.Clear();
            listView1.Items.Clear();
            listView1.View = View.Details;

            // 添加第一列
            listView1.Columns.Add('', 40);

            // 添加终结符列
            foreach (var item in terminals)
            {
                listView1.Columns.Add(item, 40);
            }

            // 添加非终结符行
            foreach (var item in nonterminals)
            {
                ListViewItem lvi = new ListViewItem(item);
                lvi.SubItems.Add('');
                foreach (var t in terminals)
                {
                    lvi.SubItems.Add('');
                }
                listView1.Items.Add(lvi);
            }

            // 填充表格
            foreach (var item in firsts)
            {
                int row = nonterminals.IndexOf(item.Key);
                foreach (var t in terminals)
                {
                    int col = terminals.IndexOf(t);
                    if (!item.Value.Contains(t))
                        listView1.Items[row].SubItems[col + 1].Text = '0';
                    else
                        listView1.Items[row].SubItems[col + 1].Text = '1';
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            // ... (代码逻辑与 button1_Click 类似,只是展示 follows 集合) ...
        }

       // ... 其他函数 (GetFirst, GetFollow, JudgeLL1) ...
    }
}

代码说明:

  1. 引入命名空间:

    • using System.Collections.Generic; 用于使用字典和列表数据结构。
    • using System.Text.RegularExpressions; 用于使用正则表达式解析文法规则。
    • using System.Windows.Forms; 用于创建窗体应用程序和使用ListView控件。
  2. 定义成员变量:

    • production: 存储文法规则的字典,键为非终结符,值为该非终结符的产生式列表。
    • firsts: 存储FIRST集合的字典,键为文法符号,值为该符号的FIRST集合。
    • follows: 存储FOLLOW集合的字典,键为非终结符,值为该非终结符的FOLLOW集合。
    • nonterminals: 存储非终结符的列表。
    • terminals: 存储终结符的列表。
  3. button4_Click 函数:

    • richTextBox1 控件中读取用户输入的文法规则。
    • 使用正则表达式和字符串处理函数解析文法规则,并存储到 production 字典中。
    • 调用 GetFirst 函数计算每个文法符号的FIRST集合,存储到 firsts 字典中。
    • 调用 GetFollow 函数计算每个非终结符的FOLLOW集合,存储到 follows 字典中。
    • 调用 JudgeLL1 函数判断该文法是否为LL(1)文法,并弹出消息框显示结果。
    • 启用 button1button2button3 按钮,以便用户可以查看FIRST集合、FOLLOW集合和预测分析表。
  4. button1_Click 函数:

    • 获取文法中所有的符号,并将其分为非终结符和终结符两类。
    • 判断终结符集合中是否包含 '#',如果没有则添加 '#'。
    • 清空并设置 listView1 控件的列和视图模式。
    • 添加列标题,包括第一列和所有终结符。
    • 遍历非终结符列表,为每个非终结符添加一行,并在每行中添加对应终结符的单元格。
    • 遍历 firsts 字典,根据FIRST集合中的元素,将对应的单元格的值设置为 '1',否则设置为 '0'。
  5. button2_Click 函数:

    • 代码逻辑与 button1_Click 函数类似,只是展示 follows 集合,而不是 firsts 集合。

注意:

  • 本代码示例中省略了 GetFirstGetFollowJudgeLL1 函数的具体实现,您可以根据LL(1)文法的定义和算法自行补充。
  • 您需要在Visual Studio等C#开发环境中创建窗体应用程序,并将代码添加到相应的事件处理程序中才能运行本程序。
  • 本代码示例仅供参考,您可能需要根据实际需求进行修改和完善。
C#实现LL(1)文法判断及FIRST、FOLLOW集合计算与展示

原文地址: https://www.cveoy.top/t/topic/fXFv 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录