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 item = 'S' -> .S';
            itemsets.Add(item);
            states.Add(GetClosure(item));

            BuilditemFamily();
        }

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

            // 显示状态和项目族信息
            dataGridView1.AutoGenerateColumns = false; // 禁止自动生成列
            dataGridView1.Columns.Clear();
            dataGridView1.Columns.Add('State', '状态');
            dataGridView1.Columns.Add('ItemSet', '项目族信息');

            for (int i = 0; i < itemsets.Count; i++)
            {
                dataGridView1.Rows.Add();
                dataGridView1.Rows[i].Cells[0].Value = i;
                dataGridView1.Rows[i].Cells[1].Value = itemsets[i];
            }
        }

        private void BuilditemFamily()
        {
            int i = 0;
            while (i < itemsets.Count)
            {
                string itemset = itemsets[i];
                i++;

                // 获取该项目集的所有可移进符号
                List<string> shiftSymbols = GetShiftSymbols(itemset);
                foreach (string symbol in shiftSymbols)
                {
                    // 计算移进后的项目集
                    string newItemset = GetShiftItemset(itemset, symbol);
                    if (!itemsets.Contains(newItemset))
                    {
                        itemsets.Add(newItemset);
                        System.Diagnostics.Debug.WriteLine(newItemset);
                        states.Add(GetClosure(newItemset));
                    }

                    // 添加GOTO表项
                    int fromState = itemsets.IndexOf(itemset);
                    int toState = itemsets.IndexOf(newItemset);
                    string key = fromState + ',' + symbol;
                    string value = 'S' + toState;
                    if (!gotoTable.ContainsKey(key))
                    {
                        gotoTable[key] = new List<string>();
                    }
                    gotoTable[key].Add(value);
                }

                // 获取该项目集的所有规约符号
                List<string> reduceSymbols = GetReduceSymbols(itemset);
                foreach (string symbol in reduceSymbols)
                {
                    // 添加ACTION表项
                    int state = itemsets.IndexOf(itemset);
                    string key = state + ',' + symbol;
                    string value = 'r' + GetReduceProductionIndex(itemset, symbol);
                    if (!actionTable.ContainsKey(key))
                    {
                        actionTable[key] = new List<string>();
                    }
                    actionTable[key].Add(value);
                }
            }
        }

        // 获取闭包
        private string GetClosure(string item)
        {
            List<string> closure = new List<string>();
            closure.Add(item);

            int i = 0;
            while (i < closure.Count)
            {
                string item1 = closure[i];
                i++;

                string[] parts = item1.Split(' ');
                int dotIndex = parts.ToList().IndexOf('.');
                if (dotIndex != parts.Length - 1) // 不是最后一个符号
                {
                    string nextSymbol = parts[dotIndex + 1];
                    List<string> productionsWithNextSymbol = productions.Where(p => p.StartsWith(nextSymbol + ' ')).ToList();
                    foreach (string production in productionsWithNextSymbol)
                    {
                        string newItem = nextSymbol + ' -> .' + production.Split(new string[] { nextSymbol + ' ' }, StringSplitOptions.None)[1];
                        if (!closure.Contains(newItem))
                        {
                            closure.Add(newItem);
                        }
                    }
                }
            }

            return string.Join('\r\n', closure);
        }

        // 获取该项目集的所有可移进符号
        private List<string> GetShiftSymbols(string itemset)
        {
            List<string> shiftSymbols = new List<string>();

            string[] items = itemset.Split(new string[] { '\r\n' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string item in items)
            {
                string[] parts = item.Split(' ');
                int dotIndex = parts.ToList().IndexOf('.');
                if (dotIndex != parts.Length - 1) // 不是最后一个符号
                {
                    string nextSymbol = parts[dotIndex + 1];
                    if (!shiftSymbols.Contains(nextSymbol))
                    {
                        shiftSymbols.Add(nextSymbol);
                    }
                }
            }

            return shiftSymbols;
        }

        // 计算移进后的项目集
        private string GetShiftItemset(string itemset, string symbol)
        {
            List<string> newItems = new List<string>();

            string[] items = itemset.Split(new string[] { '\r\n' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string item in items)
            {
                string[] parts = item.Split(' ');
                int dotIndex = parts.ToList().IndexOf('.');
                if (dotIndex != parts.Length - 1) // 不是最后一个符号
                {
                    string nextSymbol = parts[dotIndex + 1];
                    if (nextSymbol == symbol)
                    {
                        string newItem = string.Join(' ', parts.Take(dotIndex)) + ' ' + nextSymbol + ' .' + string.Join(' ', parts.Skip(dotIndex + 2));
                        newItems.Add(newItem);
                    }
                }
            }

            return string.Join('\r\n', newItems);
        }

        // 获取该项目集的所有规约符号
        private List<string> GetReduceSymbols(string itemset)
        {
            List<string> reduceSymbols = new List<string>();

            string[] items = itemset.Split(new string[] { '\r\n' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string item in items)
            {
                string[] parts = item.Split(' ');
                int dotIndex = parts.ToList().IndexOf('.');
                if (dotIndex == parts.Length - 1) // 是最后一个符号
                {
                    string reduceSymbol = parts[0];
                    if (!reduceSymbols.Contains(reduceSymbol))
                    {
                        reduceSymbols.Add(reduceSymbol);
                    }
                }
            }

            return reduceSymbols;
        }

        // 获取规约产生式在文法产生式列表中的索引
        private int GetReduceProductionIndex(string itemset, string symbol)
        {
            string[] items = itemset.Split(new string[] { '\r\n' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string item in items)
            {
                string[] parts = item.Split(' ');
                int dotIndex = parts.ToList().IndexOf('.');
                if (dotIndex == parts.Length - 1) // 是最后一个符号
                {
                    string reduceSymbol = parts[0];
                    if (reduceSymbol == symbol)
                    {
                        return productions.IndexOf(string.Join(' ', parts.Take(dotIndex)));
                    }
                }
            }

            return -1;
        }
    }
}

问题分析

原代码的问题在于 button4_Click 函数中,直接使用 dataGridView1.Rows.Add(i, itemsets[i]); 添加行数据。由于 dataGridView1AutoGenerateColumns 属性默认为 True,这会导致 DataGridView 自动根据数据源生成列,而忽略手动添加的列。

解决方案

为了解决这个问题,需要进行以下两步修改:

  1. 禁止自动生成列:button4_Click 函数中,将 dataGridView1.AutoGenerateColumns 属性设置为 False,以禁止自动生成列。
  2. 手动添加数据: 使用 dataGridView1.Rows.Add(); 添加新行后,手动为每个单元格赋值,例如:
    dataGridView1.Rows[i].Cells[0].Value = i;
    dataGridView1.Rows[i].Cells[1].Value = itemsets[i];
    

修改后的代码

请参考上面JSON格式输出中的完整代码,其中 button4_Click 函数已进行修改。

希望这些信息对您有所帮助!

C#实现LR0语法分析器:构建项目集族

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

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