private void button2_Click(object sender, EventArgs e)
{
    string str = richTextBox1.Text;
    if (str.Length == 0)
    {
        MessageBox.Show("输入为空");
        return;
    }
    string temp = "";
    int i = 0;
    while (i < str.Length)
    {
        temp = "";
        while (i < str.Length && str[i] != '\r' && str[i] != '\n')
        {
            if (str[i] != ' ')
                temp += str[i];
            i++;
        }
        i++;

        if (temp.Length > 0 && temp[temp.Length - 1] == '|')
        {
            MessageBox.Show("不得包含空串!");
            return;
        }
        if (temp.Length > 3)
        {
            if (temp[0] < 'A' || temp[0] > 'Z')
            {
                MessageBox.Show("含有非法左部!");
                return;
            }
            if (temp[1] != '-' || temp[2] != '>')
            {
                MessageBox.Show("产生式输入不规范!");
                return;
            }
            for (int j = 3; j < temp.Length; j++)
            {
                if (!char.IsUpper(temp[j]) && !char.IsLower(temp[j]) && temp[j] != '|' && temp[j] != '*' && temp[j] != '+' && temp[j] != '(' && temp[j] != ')' && temp[j] != '[' && temp[j] != ']' && temp[j] != '{' && temp[j] != '}' && temp[j] != '.' && temp[j] != ',' && temp[j] != ';' && temp[j] != ':' && temp[j] != '=' && temp[j] != '<' && temp[j] != '>')
                {
                    MessageBox.Show("含有非法字符!");
                    return;
                }
            }
        }
        if (temp.Length <= 3 && temp.Length > 0)
        {
            MessageBox.Show("产生式输入不规范!");
            return;
        }
    }
    if (LR0Judge(str))
    {
        MessageBox.Show("正确的LR(0)文法");
        button4.Enabled = true;
        button5.Enabled = true;
        button6.Enabled = true;
    }
    else
    {
        MessageBox.Show("不是LR(0)文法!");
    }
}

// 判断是否为LR(0)文法
private bool LR0Judge(string str)
{
    // 构造产生式
    List<Production> productions = new List<Production>();
    string[] lines = str.Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
    foreach (string line in lines)
    {
        string[] sides = line.Split(new char[] { '-', '>' }, StringSplitOptions.RemoveEmptyEntries);
        Production production = new Production(sides[0][0], sides[1]);
        productions.Add(production);
    }
    // 构造项集族
    ItemSetCollection itemSetCollection = new ItemSetCollection(productions);
    // 判断是否存在移进规约冲突
    if (itemSetCollection.HasShiftReduceConflict())
    {
        return false;
    }
    // 判断是否存在规约规约冲突
    if (itemSetCollection.HasReduceReduceConflict())
    {
        return false;
    }
    return true;
}

完善后的构造LR分析表函数button5_Click代码:

private void button5_Click(object sender, EventArgs e)
{
    listView2.Clear();

    LR.Table[][] table;
    table = lr.GET_ANA();
    int xlen = table.GetLength(0);
    int ylen = table[1].Length;

    listView2.Columns.Clear();
    listView2.Items.Clear();
    listView2.View = View.Details;

    listView2.Columns.Add(" ");

    for (int i = 0; i < lr.Echar.Count; i++)//添加表头
    {
        string text = lr.Echar[i].ToString();
        listView2.Columns.Add(text, 58);

    }
    for (int i = 0; i < lr.Nchar.Count; i++)//添加表头
    {
        string text = lr.Nchar[i].ToString();
        listView2.Columns.Add(text, 58);
    }

    for (int i = 0; i < xlen; i++)
    {
        ListViewItem li = new ListViewItem(i.ToString());

        for (int j = 0; j < ylen; j++)
        {
            string st = "";
            if (table[i][j].error)
                st = "-";
            else if (table[i][j].type == 'A')
                st = "AC";
            else if (table[i][j].type == 'S' || table[i][j].type == 'R')
            {
                if (table[i][j].shiftReduceConflict || table[i][j].reduceReduceConflict)
                {
                    st = "Conflict";
                }
                else
                {
                    st = table[i][j].type.ToString() + table[i][j].id.ToString();
                }
            }
            li.SubItems.Add(st);

        }
        listView2.Items.Add(li);
    }

    listView2.GridLines = true;
}

