C# 文法分析器:LL(1) 预测分析算法实现
{
"title": "class analyse_sentence",
"description": "使用 C# 实现的 LL(1) 预测分析算法,用于分析输入的文法字符串,并提供详细的分析过程。",
"keywords": "LL(1), 预测分析, 文法分析, C#, 代码, 算法",
"content": "class analyse_sentence
{
string text;
Select select;
Stack analyse;
Stack input;
public List
public analyse_sentence(string text, Select select)
{
this.text = text;
this.select = select;
this.analyse = new Stack();
input = new Stack();
result_analys = new List<string>();
result_input = new List<string>();
result_parse = new List<string>();
analyseresult();
}
void analyseresult()
{
var selects = select.getselects();
analyse.push('#');
analyse.push(selects.First().Key[0]);
input.push('#');
for (int i= text.Length-1; i>=0; i--)
input.push(text[i]);
result_analys.Add(analyse.getString());
result_input.Add(input.getString());
while (true)
{
//如果分析栈栈顶元素为终结符
if (IsTerminal(analyse.peek()))
{
//当两个栈都只剩下#时,说明匹配成功
if(analyse.peek() == input.peek() && analyse.length()==1 && input.length()==1)
{
result_parse.Add("成功");
return;
}
if(analyse.peek() == input.peek())
{
result_parse.Add("'" + analyse.peek()+"'"匹配");
analyse.pop();
input.pop();
result_analys.Add(analyse.getString());
result_input.Add(input.getString());
continue;
}
else
{
result_parse.Add("失败");
return;
}
}
int flag = 0;
string nofinal = analyse.peek().ToString();
string final = input.peek().ToString();
foreach(var parse in selects[nofinal])
{
if(parse.Value.Contains(final))
{
result_parse.Add(nofinal+"->" + parse.Key);
analyse.pop();
//当推出的产生式不为空时,对分析栈进行添加
if (!parse.Key.Equals("#"))
{
addanalyse(parse.Key);
}
result_analys.Add(analyse.getString());
result_input.Add(input.getString());
flag = 1; break;
}
}
//说明该非终结符中没有可推导出该终结符的产生式
if (flag == 0)
{
result_parse.Add("失败");
return;
}
}
}
void addanalyse(String t)
{
for(int i=t.Length-1; i>=0; i--)
{
analyse.push(t[i]);
}
}
static bool IsTerminal(char symbol)
{
return !char.IsUpper(symbol);
}
}
根据上述代码,在下列代码的基础上增加button7按钮功能对textBox1中输入的字符进行分析,button8按钮提供在listView4中单步显示分析信息,button9按钮提供在listView4中一键显示分析信息。
private void GetFirst(string symbol, Dictionary<string, List
// 判断一个字符是否为终结符
private bool IsTerminal(char c)
{
if (char.IsUpper(c))
return false;
return true;
}
// 判断一个非终结符是否能推出空串
private bool IsReachEmpty(string symbol, Dictionary<string, List<string>> 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;
}
// 计算 FOLLOW 集
private void GetFollow(string symbol, Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1, Dictionary<string, List<string>> follows1)
{
// 如果该非终结符的 FOLLOW 集已经被计算出,则直接返回
if (follows1.ContainsKey(symbol))
{
return;
}
follows1.Add(symbol, new List<string>());
// 如果是起始符号,则将 # 加入 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);
}
}
}
}
}
}
}
// 判断一个文法是否是 LL(1) 文法
private bool JudgeLL1(Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1, Dictionary<string, List<string>> follows1)
{
foreach (var item in production1)
{
Dictionary<string, List<string>> map = new Dictionary<string, List<string>>();
foreach (var prod in item.Value)
{
List<string> list = new List<string>();
foreach (var c in prod)
{
if (IsTerminal(c))
{
list.Add(c.ToString());
break;
}
else
{
GetFirst(c.ToString(), production1, firsts1);
foreach (var f in firsts1[c.ToString()])
{
if (!f.Equals("#") && !list.Contains(f))
list.Add(f);
}
if (!IsReachEmpty(c.ToString(), production1))
break;
}
}
if (list.Contains("#"))
{
GetFollow(item.Key, production1, firsts1, follows1);
foreach (var f in follows1[item.Key])
{
if (!list.Contains(f))
list.Add(f);
}
}
string key = string.Join("", list.ToArray());
if (map.ContainsKey(key))
return false;
map.Add(key, list);
}
}
return true;
}
private void GetSelect(Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1, Dictionary<string, List<string>> follows1)
{
//对非终结符的每个产生式获取select值
//如果该产生式第一个字符为终结符
//如果该产生式第一个字符为非终结符
// 对每个非终结符进行操作
// 对每个非终结符进行遍历
foreach (var nonterm in nonterminals)
{
// 获取该非终结符的所有产生式
var productions = production1[nonterm];
// 遍历该非终结符的所有产生式
foreach (var prod in productions)
{
// 初始化该产生式的 select 值
List<string> select = new List<string>();
// 如果该产生式的第一个字符为终结符,直接将该字符加入 select
if (IsTerminal(prod[0]))
{
if (prod[0].Equals("#"))
{
// 如果该产生式的第一个字符为 #,将 follow(nonterm) 加入 select
select.AddRange(follows1[nonterm]);
}
else
{
// 如果该产生式的第一个字符为其他终结符,将该终结符加入 select
select.Add(prod[0].ToString());
}
}
else
{
// 如果该产生式的第一个字符为非终结符,将该非终结符的 first 集加入 select
select.AddRange(firsts1[prod[0].ToString()]);
// 如果该非终结符的 first 集中包含空串,将 follow(nonterm) 加入 select
if (select.Contains("#"))
{
select.Remove("#");
select.AddRange(follows1[nonterm]);
}
}
// 将该产生式的 select 值加入预测分析表中
foreach (var term in select)
{
table[nonterm][term] = prod;
}
}
}
}
private void Analyse()
{
while (true)
{
// 如果分析栈栈顶元素为终结符
if (IsTerminal(analyse.Peek()))
{
// 当两个栈都只剩下#时,说明匹配成功
if (analyse.Peek() == input.Peek() && analyse.Count() == 1 && input.Count() == 1)
{
result_parse.Add("成功");
return;
}
if (analyse.Peek() == input.Peek())
{
result_parse.Add("'" + analyse.Peek() + "'"匹配");
analyse.Pop();
input.Pop();
result_analys.Add(analyse.ToString());
result_input.Add(input.ToString());
continue;
}
else
{
result_parse.Add("失败");
return;
}
}
string nofinal = analyse.Peek().ToString();
string final = input.Peek().ToString();
// 如果分析表中没有该产生式,则匹配失败
if (!table.ContainsKey(nofinal) || !table[nofinal].ContainsKey(final))
{
result_parse.Add("失败");
return;
}
// 获取推导产生式
string production = table[nofinal][final];
result_parse.Add(nofinal + "->" + production);
// 将推导产生式中的符号压入分析栈
analyse.Pop();
if (!production.Equals("#"))
{
for (int i = production.Length - 1; i >= 0; i--)
analyse.Push(production[i]);
}
// 更新分析栈和输入栈的变化
result_analys.Add(analyse.ToString());
result_input.Add(input.ToString());
}
}
private void button7_Click(object sender, EventArgs e) { string text = textBox1.Text; analyze();
// 在界面第二行之后展示步骤、分析串、剩余输入串、推导所用产生式或匹配
listView4.Columns.Clear();
listView4.Items.Clear();
listView4.View = View.Details;
listView4.Columns.Add("步骤", 60, HorizontalAlignment.Center);
listView4.Columns.Add("分析串", 60, HorizontalAlignment.Center);
listView4.Columns.Add("剩余输入串", 80, HorizontalAlignment.Center);
listView4.Columns.Add("推导所用产生式或匹配", 150, HorizontalAlignment.Center);
button8.Enabled = true;
button9.Enabled = true;
}
内容:private void analyze() { // 获取文法 string grammar = textBox2.Text;
// 将文法转换为产生式
Dictionary<string, List<string>> production = new Dictionary<string, List<string>>();
string[] lines = grammar.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string line in lines)
{
string[] tokens = line.Split(new char[] { ' ', '\t', '-', '>' }, StringSplitOptions.RemoveEmptyEntries);
string nonterm = tokens[0];
List<string> prods;
if (!production.ContainsKey(nonterm))
{
prods = new List<string>();
production.Add(nonterm, prods);
}
else
{
prods = production[nonterm];
}
for (int i = 1; i < tokens.Length; i++)
{
prods.Add(tokens[i]);
}
}
// 获取非终结符和终结符
HashSet<string> nonterminals = new HashSet<string>();
HashSet<string> terminals = new HashSet<string>();
foreach (var item in production)
{
nonterminals.Add(item.Key);
foreach (var prod in item.Value)
{
foreach (var c in prod)
{
if (char.IsUpper(c))
{
nonterminals.Add(c.ToString());
}
else
{
terminals.Add(c.ToString());
}
}
}
}
terminals.Remove("#");
// 计算 FIRST 集
Dictionary<string, List<string>> firsts = new Dictionary<string, List<string>>();
foreach (string nonterm in nonterminals)
{
GetFirst(nonterm, production, firsts);
}
// 计算 FOLLOW 集
Dictionary<string, List<string>> follows = new Dictionary<string, List<string>>();
foreach (string nonterm in nonterminals)
{
GetFollow(nonterm, production, firsts, follows);
}
// 判断文法是否为 LL(1) 文法
if (!JudgeLL1(production, firsts, follows))
{
MessageBox.Show("该文法不是 LL(1) 文法!");
return;
}
// 构造预测分析表
Dictionary<string, Dictionary<string, string>> table = new Dictionary<string, Dictionary<string, string>>();
foreach (var nonterm in nonterminals)
{
table.Add(nonterm, new Dictionary<string, string>());
foreach (var term in terminals)
{
table[nonterm].Add(term, "");
}
if (follow
原文地址: https://www.cveoy.top/t/topic/oBNU 著作权归作者所有。请勿转载和采集!