LR(0)分析表构造算法到SLR(1)分析表构造算法的改进
LR(0)分析表到SLR(1)分析表的改进
在编译原理中,LR(0)分析表和SLR(1)分析表都是用于语法分析的重要工具。SLR(1)分析表是对LR(0)分析表的一种改进,它通过考虑Follow集来解决LR(0)分析表中可能存在的移进/归约冲突。
代码实现 (C#)
以下是使用C#实现的SLR(1)分析表构造算法:
using System;
using System.Collections.Generic;
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);
}
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 = true;
public char type;
public int id;
public Table() { }
public Table(char type, int id)
{
this.type = type;
this.id = id;
this.error = false;
}
}
public class Analyze
{
public List<string> stack_state = new List<string>(100);
public List<string> stack_symbol = new List<string>(100);
public List<string> Input_str = new List<string>(100);
public List<string> Tran_pro = new List<string>(100);
}
public class SLRParser
{
public DFA[] dfa = new DFA[100];
public int Pindex = 0;
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);
Dictionary<char, HashSet<char>> first = new Dictionary<char, HashSet<char>>();
Dictionary<char, HashSet<char>> follow = new Dictionary<char, HashSet<char>>();
public string RStr = '';
public string RStr_obitemset = '';
public string RStr_DFA = '';
public string RStr_ANA = '';
public Table[][] GET_ANA()
{
SLRAnaly();
RStr_ANA += '\r\nSLR(1)分析表:\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()
{
// 构造SLR(1)项目集
SLRitemsets I0 = new SLRitemsets();
I0.Container.Add(0);
proitemset.Add(Closure(I0.Container));
int index = 0;
while (index < proitemset.Count)
{
for (int i = 0; i < Echar.Count + Nchar.Count; i++)
{
List<int> Goto = GOTO(proitemset[index], i);
if (Goto.Count == 0)
continue;
if (isnexist(proitemset, Goto))
proitemset.Add(Closure(Goto));
dfa[Pindex++] = new DFA(index, (i < Echar.Count) ? Echar[i] : Nchar[i - Echar.Count], GetIndex(proitemset, Goto));
}
index++;
}
// 构造SLR(1)分析表
SLRAna = new Table[proitemset.Count][];
for (int i = 0; i < proitemset.Count; i++)
{
SLRAna[i] = new Table[Echar.Count + Nchar.Count];
for (int j = 0; j < Echar.Count; j++)
{
SLRAna[i][j] = new Table();
List<int> Goto = GOTO(proitemset[i], Echar[j]);
if (Goto.Count == 0)
continue;
int k = GetIndex(proitemset, Goto);
if (isExist(Gy_obj, k))
SLRAna[i][j] = new Table('R', Gy_obj.IndexOf(k));
else if (isExist(proitemset[k], '·'))
SLRAna[i][j] = new Table('S', k);
else
SLRAna[i][j] = new Table('G', k);
}
for (int j = 0; j < Nchar.Count; j++)
{
SLRAna[i][Echar.Count + j] = new Table();
List<int> Goto = GOTO(proitemset[i], Nchar[j]);
if (Goto.Count == 0)
continue;
int k = GetIndex(proitemset, Goto);
if (isExist(Gy_obj, k))
SLRAna[i][Echar.Count + j] = new Table('R', Gy_obj.IndexOf(k));
else if (isExist(proitemset[k], '·'))
SLRAna[i][Echar.Count + j] = new Table('S', k);
else
SLRAna[i][Echar.Count + j] = new Table('G', k);
}
}
// 填写归约状态
for (int i = 0; i < proitemset.Count; i++)
{
for (int j = 0; j < proitemset[i].Count; j++)
{
if (SLRobjNum[proitemset[i][j]].Right.EndsWith('·'))
{
Gy_obj.Add(proitemset[i][j]);
Gy_itemset.Add(i);
// 使用Follow集判断归约操作
foreach (char c in follow[SLRproNum[proitemset[i][j]].Left])
{
int indexC = Echar.IndexOf(c);
if (indexC != -1)
{
if (SLRAna[i][indexC].error)
{
SLRAna[i][indexC] = new Table('R', Gy_obj.IndexOf(proitemset[i][j]));
}
else
{
// 出现冲突
Success = false;
return;
}
}
}
}
}
}
// 接受状态
if (SLRAna[1][Echar.Count - 1].error)
{
SLRAna[1][Echar.Count - 1] = new Table('A', 0);
}
Success = true;
}
// 其他函数
public List<int> Closure(List<int> I)
{
// ...
}
public List<int> GOTO(List<int> I, int X)
{
// ...
}
public List<int> GOTO(List<int> I, char X)
{
// ...
}
public bool isnexist(List<SLRitemsets> I, List<int> J)
{
// ...
}
public int GetIndex(List<SLRitemsets> I, List<int> J)
{
// ...
}
public bool isExist(List<int> I, int J)
{
// ...
}
public bool isExist(List<int> I, string J)
{
// ...
}
public bool isFinalsymbol(char c)
{
// ...
}
// 计算First集和Follow集
public void CalculateFirstAndFollow()
{
// ...
}
}
注意: 上述代码中省略了部分函数的具体实现,如Closure、GOTO、isnexist、GetIndex、isExist、isFinalsymbol、CalculateFirstAndFollow等,你需要根据你的具体语法规则来实现这些函数。
希望以上代码可以帮助你理解如何将LR(0)分析表的构造算法改进为SLR(1)分析表的构造算法。
总结
SLR(1)分析表是LR(0)分析表的一种改进,它通过考虑Follow集来解决LR(0)分析表中可能存在的移进/归约冲突。在实际应用中,SLR(1)分析表比LR(0)分析表应用更加广泛
原文地址: https://www.cveoy.top/t/topic/f0NZ 著作权归作者所有。请勿转载和采集!