SLR分析表构造与实现

SLR分析表的构造与LR分析表类似,只是在处理移进-归约冲突和归约-归约冲突时需要使用follow集进行判断。具体步骤如下:

  1. 构造follow集

    在SLR分析中,follow集的构造与LR分析类似,只是需要在原有的follow集的基础上,加入所有能够跟随非终结符号A的后继符号。

  2. 根据follow集处理移进-归约冲突和归约-归约冲突

    • 对于移进-归约冲突,只有当follow集中的终结符与当前输入符号相同时,才进行归约操作,否则进行移进操作。 - 对于归约-归约冲突,只有当两个归约项目所对应的follow集没有交集时,才进行归约操作,否则选择优先级更高的归约项目进行归约。

修改后的SLRAnaly()函数C#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++)    {        tnode = new Table('r', Find_pro(LRobjNum[proitemset[Gy_itemset[i]].Container[0]]));//归约项目 找到原产生式序号 添加状态r        for (int j = 0; j < Echar.Count; j++)        {            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);            tnode = new Table('N', dfa[i].to);            LRAna[dfa[i].from][CID + Echar.Count] = tnode;        }        else //不是归约项目 添加状态S        {            int CID = FindID(Echar, dfa[i].symbol);            if (Gy_obj.Contains(dfa[i].to))//归约-移进冲突            {                foreach (char c in Follow[Nchar[CID]])//遍历follow集                {                    int CID2 = FindID(Echar, c);                    if (CID2 != -1)//存在交集                    {                        if (LRAna[dfa[i].from][CID2].type == 'r')//优先级更高的归约项目                        {                            tnode = new Table('r', Find_pro(LRobjNum[proitemset[Gy_itemset[LRAna[dfa[i].from][CID2].id]].Container[0]]));                        }                        else//移进操作                        {                            tnode = new Table('S', dfa[i].to);                        }                    }                    else//不存在交集,进行归约操作                    {                        tnode = new Table('r', Find_pro(LRobjNum[proitemset[Gy_obj.IndexOf(dfa[i].to)]].Container[0]));                    }                    LRAna[dfa[i].from][CID] = tnode;                }            }            else//正常情况,进行移进操作            {                tnode = new Table('S', dfa[i].to);                LRAna[dfa[i].from][CID] = tnode;            }        }    }}

修改后的follow集构造函数C#public void GetFollow(){ Follow = new List[Nchar.Count]; for (int i = 0; i < Nchar.Count; i++) { Follow[i] = new List(); } Follow[0].Add('#');//起始符号的follow集中加入#

bool changed = true;    while (changed)//循环直到follow集不再变化    {        changed = false;        for (int i = 0; i < SLRproNum.Count; i++)        {            string right = SLRproNum[i].Right;            for (int j = 0; j < right.Length; j++)            {                if (isFinalsymbol(right[j]))//终结符号,跳过                {                    continue;                }                int index = FindID(Nchar, right[j]);                if (j == right.Length - 1)//A->αB,将follow(A)加入follow(B)                {                    foreach (char c in Follow[i])                    {                        if (!Follow[index].Contains(c))                        {                            Follow[index].Add(c);                            changed = true;                        }                    }                }                else//A->αBβ,将first(β)中除ε外的符号加入follow(B),如果ε∈first(β),将follow(A)加入follow(B)                {                    string beta = right.Substring(j + 1);                    List<char> first_beta = First(beta);                    foreach (char c in first_beta)                    {                        if (c != 'ε' && !Follow[index].Contains(c))                        {                            Follow[index].Add(c);                            changed = true;                        }                    }                    if (first_beta.Contains('ε'))                    {                        foreach (char c in Follow[i])                        {                            if (!Follow[index].Contains(c))                            {                                Follow[index].Add(c);                                changed = true;                            }                        }                    }                }            }        }    }}

其他函数代码

其他函数的代码与LR分析表构造时相同,只是需要在调用SLRAnaly()时先调用GetFollow()函数,生成follow集。

总结

通过修改SLRAnaly()函数和构造follow集,可以将LR分析表转换为SLR分析表,并处理移进-归约冲突和归约-归约冲突。该过程能够有效地生成SLR分析表,为SLR分析器提供必要的解析信息,完成语法分析

SLR文法分析表构造:SLRAnaly()函数与follow集实现

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

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