相关调用函数:

public class ItemSetCollection
{
    // 项集族
    public List<ItemSet> ItemSets { get; private set; }
    // 活前缀和非终结符
    private List<char> _livePrefixes;
    private List<char> _nonTerminals;
    // 产生式
    private List<Production> _productions;
    // FIRST集
    private Dictionary<char, HashSet<char>> _firstSets;
    // FOLLOW集
    private Dictionary<char, HashSet<char>> _followSets;
    // LR(0)自动机
    private LR0Automaton _automaton;
    // 移进规约冲突
    public bool HasShiftReduceConflict()
    {
        foreach (ItemSet itemSet in ItemSets)
        {
            foreach (Item item in itemSet.Items)
            {
                if (item.IsReduceItem)
                {
                    if (itemSet.Actions.ContainsKey(item.FollowSymbol))
                    {
                        // 存在移进规约冲突
                        return true;
                    }
                }
            }
        }
        return false;
    }
    // 规约规约冲突
    public bool HasReduceReduceConflict()
    {
        foreach (ItemSet itemSet in ItemSets)
        {
            List<Item> reduceItems = itemSet.Items.FindAll(p => p.IsReduceItem);
            if (reduceItems.Count > 1)
            {
                HashSet<char> reduceSymbols = new HashSet<char>();
                foreach (Item reduceItem in reduceItems)
                {
                    reduceSymbols.Add(reduceItem.Production.Left);
                }
                if (reduceSymbols.Count > 1)
                {
                    // 存在规约规约冲突
                    return true;
                }
            }
        }
        return false;
    }
    // 构造函数
    public ItemSetCollection(List<Production> productions)
    {
        _productions = productions;
        _livePrefixes = new List<char>();
        _nonTerminals = new List<char>();
        foreach (Production production in productions)
        {
            if (!_nonTerminals.Contains(production.Left))
            {
                _nonTerminals.Add(production.Left);
            }
        }
        // 计算FIRST集和FOLLOW集
        _firstSets = new Dictionary<char, HashSet<char>>();
        _followSets = new Dictionary<char, HashSet<char>>();
        foreach (char nonTerminal in _nonTerminals)
        {
            _firstSets.Add(nonTerminal, new HashSet<char>());
            _followSets.Add(nonTerminal, new HashSet<char>());
        }
        foreach (char nonTerminal in _nonTerminals)
        {
            CalculateFirst(nonTerminal);
        }
        CalculateFollow();
        // 构造项集族
        _automaton = new LR0Automaton(productions, _firstSets, _followSets);
        ItemSets = _automaton.BuildDFA();
    }
    // 计算非终结符的FIRST集
    private void CalculateFirst(char nonTerminal)
    {
        foreach (Production production in _productions.FindAll(p => p.Left == nonTerminal))
        {
            if (production.Right.Length == 0)
            {
                _firstSets[nonTerminal].Add('#');
            }
            else
            {
                foreach (char symbol in production.Right)
                {
                    if (char.IsUpper(symbol))
                    {
                        _firstSets[nonTerminal].UnionWith(_firstSets[symbol]);
                        if (!_livePrefixes.Contains(symbol))
                        {
                            break;
                        }
                    }
                    else
                    {
                        _firstSets[nonTerminal].Add(symbol);
                        break;
                    }
                }
            }
        }
    }
    // 计算非终结符的FOLLOW集
    private void CalculateFollow()
    {
        _followSets[_productions[0].Left].Add('#');
        while (true)
        {
            bool changed = false;
            foreach (Production production in _productions)
            {
                for (int i = 0; i < production.Right.Length; i++)
                {
                    if (char.IsUpper(production.Right[i]))
                    {
                        bool hasEpsilon = false;
                        for (int j = i + 1; j < production.Right.Length; j++)
                        {
                            if (char.IsUpper(production.Right[j]))
                            {
                                _followSets[production.Right[i]].UnionWith(_firstSets[production.Right[j]]);
                                if (!_firstSets[production.Right[j]].Contains('#'))
                                {
                                    hasEpsilon = false;
                                    break;
                                }
                            }
                            else
                            {
                                _followSets[production.Right[i]].Add(production.Right[j]);
                                hasEpsilon = false;
                                break;
                            }
                        }
                        if (hasEpsilon || i == production.Right.Length - 1)
                        {
                            _followSets[production.Right[i]].UnionWith(_followSets[production.Left]);
                        }
                    }
                }
            }
            if (!changed)
            {
                break;
            }
        }
    }
}

