using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace byyljxfzxt
{
    public partial class Form4 : Form
    {
        public Form4()
        {
            InitializeComponent();
        }

        //--------------------预处理
        Dictionary<string, List<string>> production;
        Dictionary<string, List<string>> firsts;
        Dictionary<string, List<string>> follows;
        List<string> terminals;
        List<string> nonterminals;

        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;

        }

        private void button6_Click(object sender, EventArgs e)
        {
            //构造预测分析表
            Dictionary<string, Dictionary<string, string>> table = new Dictionary<string, Dictionary<string, string>>();
            foreach (var nonterminal in nonterminals)
            {
                table.Add(nonterminal, new Dictionary<string, string>());
                foreach (var terminal in terminals)
                {
                    table[nonterminal].Add(terminal, "");
                }
            }

            Select select = GetSelect(production, firsts, follows);
            foreach (var item in production)
            {
                string A = item.Key;
                foreach (var prod in item.Value)
                {
                    foreach (var t in select.getselects()[A][prod])
                    {
                        if (table[A][t] != "")
                        {
                            MessageBox.Show("该文法不是LL(1)文法,存在冲突!\n");
                            return;
                        }
                        table[A][t] = prod;
                    }
                }
            }

            //输出预测分析表
            listView3.Clear();
            foreach (var terminal in terminals)
            {
                listView3.Columns.Add(terminal, 100, HorizontalAlignment.Center);
            }
            foreach (var nonterminal in nonterminals)
            {
                ListViewItem lvi = new ListViewItem(nonterminal);
                foreach (var terminal in terminals)
                {
                    lvi.SubItems.Add(table[nonterminal][terminal]);
                }
                listView3.Items.Add(lvi);
            }
        }

        
        private void GetFirst(string symbol, Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1)
        {
            // 如果该非终结符的 FIRST 集已经被计算出,则直接返回
            if (firsts1.ContainsKey(symbol))
            {
                return;
            }
            firsts1.Add(symbol, new List<string>());
            // 遍历产生式,计算 FIRST 集
            foreach (var prod in production1[symbol])
            {
                // 如果产生式首字符为终结符,则直接将其加入 FIRST 集中
                if (prod.Length > 0 && IsTerminal(prod[0]))
                {
                    if (!firsts1[symbol].Contains(prod[0].ToString()))
                        firsts1[symbol].Add(prod[0].ToString());
                    continue;
                }
                // 如果产生式首字符为非终结符,则计算该非终结符的 FIRST 集,并将结果加入首字符的 FIRST 集中
                else if (prod.Length > 0 && !IsTerminal(prod[0]))
                {
                    GetFirst(prod[0].ToString(), production1, firsts1);
                    foreach (var f in firsts1[prod[0].ToString()])
                    {
                        if (!firsts1[symbol].Contains(f) && !f.Equals('#'))
                            firsts1[symbol].Add(f);
                    }
                }
                //如果第一个非终结符能推出#
                if (IsReachEmpty(prod[0].ToString(), production1))
                {
                    // 递归计算第二个和后面的字符的 FIRST 集,并将结果加入该非终结符的 FIRST 集中
                    for (int j = 1; j < prod.Length; j++)
                    {
                        if (IsTerminal(prod[j]))
                        {
                            if (!firsts1[symbol].Contains(prod[j].ToString()))
                                firsts1[symbol].Add(prod[j].ToString());
                            break;
                        }
                        GetFirst(prod[j].ToString(), production1, firsts1);
                        foreach (var f in firsts1[prod[j].ToString()])
                        {
                            if (!firsts1[symbol].Contains(f) && !f.Equals('#'))
                                firsts1[symbol].Add(f);
                        }
                        // 如果该非终结符的 FIRST 集没有包含空串,则可以结束循环
                        if (!IsReachEmpty(prod[j].ToString(), production1))
                        {
                            break;
                        }
                        // 如果是最后一个字符且所有非终结符的 FIRST 集都含有空串,则将空串加入该非终结符的 FIRST 集中
                        if (j == prod.Length - 1)
                        {
                            if (!firsts1[symbol].Contains("#"))
                                firsts1[symbol].Add("#");
                        }
                    }
                }
            }
        }

       
        // 计算 FOLLOW 集
        private void GetFollow(string symbol, Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1, Dictionary<string, List<string>> follows1)
        {
            // 如果该非终结符的 FOLLOW 集已经被计算出,则直接返回
            if (follows1.ContainsKey(symbol))
            {
                return;
            }
            follows1.Add(symbol, new List<string>());
            // 如果是起始符号,则将 # 加入 FOLLOW 集中
            if (symbol.Equals(production1.Keys.First()))
            {
                if (!follows1[symbol].Contains("#"))
                    follows1[symbol].Add("#");
            }
            // 遍历产生式,计算 FOLLOW 集
            foreach (var item in production1)
            {
                foreach (var prod in item.Value)
                {
                    int index = prod.IndexOf(symbol);
                    if (index == -1)
                        continue;
                    // 如果该非终结符位于产生式末尾,则将产生式左部的 FOLLOW 集加入该非终结符的 FOLLOW 集中
                    if (index == prod.Length - 1)
                    {
                        GetFollow(item.Key, production1, firsts1, follows1);
                        foreach (var f in follows1[item.Key])
                        {
                            if (!follows1[symbol].Contains(f))
                                follows1[symbol].Add(f);
                        }
                    }
                    else
                    {
                        // 如果该非终结符后面是终结符,则将该终结符加入该非终结符的 FOLLOW 集中
                        if (IsTerminal(prod[index + 1]))
                        {
                            if (!follows1[symbol].Contains(prod[index + 1].ToString()))
                                follows1[symbol].Add(prod[index + 1].ToString());
                        }
                        // 如果该非终结符后面是非终结符,则将该非终结符的 FIRST 集加入该非终结符的 FOLLOW 集中
                        else
                        {
                            GetFirst(prod[index + 1].ToString(), production1, firsts1);
                            foreach (var f in firsts1[prod[index + 1].ToString()])
                            {
                                if (!f.Equals("#") && !follows1[symbol].Contains(f))
                                    follows1[symbol].Add(f);
                            }
                            // 如果该非终结符后面的所有符号都能推出空串,则将产生式左部的 FOLLOW 集加入该非终结符的 FOLLOW 集中
                            if (IsReachEmpty(prod[index + 1].ToString(), production1))
                            {
                                GetFollow(item.Key, production1, firsts1, follows1);
                                foreach (var f in follows1[item.Key])
                                {
                                    if (!follows1[symbol].Contains(f))
                                        follows1[symbol].Add(f);
                                }
                            }
                        }
                    }
                }
            }
        }

      
        private Select GetSelect(Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1, Dictionary<string, List<string>> follows1)
        {
            // 初始化 LL1Item、First 和 Follow 对象
            LL1Item ll1Item = new LL1Item(production1, firsts1);
            First first = new First(firsts1);
            Follow follow = new Follow(follows1);

            // 创建 Select 对象,并返回
            return new Select(ll1Item, first, follow);
        }
        static bool IsTerminal(char symbol)
        {
            return !char.IsUpper(symbol);
        }

        private bool IsReachEmpty(string symbol, Dictionary<string, List<string>> production1)
        {
            foreach (var prod in production1[symbol])
            {
                if (prod.Equals("#"))
                    return true;
            }
            return false;
        }

        private bool JudgeLL1(Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1, Dictionary<string, List<string>> follows1)
        {
            // 检查 FIRST 集合是否有交集
            foreach (var item1 in firsts1)
            {
                foreach (var item2 in firsts1)
                {
                    if (item1.Key.Equals(item2.Key)) continue;
                    // 两个不同的非终结符的 FIRST 集合存在交集,则不是 LL(1) 文法
                    if (item1.Value.Intersect(item2.Value).Any() && (item1.Value.Contains("#") || item2.Value.Contains("#")))
                    {
                        return false;
                    }
                }
            }
            // 检查 FOLLOW 集合是否有交集
            foreach (var item1 in follows1)
            {
                foreach (var item2 in follows1)
                {
                    if (item1.Key.Equals(item2.Key)) continue;
                    // 两个不同的非终结符的 FOLLOW 集合存在交集,则不是 LL(1) 文法
                    if (item1.Value.Intersect(item2.Value).Any())
                    {
                        return false;
                    }
                }
            }
            return true;
        }

        
    }
    // LL1Item 类,用于存储产生式和 First 集合信息
    public class LL1Item
    {
        private Dictionary<string, List<string>> production;
        private Dictionary<string, List<string>> firsts;
        private List<string> nofinal;

        public LL1Item(Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1)
        {
            production = production1;
            firsts = firsts1;
            nofinal = new List<string>(production1.Keys);
        }

        public Dictionary<string, List<string>> getproduction()
        {
            return production;
        }

        public List<string> getnofinal()
        {
            return nofinal;
        }
    }
    // First 类,用于存储 First 集合信息
    public class First
    {
        private Dictionary<string, List<string>> firsts;

        public First(Dictionary<string, List<string>> firsts1)
        {
            firsts = firsts1;
        }

        public Dictionary<string, List<string>> getfirsts()
        {
            return firsts;
        }
    }
    // Follow 类,用于存储 Follow 集合信息
    public class Follow
    {
        private Dictionary<string, List<string>> follows;

        public Follow(Dictionary<string, List<string>> follows1)
        {
            follows = follows1;
        }

        public Dictionary<string, List<string>> getfollows()
        {
            return follows;
        }
    }
    // Select 类,用于存储 SELECT 集合信息
    public 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;
        }
    }
}
C# LL(1) 预测分析表生成算法实现

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

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