C#实现LL(1)文法分析器:SELECT集计算函数
class Select
{
LL1Item LL1Item;
First first;
Follow follow;
Dictionary<string, Dictionary<string, List<string>>> selects;
public Select(LL1Item LL1Item, First first, Follow follow)
{
this.LL1Item = LL1Item;
this.first = first;
this.follow = follow;
selects = new Dictionary<string, Dictionary<string, List<string>>>();
GetSelect();
}
public void GetSelect()
{
var production = LL1Item.getproduction();
foreach (var nofinal in LL1Item.nofinal)
{
selects.Add(nofinal, new Dictionary<string, List<string>>());
//对非终结符的每个产生式获取select值
foreach (var f in production[nofinal])
{
selects[nofinal].Add(f, new List<string>());
for (int i = 0; i < f.Length; i++)
{
//如果该产生式第一个字符为终结符
if (IsTerminal(f[i]))
{
if (f[i].Equals('#'))
{
foreach (var fol in follow.getfollows()[nofinal])
selects[nofinal][f].Add(fol);
}
else if (!selects[nofinal][f].Contains(f[i].ToString()))
selects[nofinal][f].Add(f[i].ToString());
break;
}
//如果该产生式第一个字符为非终结符
else
{
int flag = 0;
foreach (var fir in first.getfirsts()[f[i].ToString()])
{
if (fir.Equals('#'))
flag = 1;
else
{
if (!selects[nofinal][f].Contains(fir))
selects[nofinal][f].Add(fir);
}
}
if (flag == 0) break;
}
if (i == f.Length - 1)
{
foreach (var fol in follow.getfollows()[nofinal])
if (!selects[nofinal][f].Contains(fol))
selects[nofinal][f].Add(fol);
}
}
}
}
}
static bool IsTerminal(char symbol)
{
return !char.IsUpper(symbol);
}
public Dictionary<string, Dictionary<string, List<string>>> getselects()
{
return selects;
}
}
// 不使用 LL1Item 的 GetSelect 函数实现
private Dictionary<string, List<string>> GetSelect(Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1, Dictionary<string, List<string>> follows1)
{
// 初始化 SELECT 集
Dictionary<string, List<string>> selects1 = new Dictionary<string, List<string>>();
foreach (var item in production1)
selects1.Add(item.Key, new List<string>());
// 遍历每个产生式,计算对应的 SELECT 集
foreach (var nonterm in production1.Keys)
{
foreach (var prod in production1[nonterm])
{
List<string> select = new List<string>();
bool flag = true;
// 对于产生式中的每个符号,计算其 FIRST 集
foreach (var s in prod)
{
if (IsTerminal(s))
{
select.Add(s.ToString());
flag = false;
break;
}
else
{
GetFirst(s.ToString(), production1, firsts1);
foreach (var f in firsts1[s.ToString()])
{
if (!f.Equals('#') && !select.Contains(f))
select.Add(f);
}
if (!IsReachEmpty(s.ToString(), production1))
{
flag = false;
break;
}
}
}
// 如果产生式中所有符号的 FIRST 集都包含空串,则将 FOLLOW 集加入 SELECT 集中
if (flag)
{
GetFollow(nonterm, production1, firsts1, follows1);
foreach (var f in follows1[nonterm])
{
if (!select.Contains(f))
select.Add(f);
}
}
selects1[nonterm].Add(string.Join("", select.ToArray()));
}
}
return selects1;
}
// 补充 GetFirst 和 IsReachEmpty 函数实现,以及 GetFollow 函数
// ...
原文地址: http://www.cveoy.top/t/topic/ox8A 著作权归作者所有。请勿转载和采集!