public class LR0Automaton
{
    // 项集族
    private ItemSetCollection _itemSetCollection;
    // 产生式
    private List<Production> _productions;
    // FIRST集
    private Dictionary<char, HashSet<char>> _firstSets;
    // FOLLOW集
    private Dictionary<char, HashSet<char>> _followSets;
    // 自动机的状态
    private List<ItemSet> _states;
    // 构造函数
    public LR0Automaton(List<Production> productions, Dictionary<char, HashSet<char>> firstSets, Dictionary<char, HashSet<char>> followSets)
    {
        _productions = productions;
        _firstSets = firstSets;
        _followSets = followSets;
    }
    // 构造DFA
    public List<ItemSet> BuildDFA()
    {
        _states = new List<ItemSet>();
        // 初始项集
        ItemSet initialItemSet = new ItemSet();
        initialItemSet.AddItem(new Item(_productions[0], 0));
        Closure(initialItemSet);
        _states.Add(initialItemSet);
        // 遍历项集族
        for (int i = 0; i < _states.Count; i++)
        {
            ItemSet currentState = _states[i];
            Dictionary<char, ItemSet> transitions = new Dictionary<char, ItemSet>();
            // 计算当前项集的转移项集
            foreach (Item item in currentState.Items)
            {
                if (!item.IsReduceItem)
                {
                    char symbol = item.NextSymbol;
                    Item newItem = new Item(item.Production, item.DotPosition + 1);
                    if (!transitions.ContainsKey(symbol))
                    {
                        ItemSet newItemSet = new ItemSet();
                        newItemSet.AddItem(newItem);
                        Closure(newItemSet);
                        transitions.Add(symbol, newItemSet);
                    }
                    else
                    {
                        transitions[symbol].AddItem(newItem);
                    }
                }
            }
            // 遍历转移项集
            foreach (KeyValuePair<char, ItemSet> kvp in transitions)
            {
                ItemSet newItemSet = kvp.Value;
                // 如果转移项集已存在,则添加转移边
                ItemSet existingItemSet = _states.Find(p => p.Equals(newItemSet));
                if (existingItemSet != null)
                {
                    currentState.AddTransition(newItemSet, kvp.Key);
                }
                // 否则添加新的状态
                else
                {
                    currentState.AddTransition(newItemSet, kvp.Key);
                    _states.Add(newItemSet);
                }
            }
        }
        return _states;
    }
    // 计算闭包
    private void Closure(ItemSet itemSet)
    {
        bool changed = true;
        while (changed)
        {
            changed = false;
            List<Item> closureItems = itemSet.Items.FindAll(p => !p.IsReduceItem && char.IsUpper(p.NextSymbol));
            foreach (Item closureItem in closureItems)
            {
                foreach (Production production in _productions.FindAll(p => p.Left == closureItem.NextSymbol))
                {
                    Item newItem = new Item(production, 0);
                    if (!itemSet.Items.Contains(newItem))
                    {
                        itemSet.AddItem(newItem);
                        changed = true;
                    }
                }
            }
        }
    }
}

