该代码实现了计算 LL(1) 文法中非终结符的 FOLLOW 集的功能。实现过程如下:

  1. 判断该非终结符的 FOLLOW 集是否已经被计算出,如果已经计算出,则直接返回。

  2. 将结束符号 '#' 加入起始符号 'intial' 的 FOLLOW 集。

  3. 遍历产生式,对于每个产生式,找到该非终结符在产生式中的位置,然后根据位置进行处理。

  4. 如果该非终结符在产生式末尾,则将产生式左边非终结符的 FOLLOW 集加入该非终结符的 FOLLOW 集中。

  5. 如果该非终结符不在产生式末尾(即后面还跟着其他符号),则需要根据后面的符号进行处理。

  6. 如果后面是终结符,则直接将其加入该非终结符的 FOLLOW 集中。

  7. 如果后面是非终结符,则将该非终结符的 FIRST 集加入该非终结符的 FOLLOW 集中,若该非终结符能够推出空,还需将产生式左边的 FOLLOW 集加入。

  8. 循环结束后,该非终结符的 FOLLOW 集就被计算出来了,并存储在 'follows' 字典中。

void GetFollow(string symbol)
{
    // 如果该非终结符的 FOLLOW 集已经被计算出,则直接返回
    if (follows.ContainsKey(symbol))
    {
        return;
    }
    var grammar = LL1Item.getproduction();
    var is_reach = LL1Item.getisreach();
    follows.Add(symbol, new List<string>());

    // 将结束符号 # 加入起始符号 intial 的 FOLLOW 集
    if (symbol == LL1Item.intinal)
    {
        follows[symbol].Add('#');
    }

    // 遍历产生式,计算 FOLLOW 集
    foreach (string key in LL1Item.nofinal)
    {
        foreach (var prod in grammar[key])
        {
            for (int i = 0; i < prod.Length; i++)
            {
                if (prod[i].ToString() == symbol)
                {
                    // 如果该非终结符在产生式末尾,则将产生式左边非终结符的 FOLLOW 集加入该非终结符的 FOLLOW 集中
                    if (i == prod.Length - 1)
                    {
                        if (key != symbol)
                        {
                            GetFollow(key);
                            foreach (var f in follows[key])
                            {
                                if(!follows[symbol].Contains(f))
                                    follows[symbol].Add(f);
                            }
                        }
                    }
                    // 如果该非终结符不在产生式末尾(即后面还跟着其他符号)
                    else
                    {
                        // 如果后面是终结符,则直接将其加入该非终结符的 FOLLOW 集中
                        if (IsTerminal(prod[i + 1])&& !follows[symbol].Contains(prod[i + 1].ToString()))
                        {
                            follows[symbol].Add(prod[i + 1].ToString());
                        }
                        // 如果后面是非终结符,则将该非终结符的 FIRST 集加入该非终结符的 FOLLOW 集中,若该非终结符能够推出空,还需将产生式左边的 FOLLOW 集加入
                        else
                        {
                            foreach (var f in first.getfirsts()[prod[i + 1].ToString()])
                            {
                                if (f != '#')
                                {
                                    if (!follows[symbol].Contains(f))
                                        follows[symbol].Add(f);
                                }
                            }
                            if (first.getfirsts()[prod[i + 1].ToString()].Contains('#') && key != symbol)
                            {
                                GetFollow(key);
                                foreach (var f in follows[key])
                                {
                                    if (!follows[symbol].Contains(f))
                                        follows[symbol].Add(f);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

该代码中,'follows' 字典存储了每个非终结符的 FOLLOW 集,'grammar' 字典存储了所有产生式,'first' 对象用于获取每个非终结符的 FIRST 集。

该代码的核心是递归调用 'GetFollow' 函数,通过遍历产生式,逐步计算每个非终结符的 FOLLOW 集。该算法的时间复杂度为 O(n*m),其中 n 为非终结符数量,m 为产生式数量。

**注意:**该代码仅供参考,实际应用中需要根据具体的 LL(1) 文法进行调整。

LL(1) 文法非终结符 FOLLOW 集计算算法解析

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

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