public class Select
{
    LL1Item LL1Item;
    First first;
    Follow follow;
    Dictionary<string, Dictionary<string, List<string>>> selects;

    public Select(LL1Item LL1Item, First first, Follow follow)
    {
        this.LL1Item = LL1Item;
        this.first = first;
        this.follow = follow;
        selects = new Dictionary<string, Dictionary<string, List<string>>>();
        GetSelect();
    }

    public void GetSelect()
    {
        var production = LL1Item.getproduction();
        foreach (var nofinal in LL1Item.nofinal)
        {
            selects.Add(nofinal, new Dictionary<string, List<string>>());
            //对非终结符的每个产生式获取select值
            foreach (var f in production[nofinal])
            {
                selects[nofinal].Add(f, new List<string>());
                for (int i = 0; i < f.Length; i++)
                {
                    //如果该产生式第一个字符为终结符
                    if (IsTerminal(f[i]))
                    {
                        if (f[i].Equals('#'))
                        {
                            foreach (var fol in follow.getfollows()[nofinal])
                                selects[nofinal][f].Add(fol);
                        }
                        else if (!selects[nofinal][f].Contains(f[i].ToString()))
                            selects[nofinal][f].Add(f[i].ToString());
                        break;
                    }
                    //如果该产生式第一个字符为非终结符
                    else
                    {
                        int flag = 0;
                        foreach (var fir in first.getfirsts()[f[i].ToString()])
                        {
                            if (fir.Equals('#'))
                                flag = 1;
                            else
                            {
                                if (!selects[nofinal][f].Contains(fir))
                                    selects[nofinal][f].Add(fir);
                            }
                        }
                        if (flag == 0) break;
                    }
                    if (i == f.Length - 1)
                    {
                        foreach (var fol in follow.getfollows()[nofinal])
                            if (!selects[nofinal][f].Contains(fol))
                                selects[nofinal][f].Add(fol);
                    }
                }
            }
        }
    }
    static bool IsTerminal(char symbol)
    {
        return !char.IsUpper(symbol);
    }

    public Dictionary<string, Dictionary<string, List<string>>> getselects()
    {
        return selects;
    }
}

// 计算 SELECT 集的函数 (不使用 LL1Item)
private Dictionary<string, List<string>> GetSelect(Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1, Dictionary<string, List<string>> follows1)
{
    // 初始化 SELECT 集
    Dictionary<string, List<string>> selects1 = new Dictionary<string, List<string>>();
    foreach (var item in production1)
        selects1.Add(item.Key, new List<string>());

    // 遍历每个产生式,计算对应的 SELECT 集
    foreach (var nonterm in production1.Keys)
    {
        foreach (var prod in production1[nonterm])
        {
            List<string> select = new List<string>();
            bool flag = true;
            // 对于产生式中的每个符号,计算其 FIRST 集
            foreach (var s in prod)
            {
                if (IsTerminal(s))
                {
                    select.Add(s.ToString());
                    flag = false;
                    break;
                }
                else
                {
                    GetFirst(s.ToString(), production1, firsts1);
                    foreach (var f in firsts1[s.ToString()])
                    {
                        if (!f.Equals('#') && !select.Contains(f))
                            select.Add(f);
                    }
                    if (!IsReachEmpty(s.ToString(), production1))
                    {
                        flag = false;
                        break;
                    }
                }
            }
            // 如果产生式中所有符号的 FIRST 集都包含空串,则将 FOLLOW 集加入 SELECT 集中
            if (flag)
            {
                GetFollow(nonterm, production1, firsts1, follows1);
                foreach (var f in follows1[nonterm])
                {
                    if (!select.Contains(f))
                        select.Add(f);
                }
            }
            selects1[nonterm].Add(string.Join("", select.ToArray()));
        }
    }
    return selects1;
}

// 获取符号的 FIRST 集 (需根据具体情况补充)
private void GetFirst(string symbol, Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1)
{
    // ...
}

// 判断符号是否能推导出空串 (需根据具体情况补充)
private bool IsReachEmpty(string symbol, Dictionary<string, List<string>> production1)
{
    // ...
}

// 获取非终结符的 FOLLOW 集 (需根据具体情况补充)
private void GetFollow(string nonterm, Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1, Dictionary<string, List<string>> follows1)
{
    // ...
}

代码说明:

  1. GetSelect 函数接受三个参数:

    • production1: 产生式集合,表示每个非终结符可以推导出的所有产生式。
    • firsts1: FIRST 集集合,表示每个符号的 FIRST 集。
    • follows1: FOLLOW 集集合,表示每个非终结符的 FOLLOW 集。
  2. GetSelect 函数首先初始化一个新的字典 selects1,用于存储 SELECT 集。

  3. 然后,函数遍历所有非终结符 nonterm 和其对应的产生式 prod

  4. 对于每个产生式,函数初始化一个新的列表 select 用于存储当前产生式的 SELECT 集。

  5. 函数使用一个 flag 变量来判断当前产生式的所有符号的 FIRST 集是否都包含空串。

  6. 对于产生式中的每个符号 s,函数判断其是否为终结符。

    • 如果是终结符,直接将该终结符加入 select 列表。
    • 如果不是终结符,则调用 GetFirst 函数获取该非终结符的 FIRST 集,并将其加入 select 列表,如果该非终结符的 FIRST 集包含空串,则将 flag 设置为 false
  7. 如果 flag 仍然为 true,表示当前产生式的所有符号的 FIRST 集都包含空串,则调用 GetFollow 函数获取当前非终结符的 FOLLOW 集,并将其加入 select 列表。

  8. 最后,将 select 列表中的所有元素拼接成字符串,并加入 selects1 中。

补充说明:

  • GetFirstIsReachEmptyGetFollow 函数需要根据具体的语法规则进行实现,本文示例中并未给出具体的实现代码。
  • 该代码示例仅供参考,实际应用中需要根据具体的语法规则进行调整。

注意:

  • 该代码示例仅包含 GetSelect 函数的实现,其他辅助函数需要根据具体需求进行补充。
  • 该代码示例中的 IsTerminal 函数用于判断字符是否为终结符,实际应用中可能需要根据具体的语法规则进行调整。
  • 该代码示例中的 GetSelect 函数需要使用预先计算好的 FIRST 集和 FOLLOW 集,实际应用中需要根据具体的语法规则进行计算。

建议:

  • 在学习 LL1 句法分析器时,建议先理解 FIRST 集、FOLLOW 集和 SELECT 集的概念,以及如何计算它们。
  • 在编写代码时,建议使用一些辅助工具或库来帮助你进行语法分析,例如 ANTLR 或 Yacc。
  • 建议使用测试用例来验证你的代码是否正确。
LL1 句法分析器:SELECT 集的计算 (C# 代码示例)

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

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