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表

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)//生成项目族信息
{
    itemsets.Clear();
    states.Clear();
    BuilditemFamily();
    // 显示状态和项目族信息
    dataGridView1.Columns.Clear();
    dataGridView1.Columns.Add("State", "状态");
    dataGridView1.Columns.Add("ItemSet", "项目族信息");
    for (int i = 0; i < itemsets.Count; i++)
    {
        dataGridView1.Rows.Add(i, 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;
}

上述函数在dataGridView1上什么也不输出,可能是因为在调用BuilditemFamily()函数时,没有清空itemsetsstates列表,导致新增的状态和项目族信息没有被正确添加。可以在调用前先清空这两个列表,如下所示:

private void button4_Click(object sender, EventArgs e)//生成项目族信息
{
    itemsets.Clear();
    states.Clear();
    BuilditemFamily();
    // 显示状态和项目族信息
    dataGridView1.Columns.Clear();
    dataGridView1.Columns.Add("State", "状态");
    dataGridView1.Columns.Add("ItemSet", "项目族信息");
    for (int i = 0; i < itemsets.Count; i++)
    {
        dataGridView1.Rows.Add(i, itemsets[i]);
    }
}
LR(0) 文法分析器实现 - 项目族构建与分析

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

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