在 C# 代码中,使用分析表进行语法分析时,如果出现语句 string production = table[topAnalyse.ToString()][topInput.ToString()]; 出错,只能输出 System.Collections.Generic.Stack1[System.Char],无法正确输出对应的分析串和剩余输出串,这是因为该语句没有将 table[topAnalyse.ToString()][topInput.ToString()]` 的值转换为字符串类型。

修改方法:

将语句 string production = table[topAnalyse.ToString()][topInput.ToString()]; 修改为 string production = table[topAnalyse.ToString()][topInput.ToString()].ToString();,在第 68 行进行修改。

修改后的代码:

private void GetFirst(string symbol, Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1)
        {
            // 如果该非终结符的 FIRST 集已经被计算出,则直接返回
            if (firsts1.ContainsKey(symbol))
            {
                return;
            }
            firsts1.Add(symbol, new List<string>());
            // 遍历产生式,计算 FIRST 集
            foreach (var prod in production1[symbol])
            {
                // 如果产生式首字符为终结符,则直接将其加入 FIRST 集中
                if (prod.Length > 0 && IsTerminal(prod[0]))
                {
                    if (!firsts1[symbol].Contains(prod[0].ToString()))
                        firsts1[symbol].Add(prod[0].ToString());
                    continue;
                }
                // 如果产生式首字符为非终结符,则计算该非终结符的 FIRST 集,并将结果加入首字符的 FIRST 集中
                else if (prod.Length > 0 && !IsTerminal(prod[0]))
                {
                    GetFirst(prod[0].ToString(), production1, firsts1);
                    foreach (var f in firsts1[prod[0].ToString()])
                    {
                        if (!firsts1[symbol].Contains(f) && !f.Equals('#'))
                            firsts1[symbol].Add(f);
                    }
                }
                //如果第一个非终结符能推出#
                if (IsReachEmpty(prod[0].ToString(), production1))
                {
                    // 递归计算第二个和后面的字符的 FIRST 集,并将结果加入该非终结符的 FIRST 集中
                    for (int j = 1; j < prod.Length; j++)
                    {
                        if (IsTerminal(prod[j]))
                        {
                            if (!firsts1[symbol].Contains(prod[j].ToString()))
                                firsts1[symbol].Add(prod[j].ToString());
                            break;
                        }
                        GetFirst(prod[j].ToString(), production1, firsts1);
                        foreach (var f in firsts1[prod[j].ToString()])
                        {
                            if (!firsts1[symbol].Contains(f) && !f.Equals('#'))
                                firsts1[symbol].Add(f);
                        }
                        // 如果该非终结符的 FIRST 集没有包含空串,则可以结束循环
                        if (!IsReachEmpty(prod[j].ToString(), production1))
                        {
                            break;
                        }
                        // 如果是最后一个字符且所有非终结符的 FIRST 集都含有空串,则将空串加入该非终结符的 FIRST 集中
                        if (j == prod.Length - 1)
                        {
                            if (!firsts1[symbol].Contains('#'))
                                firsts1[symbol].Add('#');
                        }
                    }
                }
            }
        }


        // 计算 FOLLOW 集
        private void GetFollow(string symbol, Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1, Dictionary<string, List<string>> follows1)
        {
            // 如果该非终结符的 FOLLOW 集已经被计算出,则直接返回
            if (follows1.ContainsKey(symbol))
            {
                return;
            }
            follows1.Add(symbol, new List<string>());
            // 如果是起始符号,则将 # 加入 FOLLOW 集中
            if (symbol.Equals(production1.Keys.First()))
            {
                if (!follows1[symbol].Contains('#'))
                    follows1[symbol].Add('#');
            }
            // 遍历产生式,计算 FOLLOW 集
            foreach (var item in production1)
            {
                foreach (var prod in item.Value)
                {
                    int index = prod.IndexOf(symbol);
                    if (index == -1)
                        continue;
                    // 如果该非终结符位于产生式末尾,则将产生式左部的 FOLLOW 集加入该非终结符的 FOLLOW 集中
                    if (index == prod.Length - 1)
                    {
                        GetFollow(item.Key, production1, firsts1, follows1);
                        foreach (var f in follows1[item.Key])
                        {
                            if (!follows1[symbol].Contains(f))
                                follows1[symbol].Add(f);
                        }
                    }
                    else
                    {
                        // 如果该非终结符后面是终结符,则将该终结符加入该非终结符的 FOLLOW 集中
                        if (IsTerminal(prod[index + 1]))
                        {
                            if (!follows1[symbol].Contains(prod[index + 1].ToString()))
                                follows1[symbol].Add(prod[index + 1].ToString());
                        }
                        // 如果该非终结符后面是非终结符,则将该非终结符的 FIRST 集加入该非终结符的 FOLLOW 集中
                        else
                        {
                            GetFirst(prod[index + 1].ToString(), production1, firsts1);
                            foreach (var f in firsts1[prod[index + 1].ToString()])
                            {
                                if (!f.Equals('#') && !follows1[symbol].Contains(f))
                                    follows1[symbol].Add(f);
                            }
                            // 如果该非终结符后面的所有符号都能推出空串,则将产生式左部的 FOLLOW 集加入该非终结符的 FOLLOW 集中
                            if (IsReachEmpty(prod[index + 1].ToString(), production1))
                            {
                                GetFollow(item.Key, production1, firsts1, follows1);
                                foreach (var f in follows1[item.Key])
                                {
                                    if (!follows1[symbol].Contains(f))
                                        follows1[symbol].Add(f);
                                }
                            }
                        }
                    }
                }
            }
        }

        private void GetSelect(Dictionary<string, List<string>> production1, Dictionary<string, List<string>> firsts1, Dictionary<string, List<string>> follows1)
        {
            //对非终结符的每个产生式获取select值
            //如果该产生式第一个字符为终结符
            //如果该产生式第一个字符为非终结符
            // 对每个非终结符进行操作
            // 对每个非终结符进行遍历
            foreach (var nonterm in nonterminals)
            {
                // 获取该非终结符的所有产生式
                var productions = production1[nonterm];

                // 遍历该非终结符的所有产生式
                foreach (var prod in productions)
                {
                    // 初始化该产生式的 select 值
                    List<string> select = new List<string>();

                    // 如果该产生式的第一个字符为终结符,直接将该字符加入 select
                    if (IsTerminal(prod[0]))
                    {
                        if (prod[0].Equals('#'))
                        {
                            // 如果该产生式的第一个字符为 #,将 follow(nonterm) 加入 select
                            select.AddRange(follows1[nonterm]);
                        }
                        else
                        {
                            // 如果该产生式的第一个字符为其他终结符,将该终结符加入 select
                            select.Add(prod[0].ToString());
                        }
                    }
                    else
                    {
                        // 如果该产生式的第一个字符为非终结符,将该非终结符的 first 集加入 select
                        select.AddRange(firsts1[prod[0].ToString()]);

                        // 如果该非终结符的 first 集中包含空串,将 follow(nonterm) 加入 select
                        if (select.Contains('#'))
                        {
                            select.Remove('#');
                            select.AddRange(follows1[nonterm]);
                        }
                    }

                    // 将该产生式的 select 值加入预测分析表中
                    foreach (var term in select)
                    {
                        table[nonterm][term] = prod;
                    }
                }
            }

        }

        private void analyze()
        {
            while (true)
            {
                // 如果分析栈为空或者输入栈为空,则分析结束
                if (analyseStack.Count == 0 || inputStack.Count == 0)
                {
                    break;
                }

                // 获取分析栈的栈顶元素和输入栈的栈顶元素
                char topAnalyse = analyseStack.Peek();
                char topInput = inputStack.Peek();

                // 如果分析栈的栈顶元素和输入栈的栈顶元素相同,则进行匹配
                if (topAnalyse == topInput)
                {
                    // 将匹配的元素从分析栈和输入栈中弹出
                    analyseStack.Pop();
                    inputStack.Pop();

                    // 在分析结果列表中添加匹配信息
                    resultAnalyse.Add(analyseStack.ToString());
                    resultInput.Add(inputStack.ToString());
                    resultParse.Add(''' + topAnalyse + '' 匹配');
                }
                else
                {
                    // 如果分析栈的栈顶元素为终结符,则出错
                    if (IsTerminal(topAnalyse))
                    {
                        resultParse.Add('出错');
                        break;
                    }
                    else
                    {
                        if (!table.ContainsKey(topAnalyse.ToString()) || !table[topAnalyse.ToString()].ContainsKey(topInput.ToString()))
                        {
                            resultParse.Add('出错');
                            break;
                        }
                        else
                        {
                            // 获取分析表中的产生式
                            string production = table[topAnalyse.ToString()][topInput.ToString()].ToString();

                            // 如果分析表中没有产生式,则出错
                            if (production == null)
                            {
                                resultParse.Add('出错');
                                break;
                            }
                            else
                            {
                                // 将产生式从分析栈中弹出
                                analyseStack.Pop();

                                // 如果产生式不是空串,则将产生式中的符号逆序压入分析栈中
                                if (production != '#')
                                {
                                    for (int i = production.Length - 1; i >= 0; i--)
                                    {
                                        analyseStack.Push(production[i]);
                                    }
                                }

                                // 在分析结果列表中添加产生式信息
                                resultAnalyse.Add(analyseStack.ToString());
                                resultInput.Add(inputStack.ToString());
                                resultParse.Add(topAnalyse + ' -> ' + production);
                                System.Console.WriteLine(analyseStack.ToString() + '\n');
                                System.Console.WriteLine(inputStack.ToString() + '\n');
                                System.Console.WriteLine(topAnalyse + ' -> ' + production + '\n');
                            }
                        }
                    }
                }
            }

            // 如果分析栈和输入栈都为空,则分析成功
            if (analyseStack.Count == 0 && inputStack.Count == 0)
            {
                resultParse.Add('成功');
            }
        }

出错原因:

table[topAnalyse.ToString()][topInput.ToString()] 获取的值可能是一个对象,而不是字符串类型,因此需要使用 .ToString() 方法将其转换为字符串类型。

注意:

请确保代码中的 table 变量类型为 Dictionary<string, Dictionary<string, string>>,确保 table[topAnalyse.ToString()][topInput.ToString()] 获取的值是一个字符串类型的值。

C# 代码错误:无法正确输出分析串和剩余输出串,如何改正?

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

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