SLR分析表的构造需要使用follow集进行判断,具体过程如下:

  1. 对于每个非终结符,求出它的follow集合。

  2. 对于每个项目集合,对于每个终结符和非终结符,分别判断是否需要进行移进或归约操作:

  • 如果该符号是终结符,则查找该项目集合中是否存在一个项目的后继符号是该终结符,如果存在,则将该符号和对应的状态加入分析表中。
  • 如果该符号是非终结符,则查找该符号的follow集合中是否包含该项目集合中的某个终结符,如果存在,则将该符号和对应的状态加入分析表中。
  1. 对于含有归约项目的项目集合,将其对应的状态加入分析表中,表示进行归约操作。

下面是SLR分析表的构造代码:

public void SLRAnaly() { Table tnode = new Table();

LRAna = new Table[proitemset.Count][];
for (int i = 0; i < proitemset.Count; i++)
    LRAna[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状态 
        LRAna[i][j] = tnode;

tnode = new Table('A', 0);
LRAna[1][FindID(Echar, '#')] = tnode;//项目集1必定是接受项目   构建[1][#]:acc的情况 先直接赋值好 dfa里没有

for (int i = 0; i < Gy_itemset.Count; i++)
{
    int proNum = Find_pro(LRobjNum[proitemset[Gy_itemset[i]].Container[0]]);
    foreach (char c in Follow[Nchar[proNum]])//对于非终结符的follow集中的每个终结符
    {
        int j = FindID(Echar, c);
        if (j != -1)//如果该终结符在Echar中存在
        {
            tnode = new Table('r', proNum);//归约项目 找到原产生式序号 添加状态r
            LRAna[Gy_itemset[i]][j] = tnode;
        }
    }
}

for (int i = 0; i < Pindex; i++)
{
    if (isFinalsymbol(dfa[i].symbol))//symbol为非终结符  添加状态N
    {
        int CID = FindID(Nchar, dfa[i].symbol);
        foreach (char c in Follow[Nchar[CID]])//对于非终结符的follow集中的每个终结符
        {
            int j = FindID(Echar, c);
            if (j != -1)//如果该终结符在Echar中存在
            {
                tnode = new Table('N', dfa[i].to);
                LRAna[dfa[i].from][j + Echar.Count] = tnode;
            }
        }
    }
    else //不是归约项目 添加状态S
    {
        int CID = FindID(Echar, dfa[i].symbol);
        tnode = new Table('S', dfa[i].to);
        LRAna[dfa[i].from][CID] = tnode;
    }
}

}

需要注意的是,在SLR分析表的构造中,需要使用follow集,因此需要在文法分析时同时求出每个非终结符的follow集。这里我们假设已经求出了Follow集,可以将其保存在一个名为Follow的List[]中。

完整代码如下:

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 Container = new List(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 class Analyze { public DFA[] dfa = new DFA[100]; public int Pindex = 0; //dfa数组指针 public Table[][] LRAna;//分析表 public bool Success = false; public List SLRproNum = new List(50);//产生式 列表 public List SLRobjNum = new List(50);//项目 列表 public List proitemset = new List(100);//项目集合 public List Gy_obj = new List(50);//归约项目序号集合 public List Gy_itemset = new List(50);//含有归约项目的集合的序号 的集合 public List Nchar = new List(50);//非终结符集合 public List Echar = new List(50);//终结符集合 public List[] Follow; //每个非终结符的follow集合

public string RStr = "";
public string RStr_obitemset = "";//输出返回
public string RStr_DFA = "";
public string RStr_ANA = "";

public Analyze(List<SLRNode> pro, List<char> n, List<char> e)
{
    this.SLRproNum = pro;
    this.Nchar = n;
    this.Echar = e;
    this.Follow = new List<char>[Nchar.Count];
    for (int i = 0; i < Nchar.Count; i++)
        Follow[i] = new List<char>();
}

public void SLRAnaly()
{
    Table tnode = new Table();

    LRAna = new Table[proitemset.Count][];
    for (int i = 0; i < proitemset.Count; i++)
        LRAna[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状态 
            LRAna[i][j] = tnode;

    tnode = new Table('A', 0);
    LRAna[1][FindID(Echar, '#')] = tnode;//项目集1必定是接受项目   构建[1][#]:acc的情况 先直接赋值好 dfa里没有

    for (int i = 0; i < Gy_itemset.Count; i++)
    {
        int proNum = Find_pro(LRobjNum[proitemset[Gy_itemset[i]].Container[0]]);
        foreach (char c in Follow[Nchar[proNum]])//对于非终结符的follow集中的每个终结符
        {
            int j = FindID(Echar, c);
            if (j != -1)//如果该终结符在Echar中存在
            {
                tnode = new Table('r', proNum);//归约项目 找到原产生式序号 添加状态r
                LRAna[Gy_itemset[i]][j] = tnode;
            }
        }
    }

    for (int i = 0; i < Pindex; i++)
    {
        if (isFinalsymbol(dfa[i].symbol))//symbol为非终结符  添加状态N
        {
            int CID = FindID(Nchar, dfa[i].symbol);
            foreach (char c in Follow[Nchar[CID]])//对于非终结符的follow集中的每个终结符
            {
                int j = FindID(Echar, c);
                if (j != -1)//如果该终结符在Echar中存在
                {
                    tnode = new Table('N', dfa[i].to);
                    LRAna[dfa[i].from][j + Echar.Count] = tnode;
                }
            }
        }
        else //不是归约项目 添加状态S
        {
            int CID = FindID(Echar, dfa[i].symbol);
            tnode = new Table('S', dfa[i].to);
            LRAna[dfa[i].from][CID] = tnode;
        }
    }
}

public void SLR()
{
    RStr = "";
    RStr_obitemset = "";
    RStr_DFA = "";
    RStr_ANA = "";

    SLRproNum.Insert(0, new SLRNode("", Nchar[0].ToString()));//添加新的开始产生式
    SLRobjNum.Insert(0, new SLRNode(SLRproNum[0].Left, "." + SLRproNum[0].Right));//添加新的开始项目

    SLR_Closure(0);//构造项目集合

    for (int i = 0; i < proitemset.Count; i++)//求出每个非终结符的follow集合
    {
        SLR_Follow(Nchar[i]);
    }

    SLR_DFA();//构造DFA

    SLRAnaly();//构造分析表

    Success = true;
}

public void SLR_Closure(int p)
{
    bool flag = true;
    while (flag)
    {
        flag = false;
        for (int i = 0; i < proitemset[p].Container.Count; i++)
        {
            int proNum = proitemset[p].Container[i];
            in
public class SLRNode public string Left; public string Right; public SLRNodestring Left string Right thisLeft = Left;

原文地址: https://www.cveoy.top/t/topic/hiyW 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录