SLR语法分析表的构造方法:首先把G拓广为G’对G’构造LR0项目集规范族C和活前缀识别自动机的状态转换函数GO。函数ACTION和GOTO可按如下方法构造:若项目A→αbβ属于IkGOIka= Ija为终结符置ACTIONka为把状态j和符号a移进栈简记为sj;若项目A→α属于Ik那么对任何非终结符aa∈FOLLOWA置ACTIONka为用产生式A→α进行归约简记为rj;其中假定A→α为文法G’
首先,需要将文法G拓广为G’,然后构造LR(0)项目集规范族C和活前缀识别自动机的状态转换函数GO。然后根据上述原理,构造ACTION和GOTO函数,最后填充分析表中的空白格。
在SLRAnaly函数中,需要遍历所有的项目集,对于每个项目集,根据ACTION和GOTO函数填充分析表中的对应位置。具体实现方法如下:
- 初始化分析表SLRAna为一个二维数组,大小为[项目集数量+1][终结符数量+非终结符数量+1],其中第一行和第一列留空。
- 对于每个项目集i,遍历其中的每个项目j,根据ACTION和GOTO函数计算对应的动作和转移,填充到SLRAna[i+1][a]中,其中a为终结符或非终结符。
- 如果某个位置无法填充,则将其标记为出错标志。
- 最后,将SLRAna作为SLR类的一个属性返回。
具体实现代码如下:
public Table[][] SLRAnaly() { SLRAna = new Table[proitemset.Count + 1][]; for (int i = 0; i <= proitemset.Count; i++) { SLRAna[i] = new Table[Nchar.Count + Echar.Count + 1]; for (int j = 0; j <= Nchar.Count + Echar.Count; j++) { SLRAna[i][j] = new Table(); } }
for (int i = 0; i < proitemset.Count; i++)
{
List<int> itemset = proitemset[i].Container;
for (int j = 0; j < itemset.Count; j++)
{
int item = itemset[j];
SLRNode obj = SLRobjNum[item];
if (obj.Right == "#")
{
SLRAna[i + 1][Echar.Count + 1] = new Table('a', 0);
}
else if (obj.Right[obj.Right.IndexOf(".") + 1] == '\0')
{
for (int k = 0; k < Gy_obj.Count; k++)
{
if (Gy_obj[k] == item)
{
SLRAna[i + 1][Echar.Count + 1] = new Table('r', k + 1);
break;
}
}
}
else
{
char symbol = obj.Right[obj.Right.IndexOf(".") + 1];
if (isFinalsymbol(symbol))
{
int next = Goto(itemset, symbol);
if (next != -1)
{
SLRAna[i + 1][Echar.IndexOf(symbol)] = new Table('s', next + 1);
}
else
{
SLRAna[i + 1][Echar.IndexOf(symbol)] = new Table();
}
}
else
{
int next = Goto(itemset, symbol);
if (next != -1)
{
SLRAna[i + 1][Nchar.IndexOf(symbol)] = new Table('g', next + 1);
}
else
{
SLRAna[i + 1][Nchar.IndexOf(symbol)] = new Table();
}
}
}
}
}
for (int i = 1; i <= Nchar.Count + Echar.Count; i++)
{
if (isFinalsymbol(Echar[i - 1]))
{
SLRAna[0][i] = new Table('s', 0);
}
else
{
SLRAna[0][i] = new Table();
}
}
SLRAna[0][Echar.Count + 1] = new Table('a', 0);
return SLRAna;
}
在SLRAnaly函数中,调用了一个名为Goto的函数,用于计算项目集在某个符号上的转移。具体实现方法如下:
public int Goto(List
在Goto函数中,首先遍历项目集中的每个项目,找到其中“.”后面紧跟着symbol的项目,将其序号加1并加入nextset中。然后对nextset求闭包,并返回其在项目集中的序号。如果不存在相同的项目集,则返回-1。
最后,在主函数中调用SLRAnaly函数,将分析表输出到文件中:
SLR slr = new SLR(); slr.Buildprod(str); Table[][] SLRAna = slr.SLRAnaly(); StreamWriter sw = new StreamWriter("SLRAnalyTable.txt"); for (int i = 0; i <= slr.proitemset.Count; i++) { for (int j = 0; j <= slr.Nchar.Count + slr.Echar.Count; j++) { if (SLRAna[i][j].error) { sw.Write("e\t"); } else if (SLRAna[i][j].type == 's') { sw.Write("s" + SLRAna[i][j].id.ToString() + "\t"); } else if (SLRAna[i][j].type == 'r') { sw.Write("r" + SLRAna[i][j].id.ToString() + "\t"); } else i
原文地址: https://www.cveoy.top/t/topic/hrgU 著作权归作者所有。请勿转载和采集!