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()];

                    // 如果分析表中没有产生式,则出错
                    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);
                    }
                }
            }
        }
    }

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

// 预测分析表
private Dictionary<string, Dictionary<string, string>> table;

// 构造函数
public SyntaxAnalyzer(List<Production> productions, List<char> terminals, List<char> nonTerminals)
{
    // 构造预测分析表
    table = new Dictionary<string, Dictionary<string, string>>();
    foreach (var nonTerminal in nonTerminals)
    {
        table.Add(nonTerminal.ToString(), new Dictionary<string, string>());
        foreach (var terminal in terminals)
        {
            table[nonTerminal.ToString()].Add(terminal.ToString(), null);
        }
        table[nonTerminal.ToString()].Add("#", null);
    }

    foreach (var production in productions)
    {
        string nonTerminal = production.Left.ToString();
        foreach (var terminal in production.First)
        {
            if (terminal != '#')
            {
                table[nonTerminal][terminal.ToString()] = production.Right;
            }
            else
            {
                foreach (var follow in production.Follow)
                {
                    table[nonTerminal][follow.ToString()] = production.Right;
                }
            }
        }
    }
}

// 判断是否为终结符
static bool IsTerminal(char symbol)
{
    return !char.IsUpper(symbol);
}

代码说明:

  1. 预测分析表: 代码使用 table 字典来存储预测分析表,其中 key 为非终结符,value 为另一个字典,该字典的 key 为终结符,value 为对应的产生式。
  2. 分析过程: 代码使用 analyseStackinputStack 两个栈来模拟语法分析过程,并使用 resultAnalyseresultInputresultParse 列表来记录分析过程中的信息。
  3. 分析步骤:
    • 获取分析栈和输入栈的栈顶元素。
    • 如果两个栈顶元素相同,则进行匹配,并将元素从两个栈中弹出。
    • 如果分析栈的栈顶元素为终结符,则出错。
    • 如果分析栈的栈顶元素为非终结符,则根据预测分析表获取产生式,并将产生式中的符号逆序压入分析栈中。
  4. 分析结果: 代码最后会根据分析栈和输入栈的状态判断分析是否成功,并将分析结果记录到 resultParse 列表中。

示例:

假设 LL(1) 文法为:

E -> T + E | T
T -> F * T | F
F -> id

预测分析表为:

| | id | + | * | # | | |-------|----|---|---|---|--| | E | T | T | T | T | | | T | F | F | F | F | | | F | id | | | | |

输入字符串为:id + id * id

分析过程:

  • 初始化分析栈为 E,输入栈为 id + id * id#
  • 根据预测分析表,E 可以推导出 T,将 T 压入分析栈,分析栈变为 TEresultParse 列表中添加 E -> T
  • 继续根据预测分析表,T 可以推导出 F,将 F 压入分析栈,分析栈变为 TFEresultParse 列表中添加 T -> F
  • 继续根据预测分析表,F 可以推导出 id,将 id 压入分析栈,分析栈变为 TFidEresultParse 列表中添加 F -> id
  • 匹配 id,将 id 从分析栈和输入栈中弹出,分析栈变为 TFEresultParse 列表中添加 "id" 匹配
  • 继续分析,直到输入栈为空,分析成功。

结果:

resultParse 列表中包含以下内容:

E -> T
T -> F
F -> id
"id" 匹配
E -> T + E
T -> F
F -> id
"id" 匹配
"+" 匹配
T -> F * T
F -> id
"id" 匹配
"*" 匹配
F -> id
"id" 匹配
"#" 匹配
成功

总结:

该代码实现了基于 LL(1) 文法的语法分析器,能够根据预测分析表对输入字符串进行分析,并输出分析结果。代码结构清晰、易于理解,适用于学习和理解语法分析过程。

LL(1) 语法分析器实现

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

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