using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace LR0Parser
{
    public partial class Form1 : Form
    {
        private List<string> productions = new List<string>(); // 存储文法产生式
        private List<string> symbols = new List<string>(); // 存储文法符号
        private List<string> states = new List<string>(); // 存储状态
        private List<string> itemsets = new List<string>(); // 存储项目族
        private Dictionary<string, List<string>> gotoTable = new Dictionary<string, List<string>>(); // 存储GOTO表
        private Dictionary<string, List<string>> actionTable = new Dictionary<string, List<string>>(); // 存储ACTION表

        public Form1()
        {
            InitializeComponent();
        }

        private void button2_Click(object sender, EventArgs e)//判别LR0文法
        {
            // 读取文法产生式
            string[] productionsArr = richTextBox1.Text.Split(new string[] { '\r\n' }, StringSplitOptions.RemoveEmptyEntries);
            productions.AddRange(productionsArr);

            // 获取文法符号
            foreach (string production in productions)
            {
                string[] parts = production.Split(' ');
                foreach (string part in parts)
                {
                    if (!symbols.Contains(part))
                    {
                        symbols.Add(part);
                    }
                }
            }

            // 初始化状态0
            string initialState = '0';
            List<string> initialItemset = new List<string>();
            initialItemset.Add(productions[0] + ' .'); // 初始项目
            itemsets.Add(string.Join('\r\n', initialItemset));
            states.Add(initialState);

            // 生成项目族
            BuilditemFamily();

            // 生成GOTO表和ACTION表
            BuildTables();

            // 显示状态和项目族信息
            // 添加第一列
            listView1.Columns.Add('', 50);

            // 添加列名
            listView1.Columns.Add('状态', 50);
            listView1.Columns.Add('项目集信息', 50);

            // 添加数据
            for (int i = 0; i < states.Count; i++)
            {
                ListViewItem item = new ListViewItem();
                item.SubItems[0].Text = (i + 1).ToString();
                item.SubItems.Add(states[i]);
                item.SubItems.Add(itemsets[i]);
                listView1.Items.Add(item);
            }
        }

        private void BuilditemFamily()
        {
            int index = 0;
            while (index < itemsets.Count)
            {
                // 获取当前项目集的所有项目
                List<string> itemset = itemsets[index].Split(new string[] { '\r\n' }, StringSplitOptions.RemoveEmptyEntries).ToList();

                // 获取当前项目集中所有的非终结符
                List<string> nonterminals = new List<string>();
                foreach (string item in itemset)
                {
                    string[] parts = item.Split(' ');
                    for (int i = 0; i < parts.Length; i++)
                    {
                        if (i < parts.Length - 1 && !symbols.Contains(parts[i]) && !nonterminals.Contains(parts[i]))
                        {
                            nonterminals.Add(parts[i]);
                        }
                    }
                }

                // 对每个非终结符进行扩展
                foreach (string nonterminal in nonterminals)
                {
                    List<string> newItemset = new List<string>();
                    foreach (string item in itemset)
                    {
                        string[] parts = item.Split(' ');
                        for (int i = 0; i < parts.Length - 1; i++)
                        {
                            if (parts[i] == nonterminal)
                            {
                                string newItem = string.Join(' ', parts.Take(i)) + ' ' + nonterminal + ' .' + string.Join(' ', parts.Skip(i + 1));
                                if (!newItemset.Contains(newItem))
                                {
                                    newItemset.Add(newItem);
                                }
                            }
                        }
                    }

                    // 计算新的项目集
                    List<string> closure = Closure(newItemset);
                    string newState = Goto(index, nonterminal);
                    if (!states.Contains(newState))
                    {
                        states.Add(newState);
                        itemsets.Add(string.Join('\r\n', closure));
                    }
                }

                index++;
            }
        }

        private List<string> Closure(List<string> itemset)
        {
            List<string> closure = new List<string>();
            closure.AddRange(itemset);

            int index = 0;
            while (index < closure.Count)
            {
                string[] parts = closure[index].Split(' ');
                for (int i = 0; i < parts.Length - 1; i++)
                {
                    if (parts[i] == '.')
                    {
                        string nextSymbol = parts[i + 1];
                        if (symbols.Contains(nextSymbol))
                        {
                            // 扩展项目
                            foreach (string production in productions)
                            {
                                string[] productionParts = production.Split(' ');
                                if (productionParts[0] == nextSymbol)
                                {
                                    string newItem = nextSymbol + ' . ' + string.Join(' ', productionParts.Skip(1));
                                    if (!closure.Contains(newItem))
                                    {
                                        closure.Add(newItem);
                                    }
                                }
                            }
                        }
                    }
                }

                index++;
            }

            return closure;
        }

        private string Goto(int index, string symbol)
        {
            List<string> itemset = itemsets[index].Split(new string[] { '\r\n' }, StringSplitOptions.RemoveEmptyEntries).ToList();
            List<string> newItemset = new List<string>();
            foreach (string item in itemset)
            {
                string[] parts = item.Split(' ');
                for (int i = 0; i < parts.Length - 1; i++)
                {
                    if (parts[i] == '.' && parts[i + 1] == symbol)
                    {
                        string newItem = string.Join(' ', parts.Take(i)) + ' ' + symbol + ' .' + string.Join(' ', parts.Skip(i + 2));
                        if (!newItemset.Contains(newItem))
                        {
                            newItemset.Add(newItem);
                        }
                    }
                }
            }

            List<string> closure = Closure(newItemset);
            return string.Join(',', closure);
        }

        private void BuildTables()
        {
            for (int i = 0; i < states.Count; i++)
            {
                List<string> itemset = itemsets[i].Split(new string[] { '\r\n' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                foreach (string item in itemset)
                {
                    string[] parts = item.Split(' ');
                    for (int j = 0; j < parts.Length - 1; j++)
                    {
                        if (parts[j] == '.')
                        {
                            string nextSymbol = parts[j + 1];
                            if (symbols.Contains(nextSymbol))
                            {
                                // GOTO表项
                                string newState = Goto(i, nextSymbol);
                                if (!gotoTable.ContainsKey(states[i]))
                                {
                                    gotoTable.Add(states[i], new List<string>());
                                }
                                gotoTable[states[i]].Add(newState + ':' + nextSymbol);
                            }
                            else
                            {
                                // ACTION表项
                                string action;
                                if (nextSymbol == '$')
                                {
                                    action = 'acc';
                                }
                                else
                                {
                                    action = 's' + states.IndexOf(Goto(i, nextSymbol));
                                }

                                if (!actionTable.ContainsKey(states[i]))
                                {
                                    actionTable.Add(states[i], new List<string>());
                                }
                                actionTable[states[i]].Add(action + ':' + nextSymbol);
                            }
                        }
                    }
                }
            }
        }

        private void button4_Click(object sender, EventArgs e)//生成项目族信息
        {
            BuilditemFamily();

            // 显示状态和项目族信息
            // 添加第一列
            listView1.Columns.Add('', 50);

            // 添加列名
            listView1.Columns.Add('状态', 50);
            listView1.Columns.Add('项目集信息', 50);

            // 添加数据
            for (int i = 0; i < states.Count; i++)
            {
                ListViewItem item = new ListViewItem();
                item.SubItems[0].Text = (i + 1).ToString();
                item.SubItems.Add(states[i]);
                item.SubItems.Add(itemsets[i]);
                listView1.Items.Add(item);
            }
        }
    }
}
C#实现LR(0)分析器:判别文法与生成项目族信息

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

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