SLR分析表构建:C#代码实现及错误分析
public class SLRNode
{
public string Left;
public string Right;
public SLRNode(string Left, string Right)
{
this.Left = Left;
this.Right = Right;
}
}
//项目集类
public class SLRitemsets
{
public List
//DFA结点
public struct DFA
{
public int from;
public char symbol;
public int to;
public DFA(int from, char symbol, int to)
{
this.from = from;
this.symbol = symbol;
this.to = to;
}
}
public class Table
{
public bool error;//是否为ERROR
public char type;//结点类型
public int id;//数值
public Table()
{
this.error = true;
}
public Table(char type, int id)
{
this.type = type;
this.id = id;
this.error = false;
}
}
public DFA[] dfa = new DFA[100];
public int Pindex = 0; //dfa数组指针
public Table[][] SLRAna;//分析表
public Analyze Jz;
public bool Success = false;
public List
public List
public string RStr = ''; public string RStr_obitemset = '';//输出返回 public string RStr_DFA = ''; public string RStr_ANA = ''; public Table[][] GET_ANA() { SLRAnaly(); RStr_ANA += '\r\nSLR0分析表:\r\n '; int i; for (i = 0; i < Echar.Count; i++) { RStr_ANA += Echar[i].ToString() + ' '; } for (i = 0; i < Nchar.Count; i++) { RStr_ANA += Nchar[i].ToString() + ' '; } RStr_ANA += '\r\n'; for (i = 0; i < proitemset.Count; i++) { RStr_ANA += i.ToString() + ' '; for (int j = 0; j < Echar.Count + Nchar.Count; j++) {
if (SLRAna[i][j].error)
{
RStr_ANA += ' ' + ' ';
}
else if (i == 1 && j == Echar.Count - 1)
{
RStr_ANA += 'AC' + ' ';
}
else if (SLRAna[i][j].type != 'N')
{
RStr_ANA += SLRAna[i][j].type.ToString() + SLRAna[i][j].id.ToString() + ' ';
}
else
RStr_ANA += SLRAna[i][j].id.ToString() + ' ';
}
RStr_ANA += '\r\n';
}
return SLRAna;
} public void SLRAnaly() { Table tnode = new Table();
SLRAna = new Table[proitemset.Count][];
for (int i = 0; i < proitemset.Count; i++)
SLRAna[i] = new Table[Echar.Count + Nchar.Count];
for (int i = 0; i < proitemset.Count; i++)//初始化 赋予ERROR属性
for (int j = 0; j < Echar.Count + Nchar.Count; j++)//为终结符加r状态
SLRAna[i][j] = tnode;
tnode = new Table('A', 0);
SLRAna[1][FindID(Echar, '#')] = tnode;//项目集1必定是接受项目 构建[1][#]:acc的情况 先直接赋值好 dfa里没有
for (int i = 0; i < Gy_itemset.Count; i++)
{
SLRNode item = SLRobjNum[proitemset[Gy_itemset[i]].Container[0]];
char left = item.Left[0];
List<char> follow = GetFollow(left, Find_pro(item));
foreach (char c in follow)
{
int CID = FindID(Echar, c);
SLRAna[Gy_itemset[i]][CID] = new Table('r', Find_pro(item));
if (c == '#')
{
foreach (char e in Echar)
{
int EID = FindID(Echar, e);
SLRAna[Gy_itemset[i]][EID] = new Table('r', Find_pro(item));
}
}
}
}
for (int i = 0; i < Pindex; i++)
{
if (isFinalsymbol(dfa[i].symbol))//symbol为非终结符 添加状态N
{
int CID = FindID(Nchar, dfa[i].symbol);
SLRAna[dfa[i].from][CID + Echar.Count] = new Table('N', dfa[i].to);
}
else //不是归约项目 添加状态S
{
int CID = FindID(Echar, dfa[i].symbol);
SLRAna[dfa[i].from][CID] = new Table('S', dfa[i].to);
}
}
}
public List
public List
// ... 其他代码
// 问题分析:
// 根据错误信息,可以看出在构建SLR分析表时出现了错误。具体来说,就是在生成状态5时,对于符号“)”和“#”都被标记成了“r6”,而实际上“)”应该是“r4”,“#”应该是“r1”。同样的情况也出现在其他状态中。
// 原因分析:
// 经过查看代码,发现在SLRAnaly()函数中,对于归约项目和非终结符的处理有误。具体来说,对于归约项目,只是将其follow集合中的符号标记成了“r”,但没有区分是哪一个归约项目。对于非终结符,也只是将其对应的状态标记成了“N”,但没有区分是哪一个非终结符。
// 修改方案:
// 1. 对于归约项目,需要在SLRAnaly()函数中对其follow集合中的每个符号都标记上对应的归约项目编号。具体来说,可以在GetFollow()函数中添加一个参数,表示当前处理的是哪一个归约项目,然后在标记follow集合时将其记录下来。修改后的代码如下:
// csharp // public List<char> GetFollow(char c, int proNum) // { // List<char> follow = new List<char>(); // if (c == 'E') // follow.Add('#'); // foreach (SLRNode node in SLRproNum) // { // int index = node.Right.IndexOf(c); // if (index != -1 && index < node.Right.Length - 1) // { // char next = node.Right[index + 1]; // if (isFinalsymbol(next)) // follow.Add(next); // else // { // List<char> first = GetFirst(next, c); // if (first.Contains('#')) // { // first.Remove('#'); // follow.AddRange(first); // follow.AddRange(GetFollow(node.Left[0], Find_pro(node))); // } // else // { // follow.AddRange(first); // } // } // } // else if (index != -1 && index == node.Right.Length - 1) // { // follow.AddRange(GetFollow(node.Left[0], Find_pro(node))); // } // } // follow = follow.Distinct().ToList(); // foreach (char c in follow) // { // int CID = FindID(Echar, c); // SLRAna[Gy_itemset[proNum]][CID] = new Table('r', proNum); // } // return follow; // } //
// 在SLRAnaly()函数中调用GetFollow()时需要传入对应的归约项目编号,即:
// csharp // foreach (int num in proitemset[Gy_itemset[i]].Container) // { // SLRNode item = SLRobjNum[num]; // char left = item.Left[0]; // List<char> follow = GetFollow(left, Find_pro(item)); // //... // } //
// 2. 对于非终结符,需要在SLRAnaly()函数中对其对应的状态标记上对应的非终结符编号。具体来说,可以在GetFirst()函数中添加一个参数,表示当前处理的是哪一个非终结符,然后在标记first集合时将其记录下来。修改后的代码如下:
// csharp // public List<char> GetFirst(char c, char nonTerminal) // { // List<char> first = new List<char>(); // if (isFinalsymbol(c)) // first.Add(c); // else // { // foreach (SLRNode node in SLRproNum) // { // if (node.Left[0] == c) // { // if (node.Right[0] == c) // continue; // else if (isFinalsymbol(node.Right[0])) // first.Add(node.Right[0]); // else // { // List<char> subFirst = GetFirst(node.Right[0], nonTerminal); // if (subFirst.Contains('#')) // { // subFirst.Remove('#'); // first.AddRange(subFirst); // first.AddRange(GetFirst(node.Right[1], nonTerminal)); // } // else // { // first.AddRange(subFirst); // } // } // } // } // } // first = first.Distinct().ToList(); // foreach (char c in first) // { // int CID = FindID(Echar, c); // SLRAna[dfa[i].from][CID + Echar.Count] = new Table('N', FindID(Nchar, nonTerminal)); // } // return first; // } //
// 在SLRAnaly()函数中调用GetFirst()时需要传入对应的非终结符,即:
// csharp // foreach (char c in Nchar) // { // GetFirst(c, c); // } //
// 3. 最后,在SLRAnaly()函数中需要将所有未被标记的状态都标记成“error”,以免出现未初始化的情况。具体来说,可以在循环结束后添加如下代码:
// csharp // for (int i = 0; i < proitemset.Count; i++) // { // for (int j = 0; j < Echar.Count + Nchar.Count; j++) // { // if (SLRAna[i][j].error) // SLRAna[i][j] = new Table(); // } // } //
// 修改后的完整代码如下:
// csharp // public class SLRNode // { // public string Left; // public string Right; // public SLRNode(string Left, string Right) // { // this.Left = Left; // this.Right = Right; // } // } // //项目集类 // public class SLRitemsets // { // public List<int> Container // = new List<int>(100); // //记录项目在项目集合中的序号 // } // // //DFA结点 // public struct DFA // { // public int from; // public char symbol; // public int to; // public DFA(int from, char symbol, int to) // { // this.from = from; // this.symbol = symbol; // this.to = to; // } // } // public class Table // { // public bool error;//是否为ERROR // public char type;//结点类型 // public int id;//数值 // public Table() // { // this.error = true; // } // public Table(char type, int id) // { // this.type = type; // this.id = id; // this.error = false; // } // } // public DFA[] dfa = new DFA[100]; // public int Pindex = 0; //dfa数组指针 // public Table[][] SLRAna;//分析表 // public Analyze Jz; // public bool Success = false; // public List<SLRNode> SLRproNum = new List<SLRNode>(50);//产生式 列表 // public List<SLRNode> SLRobjNum = new List<SLRNode>(50);//项目 列表 // public List<SLRitemsets> proitemset = new List<SLRitemsets>(100);//项目集合 // public List<int> Gy_obj = new List<int>(50);//归约项目序号集合 // public List<int> Gy_itemset = new List<int>(50);//含有归约项目的集合的序号 的集合 // public List<char> Nchar = new List<char>(50);//非终结符集合 // public List<char> Echar = new List<char>(50);//终结符集合 // // public List<char>[] Follow; //每个非终结符的follow集合 // // public string RStr = ''; // public string RStr_obitemset = '';//输出返回 // public string RStr_DFA = ''; // public string RStr_ANA = ''; // public Table[][] GET_ANA() // { // SLRAnaly(); // RStr_ANA += '\r\nSLR0分析表:\r\n '; // int i; // for (i = 0; i < Echar.Count; i++) // { // RStr_ANA += Echar[i].ToString() + ' '; // } // for (i = 0; i < Nchar.Count; i++) // { // RStr_ANA += Nchar[i].ToString() + ' '; // } // RStr_ANA += '\r\n'; // for (i = 0; i < proitemset.Count; i++) // { // RStr_ANA += i.ToString() + ' '; // for (int j = 0; j < Echar.Count + Nchar.Count; j++) // { // // if (SLRAna[i][j].error) // { // RStr_ANA += ' ' + ' '; // } // else if (i == 1 && j == Echar.Count - 1) // { // RStr_ANA += 'AC' + ' '; // } // else if (SLRAna[i][j].type != 'N') // { // RStr_ANA += SLRAna[i][j].type.ToString() + SLRAna[i][j].id.ToString() + ' '; // } // else // RStr_ANA += SLRAna[i][j].id.ToString() + ' '; // } // RStr_ANA += '\r\n'; // } // // return SLRAna; // // } // public void SLRAnaly() // { // Table tnode = new Table(); // // SLRAna = new Table[proitemset.Count][]; // for (int i = 0; i < proitemset.Count; i++) // SLRAna[i] = new Table[Echar.Count + Nchar.Count]; // // for (int i = 0; i < proitemset.Count; i++)//初始化 赋予ERROR属性 // for (int j = 0; j < Echar.Count + Nchar.Count; j++)//为终结符加r状态 // SLRAna[i][j] = tnode; // // tnode = new Table('A', 0); // SLRAna[1][FindID(Echar, '#')] = tnode;//项目集1必定是接受项目 构建[1][#]:acc的情况 先直接赋值好 dfa里没有 // // for (int i = 0; i < Gy_itemset.Count; i++) // { // foreach (int num in proitemset[Gy_itemset[i]].Container) // { // SLRNode item = SLRobjNum[num]; // char left = item.Left[0]; // List<char> follow = GetFollow(left, Find_pro(item)); // foreach (char c in follow) // { // int CID = FindID(Echar, c); // SLRAna[Gy_itemset[i]][CID] = new Table('r', Find_pro(item)); // if (c == '#') // { // foreach (char e in Echar) // { // int EID = FindID(Echar, e); // SLRAna[Gy_itemset[i]][EID] = new Table('r', Find_pro(item)); // } // } // } // } // } // // for (int i = 0; i < Pindex; i++) // { // if (isFinalsymbol(dfa[i].symbol))//symbol为非终结符 添加状态N // { // int CID = FindID(Nchar, dfa[i].symbol); // SLRAna[dfa[i].from][CID + Echar.Count] = new Table('N', dfa[i].to); // } // else //不是归约项目 添加状态S // { // int CID = FindID(Echar, dfa[i].symbol); // SLRAna[dfa[i].from][CID] = new Table('S', dfa[i].to); // } // } // for (int i = 0; i < proitemset.Count; i++) // { // for (int j = 0; j < Echar.Count + Nchar.Count; j++) // { // if (SLRAna[i][j].error) // SLRAna[i][j] = new Table(); // } // } // } // public List<char> GetFollow(char c, int proNum) // { // List<char> follow = new List<char>(); // if (c == 'E') // follow.Add('#'); // foreach (SLRNode node in SLRproNum) // { // int index = node.Right.IndexOf(c); // if (index != -1 && index < node.Right.Length - 1) // { // char next = node.Right[index + 1]; // if (isFinalsymbol(next)) // follow.Add(next); // else // { // List<char> first = GetFirst(next, c); // if (first.Contains('#')) // { // first.Remove('#'); // follow.AddRange(first); // follow.AddRange(GetFollow(node.Left[0], Find_pro(node))); // } // else // { // follow.AddRange(first); // } // } // } // else if (index != -1 && index == node.Right.Length - 1) // { // follow.AddRange(GetFollow(node.Left[0], Find_pro(node))); // } // } // follow = follow.Distinct().ToList(); // return follow; // } // // // public List<char> GetFirst(char c, char nonTerminal) // { // List<char> first = new List<char>(); // if (isFinalsymbol(c)) // first.Add(c); // else // { // foreach (SLRNode node in SLRproNum) // { // if (node.Left[0] == c) // { // if (node.Right[0] == c) // continue; // else if (isFinalsymbol(node.Right[0])) // first.Add(node.Right[0]); // else // { // List<char> subFirst = GetFirst(node.Right[0], nonTerminal); // if (subFirst.Contains('#')) // { // subFirst.Remove('#'); // first.AddRange(subFirst); // first.AddRange(GetFirst(node.Right[1], nonTerminal)); // } // else // { // first.AddRange(subFirst); // } // } // } // } // } // first = first.Distinct().ToList(); // return first; // } // // // // ... 其他代码 //
原文地址: https://www.cveoy.top/t/topic/f0CS 著作权归作者所有。请勿转载和采集!