// 获取非终结符的Follow集
public Dictionary<char, HashSet<char>> GetFollow(List<char> Nchar, List<char> Echar, List<SLRNode> SLRproNum, List<SLRNode> SLRobjNum)
{
    Dictionary<char, HashSet<char>> follow = new Dictionary<char, HashSet<char>>();

    // 将'#'加入开始符的Follow集
    HashSet<char> start_follow = new HashSet<char>();
    start_follow.Add('#');
    follow.Add(SLRproNum[0].Left[0], start_follow);

    // 循环直到所有非终结符的Follow集都不再改变
    bool change = true;
    while (change)
    {
        change = false;
        for (int i = 0; i < SLRproNum.Count; i++)
        {
            string right = SLRproNum[i].Right;
            for (int j = 0; j < right.Length; j++)
            {
                if (!Nchar.Contains(right[j]))
                    continue;
                if (j == right.Length - 1)
                {//如果该非终结符在产生式末尾
                    HashSet<char> set = follow[SLRproNum[i].Left[0]];
                    HashSet<char> old_set = new HashSet<char>(set);
                    set.UnionWith(old_set);
                    if (set.Count != old_set.Count)
                        change = true;
                }
                else
                {//如果该非终结符不在产生式末尾
                    HashSet<char> set = new HashSet<char>();
                    for (int k = j + 1; k < right.Length; k++)
                    {
                        if (Echar.Contains(right[k]))
                        {
                            set.Add(right[k]);
                            break;
                        }
                        HashSet<char> first = First(right[k].ToString(), SLRobjNum);
                        if (first.Contains('#'))
                        {
                            first.Remove('#');
                            set.UnionWith(first);
                            continue;
                        }
                        else
                        {
                            set.UnionWith(first);
                            break;
                        }
                    }
                    HashSet<char> old_set = new HashSet<char>(follow[right[j]]);
                    follow[right[j]].UnionWith(set);
                    if (follow[right[j]].Count != old_set.Count)
                        change = true;
                }
            }
        }
    }

    return follow;
}

// 获取符号串的First集
public HashSet<char> First(string str, List<SLRNode> SLRobjNum)
{
    HashSet<char> set = new HashSet<char>();
    if (str == '')
    {
        set.Add('#');
        return set;
    }
    if (!isFinalsymbol(str[0]))
    {
        for (int i = 0; i < SLRobjNum.Count; i++)
        {
            if (SLRobjNum[i].Left[0] == str[0])
            {
                if (SLRobjNum[i].Right == '#')
                    set.UnionWith(First(str.Substring(1), SLRobjNum));
                else
                    set.UnionWith(First(SLRobjNum[i].Right + str.Substring(1), SLRobjNum));
            }
        }
    }
    else
    {
        set.Add(str[0]);
    }
    return set;
}

这段代码实现了SLR(1)分析器中的GetFollow()函数,用于计算文法中非终结符的Follow集。函数接受四个参数:

  • Nchar: 非终结符集合
  • Echar: 终结符集合
  • SLRproNum: 产生式集合
  • SLRobjNum: 项目集合

函数首先将'#'加入开始符的Follow集中,然后循环遍历所有产生式,根据Follow集的定义逐步计算每个非终结符的Follow集,直到所有非终结符的Follow集都不再改变为止。

函数中还包含一个辅助函数First(),用于计算符号串的First集。

这段代码清晰易懂,注释详细,可以帮助理解SLR(1)分析器中Follow集的计算方法。

SLR(1)分析器中GetFollow()函数的实现

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

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