LL(1) 文法语法分析:预测分析表构建及分析函数实现
由于 LL(1) 文法的语法分析需要进行预测分析表的构建,因此需要在代码中添加以下函数来构建预测分析表:
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;
}
}
}
}
该函数根据非终结符的 FIRST 集和 FOLLOW 集,计算每个产生式的 SELECT 集,并将结果填充到预测分析表中。
此外,还需要修改 analyze 函数,使其能够根据预测分析表进行语法分析。修改后的 analyze 函数代码如下:
private void analyze()
{
while (true)
{
// 如果分析栈为空或者输入栈为空,则分析结束
if (analyseStack.Count == 0 || inputStack.Count == 0)
{
break;
}
// 获取分析栈的栈顶元素和输入栈的栈顶元素
char topAnalyse = analyseStack.Peek();
char topInput = inputStack.Peek();
// 如果分析栈的栈顶元素和输入栈的栈顶元素相同,则进行匹配
if (topAnalyse == topInput)
{
// 将匹配的元素从分析栈和输入栈中弹出
analyseStack.Pop();
inputStack.Pop();
// 在分析结果列表中添加匹配信息
resultAnalyse.Add(analyseStack.ToString());
resultInput.Add(inputStack.ToString());
resultParse.Add('"' + topAnalyse + '"' + " 匹配");
}
else
{
// 如果分析栈的栈顶元素为终结符,则出错
if (IsTerminal(topAnalyse))
{
resultParse.Add("出错");
break;
}
else
{
if (!table.ContainsKey(topAnalyse.ToString()) || !table[topAnalyse.ToString()].ContainsKey(topInput.ToString()))
{
resultParse.Add("出错");
break;
}
else
{
// 获取分析表中的产生式
string production = table[topAnalyse.ToString()][topInput.ToString()];
// 如果分析表中没有产生式,则出错
if (production == null)
{
resultParse.Add("出错");
break;
}
else
{
// 将产生式从分析栈中弹出
analyseStack.Pop();
// 如果产生式不是空串,则将产生式中的符号逆序压入分析栈中
if (production != "#")
{
for (int i = production.Length - 1; i >= 0; i--)
{
analyseStack.Push(production[i]);
}
}
// 在分析结果列表中添加产生式信息
resultAnalyse.Add(analyseStack.ToString());
resultInput.Add(inputStack.ToString());
resultParse.Add(topAnalyse + " -> " + production);
}
}
}
}
}
// 如果分析栈和输入栈都为空,则分析成功
if (analyseStack.Count == 0 && inputStack.Count == 0)
{
resultParse.Add("成功");
}
}
该函数根据预测分析表,对输入字符串进行分析,并将分析结果存储在 resultAnalyse,resultInput 和 resultParse 列表中。
通过以上步骤,便可以利用 C# 代码实现 LL(1) 文法的语法分析器。
原文地址: http://www.cveoy.top/t/topic/fYDJ 著作权归作者所有。请勿转载和采集!