SLR1 分析:错误分析与修正

问题:

在使用 SLR1 分析方法分析文法时,分析表中缺少了 'r' 状态,导致分析器无法正确识别归约项目。这是因为在 SLRAnaly() 方法中,没有正确处理归约项目。

错误分析:

  1. **没有处理 Follow 集:**在遍历项目集中的所有项目时,对于归约项目,应该将其左部符号的 Follow 集中的所有终结符加入到对应的分析表格中。
  2. **没有处理结束符号 #:**当 Follow 集中包含结束符号 '#' 时,需要将所有终结符的分析表格都设为对应产生式的编号 'r'。

修正代码:

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 < proitemset.Count; i++)//遍历所有的项目集
    {
        foreach (int index in proitemset[i].Container)//遍历项目集中的所有项目
        {
            SLRNode item = SLRobjNum[index];
            if (item.Right == 'd')//归约项目
            {
                int leftIndex = FindID(Nchar, item.Left[0]);
                List<char> follow = Follow[leftIndex];//获取左部符号的follow集
                foreach (char c in follow)
                {
                    int CID = FindID(Echar, c);
                    SLRAna[i][CID] = new Table('r', Find_pro(item));
                    if (c == '#')
                    {
                        foreach (char e in Echar)
                        {
                            int EID = FindID(Echar, e);
                            SLRAna[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);
        }
    }
}

修正后的代码主要做了以下改动:

  1. 在处理归约项目时,使用 Follow 集中的所有终结符填充对应的分析表格,将 'r' 状态加入其中。
  2. 在处理结束符号 '#' 时,将所有终结符的分析表格都设为对应产生式的编号 'r'。

代码说明:

  • FindID(Echar, c): 获取终结符 cEchar 列表中的序号。
  • FindID(Nchar, c): 获取非终结符 cNchar 列表中的序号。
  • Find_pro(item): 获取项目 item 对应的产生式的编号。
  • isFinalsymbol(c): 判断字符 c 是否是终结符。

总结:

通过正确处理归约项目和结束符号,我们可以完整构建 SLR1 分析表,并使用该分析表进行语法的识别和分析。

建议:

  • 在实现 SLR1 分析方法时,务必仔细处理归约项目,确保分析表完整性。
  • 使用调试工具对代码进行测试,确保程序正确性。
  • 参考相关资料,深入理解 SLR1 分析的原理和实现细节。
SLR1 分析:错误分析与修正

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

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