private Dictionary<string, Dictionary<int, string>> GetSelect(Dictionary<string, List<string>> production, Dictionary<string, List<string>> firsts, Dictionary<string, List<string>> follows)
{
    var selects = new Dictionary<string, Dictionary<int, string>>();
    foreach (var nonterm in production.Keys)
    {
        selects[nonterm] = new Dictionary<int, string>();
        for (int i = 0; i < production[nonterm].Count; i++)
        {
            var prod = production[nonterm][i];
            selects[nonterm][i] = '';
            for (int j = 0; j < prod.Length; j++)
            {
                var symbol = prod[j];
                if (IsTerminal(symbol))
                {
                    if (symbol == '#')
                    {
                        foreach (var follow in follows[nonterm])
                        {
                            if (!selects[nonterm][i].Contains(follow))
                            {
                                selects[nonterm][i] += follow + ' ';
                            }
                        }
                    }
                    else if (!selects[nonterm][i].Contains(symbol.ToString()))
                    {
                        selects[nonterm][i] += symbol + ' ';
                    }
                    break;
                }
                else
                {
                    var first = firsts[symbol.ToString()];
                    bool hasEmpty = false;
                    foreach (var f in first)
                    {
                        if (f == '#' )
                        {
                            hasEmpty = true;
                        }
                        else if (!selects[nonterm][i].Contains(f))
                        {
                            selects[nonterm][i] += f + ' ';
                        }
                    }
                    if (!hasEmpty)
                    {
                        break;
                    }
                    if (j == prod.Length - 1)
                    {
                        foreach (var follow in follows[nonterm])
                        {
                            if (!selects[nonterm][i].Contains(follow))
                            {
                                selects[nonterm][i] += follow + ' ';
                            }
                        }
                    }
                }
            }
        }
    }
    return selects;
}

该函数接受三个参数:production 表示文法产生式,firsts 表示每个非终结符的 First 集,follows 表示每个非终结符的 Follow 集。函数首先创建了一个字典 selects,用来存储每个产生式的 select 集。然后,对每个非终结符的每个产生式进行遍历,计算该产生式的 select 集。

对于每个产生式,函数首先清空 selects 中对应产生式的 select 集。然后,对该产生式的每个符号进行遍历,判断该符号是终结符还是非终结符。

如果该符号是终结符,则将其加入到 selects 中。如果该符号是非终结符,则将该非终结符的 First 集加入到 selects 中。

如果该产生式的最后一个符号是空字符 '#',则将该非终结符的 Follow 集加入到 selects 中。

最后,函数返回 selects 字典,该字典存储了每个产生式的 select 集。

代码解析

  • selects 字典用于存储每个产生式的 select 集,键为非终结符,值为一个字典,键为产生式在 production 中的索引,值为该产生式的 select 集字符串。

  • foreach (var nonterm in production.Keys) 遍历每个非终结符。

  • foreach (var prod in production[nonterm]) 遍历每个非终结符的产生式。

  • selects[nonterm][i] = ''; 清空 selects 中对应产生式的 select 集。

  • foreach (var symbol in prod) 遍历产生式中的每个符号。

  • if (IsTerminal(symbol)) 判断符号是否为终结符。

  • if (symbol == '#') 判断符号是否为空字符。

  • foreach (var follow in follows[nonterm]) 遍历该非终结符的 Follow 集。

  • if (!selects[nonterm][i].Contains(follow)) 判断 Follow 集中的符号是否已存在于 select 集中。

  • selects[nonterm][i] += follow + ' '; 将 Follow 集中的符号加入到 select 集中。

  • else if (!selects[nonterm][i].Contains(symbol.ToString())) 判断终结符是否已存在于 select 集中。

  • selects[nonterm][i] += symbol + ' '; 将终结符加入到 select 集中。

  • break; 结束循环,因为已经找到第一个终结符。

  • else 判断符号是否为非终结符。

  • foreach (var f in firsts[symbol.ToString()]) 遍历该非终结符的 First 集。

  • if (f == '#' ) 判断 First 集中的符号是否为空字符。

  • if (!selects[nonterm][i].Contains(f)) 判断 First 集中的符号是否已存在于 select 集中。

  • selects[nonterm][i] += f + ' '; 将 First 集中的符号加入到 select 集中。

  • if (j == prod.Length - 1) 判断是否到达产生式的最后一个符号。

  • foreach (var follow in follows[nonterm]) 遍历该非终结符的 Follow 集。

  • if (!selects[nonterm][i].Contains(follow)) 判断 Follow 集中的符号是否已存在于 select 集中。

  • selects[nonterm][i] += follow + ' '; 将 Follow 集中的符号加入到 select 集中。

  • return selects; 返回 selects 字典。

该 GetSelect 函数实现了 LL(1) 预测分析表生成算法中的重要步骤,即计算每个产生式的 select 集。通过该函数,我们可以得到每个产生式对应的预测分析表项,进而构建完整的预测分析表。', 'code': '```C# private Dictionary<string, Dictionary<int, string>> GetSelect(Dictionary<string, List> production, Dictionary<string, List> firsts, Dictionary<string, List> follows) { var selects = new Dictionary<string, Dictionary<int, string>>(); foreach (var nonterm in production.Keys) { selects[nonterm] = new Dictionary<int, string>(); for (int i = 0; i < production[nonterm].Count; i++) { var prod = production[nonterm][i]; selects[nonterm][i] = ''; for (int j = 0; j < prod.Length; j++) { var symbol = prod[j]; if (IsTerminal(symbol)) { if (symbol == '#') { foreach (var follow in follows[nonterm]) { if (!selects[nonterm][i].Contains(follow)) { selects[nonterm][i] += follow + ' '; } } } else if (!selects[nonterm][i].Contains(symbol.ToString())) { selects[nonterm][i] += symbol + ' '; } break; } else { var first = firsts[symbol.ToString()]; bool hasEmpty = false; foreach (var f in first) { if (f == '#' ) { hasEmpty = true; } else if (!selects[nonterm][i].Contains(f)) { selects[nonterm][i] += f + ' '; } } if (!hasEmpty) { break; } if (j == prod.Length - 1) { foreach (var follow in follows[nonterm]) { if (!selects[nonterm][i].Contains(follow)) { selects[nonterm][i] += follow + ' '; } } } } } } } return selects; }

LL(1) 预测分析表生成算法 - GetSelect 函数实现

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

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