// 完整代码如下:
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;
}

代码逻辑说明:

  1. 初始化 SELECT 集: 创建一个名为 selects1 的字典,用于存储每个非终结符对应的 SELECT 集。初始时,每个非终结符的 SELECT 集为空。

  2. 遍历产生式: 遍历所有产生式,对每个产生式计算其 SELECT 集。

  3. 计算 FIRST 集: 对产生式中的每个符号,计算其 FIRST 集。如果符号是终结符,则其 FIRST 集为该终结符本身。如果符号是非终结符,则调用 GetFirst 函数获取其 FIRST 集。

  4. 判断是否包含空串: 如果当前符号的 FIRST 集包含空串,则继续计算下一个符号的 FIRST 集。如果当前符号的 FIRST 集不包含空串,则将当前符号的 FIRST 集加入 SELECT 集中,并结束当前产生式的 SELECT 集计算。

  5. 计算 FOLLOW 集: 如果当前产生式中所有符号的 FIRST 集都包含空串,则计算当前非终结符的 FOLLOW 集,并将 FOLLOW 集加入 SELECT 集中。

代码示例:

// 示例数据
Dictionary<string, List<string>> production = new Dictionary<string, List<string>>
{
    {"E", new List<string> { "E+T", "T" }},
    {"T", new List<string> { "T*F", "F" }},
    {"F", new List<string> { "(E)", "id" }}
};

Dictionary<string, List<string>> firsts = new Dictionary<string, List<string>>
{
    {"E", new List<string> { "(", "id" }},
    {"T", new List<string> { "(", "id" }},
    {"F", new List<string> { "(", "id" }},
    {"+", new List<string> { "+" }},
    {"*", new List<string> { "*" }},
    {"(", new List<string> { "(" }},
    {")", new List<string> { ")" }},
    {"id", new List<string> { "id" }}
};

Dictionary<string, List<string>> follows = new Dictionary<string, List<string>>
{
    {"E", new List<string> { ")", "$" }},
    {"T", new List<string> { "+", ")", "$" }},
    {"F", new List<string> { "*", "+", ")", "$" }}
};

// 计算 SELECT 集
Dictionary<string, List<string>> selects = GetSelect(production, firsts, follows);

// 打印 SELECT 集
foreach (var nonterm in selects.Keys)
{
    Console.WriteLine($"{nonterm}: {string.Join(", ", selects[nonterm])}");
}

输出:

E: (,(id,E+T,T
T: (,(id,T*F,F
F: (,(id

代码中的 GetFirstGetFollow 函数需要根据具体情况进行实现。

LL1 语法分析器中的 SELECT 集计算 - C# 代码实现

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

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