{ 'title': 'LR(0) 文法分析器实现及判别', 'description': '该项目展示了如何使用 C# 语言实现 LR(0) 文法分析器,并提供判别 LR(0) 文法功能。代码包含 LR(0) 项目类、项集类、LR(0) 分析器类以及测试代码。', 'keywords': 'LR(0), 文法分析器, C#, 项目族, LR(0) 分析表, DFA, 判别 LR(0) 文法', 'content': 'private void button2_Click(object sender, EventArgs e)//判别LR0文法 { Dictionary<string, List> production = new Dictionary<string, List>(); production = getProduction(); Dictionary<string, List> firsts = new Dictionary<string, List>(); Dictionary<string, List> follows = new Dictionary<string, List>(); GetFirst(production.Keys.First(), production, firsts); GetFollow(production.Keys.First(), production, firsts, follows); if (JudgeLR0(production, firsts, follows)) MessageBox.Show('该文法为LR(0)文法!'); else MessageBox.Show('该文法不为LR(0)文法!'); }

private void button4_Click(object sender, EventArgs e)//生成项目族信息 { Dictionary<string, List> production = new Dictionary<string, List>(); production = getProduction(); Dictionary<string, List> productions = new Dictionary<string, List<List>>(); transformpro(production, productions); List terminals = new List(); List nonterminals = new List(); getTerminals(production, terminals); getNonTerminals(production, nonterminals); Dictionary<int, ItemSet> states = new Dictionary<int, ItemSet>(); Dictionary<int, HashSet> transitions = new Dictionary<int, HashSet>(); Dictionary<ItemSet, int> stateNumbers = new Dictionary<ItemSet, int>(); buildDFA(production, productions, terminals, nonterminals, states, transitions, stateNumbers);

// 显示项目族信息
dataGridView1.Columns.Clear();
dataGridView1.Columns.Add('状态', '状态');
dataGridView1.Columns.Add('项目族', '项目族');
int stateIndex = 0;
foreach (var state in states)
{
    dataGridView1.Rows.Add();
    dataGridView1.Rows[stateIndex].Cells[0].Value = state.Key;
    string items = string.Join('\n', state.Value.items.Select(item => item.ToString()));
    dataGridView1.Rows[stateIndex].Cells[1].Value = items;
    stateIndex++;
}

}

private void button5_Click(object sender, EventArgs e)//构造LR分析表 { Dictionary<string, List> production = new Dictionary<string, List>(); production = getProduction(); Dictionary<string, List> productions = new Dictionary<string, List<List>>(); transformpro(production, productions); List terminals = new List(); List nonterminals = new List(); getTerminals(production, terminals); getNonTerminals(production, nonterminals); Dictionary<int, ItemSet> states = new Dictionary<int, ItemSet>(); Dictionary<int, HashSet> transitions = new Dictionary<int, HashSet>(); Dictionary<ItemSet, int> stateNumbers = new Dictionary<ItemSet, int>(); buildDFA(production, productions, terminals, nonterminals, states, transitions, stateNumbers); Dictionary<int, List> table = buildTable(production, productions, terminals, nonterminals, states, transitions, stateNumbers);

// 显示分析表
dataGridView2.Columns.Clear();
dataGridView2.Columns.Add('状态', '状态');
foreach (var terminal in terminals)
{
    dataGridView2.Columns.Add(terminal, terminal);
}
foreach (var nonterminal in nonterminals)
{
    dataGridView2.Columns.Add(nonterminal, nonterminal);
}
int stateIndex = 0;
foreach (var state in table)
{
    dataGridView2.Rows.Add();
    dataGridView2.Rows[stateIndex].Cells[0].Value = state.Key;
    int columnIndex = 1;
    foreach (var action in state.Value)
    {
        dataGridView2.Rows[stateIndex].Cells[columnIndex].Value = action;
        columnIndex++;
    }
    stateIndex++;
}

}

private void button7_Click(object sender, EventArgs e)//单步显示输入的待分析句子 { string input = textBox1.Text; if (input.Length > 0) { string symbol = input[0].ToString(); input = input.Substring(1); textBox1.Text = input; textBox2.Text += symbol + ' '; } }

private void button8_Click(object sender, EventArgs e)//一键显示输入的待分析句子 { textBox2.Text = textBox1.Text; }