public class Production
{
    // 产生式左侧
    public char Left { get; private set; }
    // 产生式右侧
    public string Right { get; private set; }
    // 构造函数
    public Production(char left, string right)
    {
        Left = left;
        Right = right;
    }
}

public class Item
{
    // 产生式
    public Production Production { get; private set; }
    // 点的位置
    public int DotPosition { get; private set; }
    // 是否为规约项
    public bool IsReduceItem { get { return DotPosition == Production.Right.Length; } }
    // 下一个符号
    public char NextSymbol { get { return IsReduceItem ? '#' : Production.Right[DotPosition]; } }
    // 规约符号
    public char FollowSymbol { get { return Production.Left; } }
    // 构造函数
    public Item(Production production, int dotPosition)
    {
        Production = production;
        DotPosition = dotPosition;
    }
}

public class ItemSet
{
    // 项集中的项
    public List<Item> Items { get; private set; }
    // 状态之间的转移
    public Dictionary<ItemSet, char> Transitions { get; private set; }
    // 动作表
    public Dictionary<char, LR.Table> Actions { get; private set; }
    // 构造函数
    public ItemSet()
    {
        Items = new List<Item>();
        Transitions = new Dictionary<ItemSet, char>();
        Actions = new Dictionary<char, LR.Table>();
    }
    // 添加项
    public void AddItem(Item item)
    {
        if (!Items.Contains(item))
        {
            Items.Add(item);
        }
    }
    // 添加转移边
    public void AddTransition(ItemSet target, char symbol)
    {
        if (!Transitions.ContainsKey(target))
        {
            Transitions.Add(target, symbol);
        }
    }
    // 判断两个项集是否相等
    public override bool Equals(object obj)
    {
        if (obj == null || !(obj is ItemSet))
        {
            return false;
        }
        ItemSet other = (ItemSet)obj;
        if (Items.Count != other.Items.Count)
        {
            return false;
        }
        foreach (Item item in Items)
        {
            if (!other.Items.Contains(item))
            {
                return false;
            }
        }
        return true;
    }
    // 重写GetHashCode方法
    public override int GetHashCode()
    {
        int hashCode = 0;
        foreach (Item item in Items)
        {
            hashCode ^= item.GetHashCode();
        }
        return hashCode;
    }
}

说明:

  1. LR0Judge 函数用于判断输入的文法是否为 LR(0) 文法。它通过构造产生式和项集族,并检查是否存在移进规约冲突和规约规约冲突来进行判断。
  2. HasShiftReduceConflictHasReduceReduceConflict 函数分别用于检测移进规约冲突和规约规约冲突。
  3. button5_Click 函数用于构造 LR 分析表,并在表中显示冲突信息。
  4. ItemSetCollection 类用于表示项集族,包括项集、FIRST 集、FOLLOW 集和 LR(0) 自动机。
  5. LR0Automaton 类用于构造 LR(0) 自动机。
  6. Production 类用于表示产生式。
  7. Item 类用于表示项。
  8. ItemSet 类用于表示项集。

使用方法:

  1. 将代码复制到 C# 项目中。
  2. 在项目中添加一个 richTextBox1 用于输入文法,一个 button2 用于判断文法是否为 LR(0) 文法,一个 button5 用于构造 LR 分析表,以及其他必要控件。
  3. button2_Clickbutton5_Click 事件绑定到相应的代码。
  4. 运行程序,输入文法,并点击按钮进行判断和构造分析表。

示例:

E->E+T
E->T
T->T*F
T->F
F->(E)
F->id

上述文法为一个 LR(0) 文法,程序会输出正确的 LR(0) 分析表。

注意:

本代码仅实现了基本的 LR(0) 文法分析功能,并未包含其他功能,例如语义分析、代码生成等。


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

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