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 string startSymbol; // 文法开始符号

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

    // 显示状态和项目族信息

    listView1.Columns.Clear();
    listView1.Items.Clear();
    listView1.View = View.Details;
    
    // 添加列名
    listView1.Columns.Add('状态', 150);   
    listView1.Columns.Add('项目集信息', 300);

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

private void BuilditemFamily()
{
    // 初始化文法
    InitializeGrammar();
    // 初始化项目族
    List<ItemSet> itemFamily = new List<ItemSet>();
    ItemSet firstSet = new ItemSet();
    firstSet.items.Add(new Item(startSymbol, new List<string> { symbols[0] }, 0));
    itemFamily.Add(Closure(firstSet));
    // 构造项目族
    for (int i = 0; i < itemFamily.Count; i++)
    {
        ItemSet currentItemSet = itemFamily[i];
        for (int j = 0; j < symbols.Count; j++)
        {
            char symbol = symbols[j][0];
            ItemSet gotoItemSet = Goto(currentItemSet, symbol);
            if (gotoItemSet.items.Count > 0 && !itemFamily.Contains(gotoItemSet))
            {
                itemFamily.Add(gotoItemSet);
            }
        }
        states.Add('I' + i);
        itemsets.Add(string.Join('\n', currentItemSet.items.Select(item => item.ToString())));
    }
}

// 初始化文法
private void InitializeGrammar()
{
    // 解析输入
    productions.Clear();
    symbols.Clear();
    string[] lines = richTextBox1.Lines;
    for (int i = 0; i < lines.Length; i++)
    {
        string line = lines[i].Trim();
        if (line.Length == 0) continue;
        productions.Add(line);
        string lhs = line.Split(new char[] { ' ', '-' }, StringSplitOptions.RemoveEmptyEntries)[0];
        if (!symbols.Contains(lhs)) symbols.Add(lhs);
        string[] rhs = line.Split(new char[] { ' ', '-', '>' }, StringSplitOptions.RemoveEmptyEntries)[1].Split(new char[] { ' ', '|' }, StringSplitOptions.RemoveEmptyEntries);
        foreach (string symbol in rhs)
        {
            if (!symbols.Contains(symbol)) symbols.Add(symbol);
        }
    }
    startSymbol = productions[0].Split(new char[] { ' ', '-' }, StringSplitOptions.RemoveEmptyEntries)[0];
}

// 计算闭包
private ItemSet Closure(ItemSet itemSet)
{
    ItemSet closure = new ItemSet();
    while (true)
    {
        int originalLength = closure.items.Count;
        foreach (Item item in itemSet.items)
        {
            if (item.dotIndex == item.RHS.Count) continue;
            char nextSymbol = item.RHS[item.dotIndex][0];
            List<string> productions = GetProductions(nextSymbol);
            foreach (string production in productions)
            {
                Item newItem = new Item(production.Split(new char[] { ' ', '-' }, StringSplitOptions.RemoveEmptyEntries)[0],
                    production.Split(new char[] { ' ', '-', '>' }, StringSplitOptions.RemoveEmptyEntries)[1].Split(new char[] { ' ', '|' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
                    0);
                if (!closure.items.Contains(newItem))
                {
                    closure.items.Add(newItem);
                }
            }
        }
        if (closure.items.Count == originalLength) break;
    }
    return closure;
}

// 计算Goto
private ItemSet Goto(ItemSet itemSet, char symbol)
{
    ItemSet gotoSet = new ItemSet();
    foreach (Item item in itemSet.items)
    {
        if (item.dotIndex == item.RHS.Count) continue;
        if (item.RHS[item.dotIndex][0] == symbol)
        {
            gotoSet.items.Add(new Item(item.LHS, item.RHS, item.dotIndex + 1));
        }
    }
    return Closure(gotoSet);
}

// 获取所有左部为symbol的产生式
private List<string> GetProductions(char symbol)
{
    return productions.Where(p => p.StartsWith(symbol + ' -')).ToList();
}

// 项目类
private class Item
{
    public string LHS; // 产生式左部
    public List<string> RHS; // 产生式右部
    public int dotIndex; // 点的位置

    public Item(string lhs, List<string> rhs, int dotIndex)
    {
        this.LHS = lhs;
        this.RHS = rhs;
        this.dotIndex = dotIndex;
    }

    // 判断两个项目是否相等
    public override bool Equals(object obj)
    {
        if (obj == null || GetType() != obj.GetType())
        {
            return false;
        }

        Item other = (Item)obj;
        return LHS == other.LHS && dotIndex == other.dotIndex && RHS.Count == other.RHS.Count
                && new HashSet<string>(RHS).SetEquals(other.RHS);
    }

    public override int GetHashCode()
    {
        return LHS.GetHashCode() ^ dotIndex.GetHashCode() ^ RHS.GetHashCode();
    }

    public override string ToString()
    {
        List<string> tempRHS = new List<string>(RHS);
        tempRHS.Insert(dotIndex, '.');
        return $'{LHS}->{string.Join('', tempRHS)}';
    }
}

// 项目集类
private class ItemSet
{
    public List<Item> items = new List<Item>();

    public override bool Equals(object obj)
    {
        if (obj == null || GetType() != obj.GetType())
        {
            return false;
        }

        ItemSet otherSet = (ItemSet)obj;
        return items.SequenceEqual(otherSet.items);
    }

    public override int GetHashCode()
    {
        return items.GetHashCode();
    }
}
LR(0) 分析器项目族生成算法

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

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