private Dictionary<string, List> getProduction() { Dictionary<string, List> production = new Dictionary<string, List>(); string[] productionStrings = textBox3.Text.Split('\n'); foreach (string productionString in productionStrings) { string[] parts = productionString.Split('->'); if (parts.Length == 2) { string lhs = parts[0].Trim(); string[] rhs = parts[1].Trim().Split(' '); if (!production.ContainsKey(lhs)) { production.Add(lhs, new List()); } production[lhs].Add(string.Join('', rhs)); } } return production; }

private void transformpro(Dictionary<string, List> production, Dictionary<string, List<List>> productions) { foreach (var item in production) { productions.Add(item.Key, new List<List>()); foreach (var item2 in item.Value) { List proitem = new List(); for (int i = 0; i < item2.Length; i++) proitem.Add(item2[i].ToString()); productions[item.Key].Add(proitem); } } }

private void getTerminals(Dictionary<string, List> production, List terminals) { foreach (var item in production) { foreach (var item2 in item.Value) { for (int i = 0; i < item2.Length; i++) { if (IsTerminal(item2[i])) { if (!terminals.Contains(item2[i].ToString())) { terminals.Add(item2[i].ToString()); } } } } } }

private void getNonTerminals(Dictionary<string, List> production, List nonterminals) { foreach (var item in production) { if (!nonterminals.Contains(item.Key)) nonterminals.Add(item.Key); } }

private void buildDFA(Dictionary<string, List> production, Dictionary<string, List<List>> productions, List terminals, List nonterminals, Dictionary<int, ItemSet> states, Dictionary<int, HashSet> transitions, Dictionary<ItemSet, int> stateNumbers) { //构造初始项目集 string s = productions.Keys.First() + '''; Item startItem = new Item(s, new List() { productions.Keys.First() }, 0); ItemSet startSet = new ItemSet(); startSet.items.Add(startItem); startSet = CLOSURE(startSet, production, productions, nonterminals);

// 初始化状态编号
stateNumbers = new Dictionary<ItemSet, int>();
states = new Dictionary<int, ItemSet>();

// 使用队列保存待处理的项集
Queue<ItemSet> queue = new Queue<ItemSet>();
stateNumbers[startSet] = 0;
states.Add(0, startSet);
queue.Enqueue(startSet);

while (queue.Count > 0)
{
    ItemSet I = queue.Dequeue();
    int stateNumber = stateNumbers[I];

    // 计算 I 中每个符号的移进操作后得到的新项集,并添加到 DFA 中
    foreach (string symbol in nonterminal.Union(terminals))
    {
        ItemSet J = GOTO(I, symbol, production, productions, nonterminals);
        int index;

        if (J.items.Count > 0)
        {
            index = iscommon(stateNumbers, states, J);
            if (index == -1)// 如果该项集不为空且还没有被加入到状态集合中
            {
                stateNumbers[J] = states.Count;
                states.Add(states.Count, J);
                queue.Enqueue(J);
            }
            if (!transitions.ContainsKey(stateNumber))// 如果该项集不为空
            {
                transitions[stateNumber] = new HashSet<string>();
            }
            transitions[stateNumber].Add(symbol + (index != -1 ? index : stateNumbers[J]));
        }
    }
}

}

private Dictionary<int, List> buildTable(Dictionary<string, List> production, Dictionary<string, List<List>> productions, List terminals, List nonterminals, Dictionary<int, ItemSet> states, Dictionary<int, HashSet> transitions, Dictionary<ItemSet, int> stateNumbers) { Dictionary<int, List> table = new Dictionary<int, List>(); for (int i = 0; i < states.Count; i++) { List actions = new List(); // 对每个状态经过终结符的情况进行判断 foreach (var symbol in terminals) { if (transitions.ContainsKey(i)) { foreach (var item in transitions[i]) { if (item[0].ToString().Equals(symbol)) { actions.Add('S' + item.Substring(1)); break; } } if (actions.Count == 0) actions.Add(''); } else { if (states[i].items.First().LHS.Equals(production.Keys.First() + ''')) { if (symbol.Equals('#')) actions.Add('acc'); else actions.Add(''); } else { int index = getproconut(states[i], production, productions); if (index != -1) actions.Add('r' + index); else actions.Add(''); } } } // 对每个状态经过非终结符的情况进行判断 foreach (var t in nonterminals) { if (transitions.ContainsKey(i)) { foreach (var item in transitions[i]) { if (item[0].ToString().Equals(t)) { actions.Add(item.Substring(1)); break; } } if (actions.Count == 0) actions.Add(''); } else actions.Add(''); } table.Add(i, actions); } return table; }

private ItemSet CLOSURE(ItemSet I, Dictionary<string, List> production, Dictionary<string, List<List>> productions, List nonterminals) { ItemSet J = new ItemSet(); foreach (var item in I.items) J.items.Add(item); Stack stack = new Stack();

foreach (Item i in I.items)
{
    stack.Push(i);
}

while (stack.Count > 0)
{
    Item i = stack.Pop();
    if (i.dotIndex < i.RHS.Count && nonterminals.Contains(i.RHS[i.dotIndex])) // dot 后的符号为非终结符
    {
        string X = i.RHS[i.dotIndex];
        foreach (List<string> prod in productions[X]) // 考虑 X -> Y1 Y2 ... Yk 的每个产生式
        {
            Item newI = new Item(X, prod, 0);
            if (!J.items.Contains(newI))
            {
                J.items.Add(newI);
                stack.Push(newI);
            }
        }
    }
}
return J;

}

private ItemSet GOTO(ItemSet I, string X, Dictionary<string, List> production, Dictionary<string, List<List>> productions, List nonterminals) { ItemSet J = new ItemSet(); foreach (Item i in I.items) { if (i.dotIndex < i.RHS.Count && i.RHS[i.dotIndex] == X) { Item newI = new Item(i.LHS, i.RHS, i.dotIndex + 1); J.items.Add(newI); } }

return CLOSURE(J, production, productions, nonterminals);

}

private int iscommon(Dictionary<ItemSet, int> stateNumbers, Dictionary<int, ItemSet> states, ItemSet itemSet) { int flag; int index = -1; foreach (var item in stateNumbers.Keys) { flag = 0; if (item.items.Count == itemSet.items.Count) { foreach (var j in itemSet.items) { foreach (var i in item.items) { if (i.Equals(j)) { flag++; break; } } } if (flag == item.items.Count) index = stateNumbers[item]; } } return index; }

private int getproconut(ItemSet itemSet, Dictionary<string, List> production, Dictionary<string, List<List>> productions) { int index = 1; if (itemSet.items.Count == 1) { foreach (var item in itemSet.items) if (item.dotIndex == item.RHS.Count) { foreach (var key in productions.Keys) { if (key.Equals(item.LHS)) { foreach (var item2 in productions[key]) { if (item.RHS.Equals(item2)) return index; else index++; } } index += productions[key].Count; } return index; } } return -1; }

private bool JudgeLR0(Dictionary<string, List> production, Dictionary<string, List> first, Dictionary<string, List> follow) { foreach (var item in production) { foreach (var prod in item.Value) { for (int i = 0; i < prod.Length; i++) { if (!IsTerminal(prod[i]) && i < prod.Length - 1) { string symbol = prod[i].ToString(); // 计算 FIRST(symbol) 集合 List firstSet = first[symbol]; // 计算 FOLLOW(item.Key) 集合 List followSet = follow[item.Key]; // 判断 FIRST(symbol) 和 FOLLOW(item.Key) 是否有交集 if (firstSet.Intersect(followSet).Any()) { return false; } } } } } return true; }

// Item 类 public class Item { public string LHS; // 产生式左部 public List 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)}';
}

}

// ItemSet 类 public class ItemSet { public HashSet items;

public ItemSet()
{
    items = new HashSet<Item>();
}

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

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

public override int GetHashCode()
{
    return items.GetHashCode();
}

}

// 判断一个字符是否为终结符 private bool IsTerminal(char c) { if (char.IsUpper(c)) return false; return true; }

// 判断一个非终结符是否能推出空串 private bool IsReachEmpty(string symbol, Dictionary<string, List> production1) { if (!production1.ContainsKey(symbol)) return false; foreach (var prod in production1[symbol]) { if (prod.Equals('#')) return true; bool flag = true; for (int i = 0; i < prod.Length; i++) { if (!IsReachEmpty(prod[i].ToString(), production1)) { flag = false; break; } } if (flag) return true; } return false; }

// 计算 FIRST 集 private void GetFirst(string symbol, Dictionary<string, List> production1, Dictionary<string, List> firsts1) { // 如果该非终结符的 FIRST 集已经被计算出,则直接返回 if (firsts1.ContainsKey(symbol)) { return; } firsts1.Add(symbol, new List()); // 遍历产生式,计算 FIRST 集 foreach (var prod in production1[symbol]) { // 如果产生式首字符为终结符,则直接将其加入 FIRST 集中 if (prod.Length > 0 && IsTerminal(prod[0])) { if (!firsts1[symbol].Contains(prod[0].ToString())) firsts1[symbol].Add(prod[0].ToString()); continue; } // 如果产生式首字符为非终结符,则计算该非终结符的 FIRST 集,并将结果加入首字符的 FIRST 集中 else if (prod.Length > 0 && !IsTerminal(prod[0])) { GetFirst(prod[0].ToString(), production1, firsts1); foreach (var f in firsts1[prod[0].ToString()]) { if (!firsts1[symbol].Contains(f) && !f.Equals('#')) firsts1[symbol].Add(f); } } //如果第一个非终结符能推出# if (IsReachEmpty(prod[0].ToString(), production1)) { // 递归计算第二个和后面的字符的 FIRST 集,并将结果加入该非终结符的 FIRST 集中 for (int j = 1; j < prod.Length; j++) { if (IsTerminal(prod[j])) { if (!firsts1[symbol].Contains(prod[j].ToString())) firsts1[symbol].Add(prod[j].ToString()); break; } GetFirst(prod[j].ToString(), production1, firsts1); foreach (var f in firsts1[prod[j].ToString()]) { if (!firsts1[symbol].Contains(f) && !f.Equals('#')) firsts1[symbol].Add(f); } // 如果该非终结符的 FIRST 集没有包含空串,则可以结束循环 if (!IsReachEmpty(prod[j].ToString(), production1)) { break; } // 如果是最后一个字符且所有非终结符的 FIRST 集都含有空串,则将空串加入该非终结符的 FIRST 集中 if (j == prod.Length - 1) { if (!firsts1[symbol].Contains('#')) firsts1[symbol].Add('#'); } } } } }

// 计算 FOLLOW 集 private void GetFollow(string symbol, Dictionary<string, List> production1, Dictionary<string, List> firsts1, Dictionary<string, List> follows1) { // 如果该非终结符的 FOLLOW 集已经被计算出,则直接返回 if (follows1.ContainsKey(symbol)) { return; } follows1.Add(symbol, new List()); // 如果是起始符号,则将 # 加入 FOLLOW 集中 if (symbol.Equals(production1.Keys.First())) { if (!follows1[symbol].Contains('#')) follows1[symbol].Add('#'); } // 遍历产生式,计算 FOLLOW 集 foreach (var item in production1) { foreach (var prod in item.Value) { int index = prod.IndexOf(symbol); if (index == -1) continue; // 如果该非终结符位于产生式末尾,则将产生式左部的 FOLLOW 集加入该非终结符的 FOLLOW 集中 if (index == prod.Length - 1) { GetFollow(item.Key, production1, firsts1, follows1); foreach (var f in follows1[item.Key]) { if (!follows1[symbol].Contains(f)) follows1[symbol].Add(f); } } else { // 如果该非终结符后面是终结符,则将该终结符加入该非终结符的 FOLLOW 集中 if (IsTerminal(prod[index + 1])) { if (!follows1[symbol].Contains(prod[index + 1].ToString())) follows1[symbol].Add(prod[index + 1].ToString()); } // 如果该非终结符后面是非终结符,则将该非终结符的 FIRST 集加入该非终结符的 FOLLOW 集中 else { GetFirst(prod[index + 1].ToString(), production1, firsts1); foreach (var f in firsts1[prod[index + 1].ToString()]) { if (!f.Equals('#') && !follows1[symbol].Contains(f)) follows1[symbol].Add(f); } // 如果该非终结符后面的所有符号都能推出空串,则将产生式左部的 FOLLOW 集加入该非终结符的 FOLLOW 集中 if (IsReachEmpty(prod[index + 1].ToString(), production1)) { GetFollow(item.Key, production1, firsts1, follows1); foreach (var f in follows1[item.Key]) { if (!follows1[symbol].Contains(f)) follows1[symbol].Add(f); } } } } } } }

LR(0) 文法分析器实现及判别

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

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