LR(0)分析表到SLR(1)分析表的改进

在编译原理中,LR(0)分析表和SLR(1)分析表都是用于语法分析的重要工具。SLR(1)分析表是对LR(0)分析表的一种改进,它通过考虑Follow集来解决LR(0)分析表中可能存在的移进/归约冲突。

代码实现 (C#)

以下是使用C#实现的SLR(1)分析表构造算法:

using System;
using System.Collections.Generic;

public class SLRNode
{
    public string Left;
    public string Right;
    public SLRNode(string Left, string Right)
    {
        this.Left = Left;
        this.Right = Right;
    }
}

public class SLRitemsets
{
    public List<int> Container = new List<int>(100);
}

public struct DFA
{
    public int from;
    public char symbol;
    public int to;
    public DFA(int from, char symbol, int to)
    {
        this.from = from;
        this.symbol = symbol;
        this.to = to;
    }
}

public class Table
{
    public bool error = true;
    public char type;
    public int id;
    public Table() { }
    public Table(char type, int id)
    {
        this.type = type;
        this.id = id;
        this.error = false;
    }
}

public class Analyze
{
    public List<string> stack_state = new List<string>(100);
    public List<string> stack_symbol = new List<string>(100);
    public List<string> Input_str = new List<string>(100);
    public List<string> Tran_pro = new List<string>(100);
}

public class SLRParser
{
    public DFA[] dfa = new DFA[100];
    public int Pindex = 0;
    public Table[][] SLRAna;
    public Analyze Jz;
    public bool Success = false;
    public List<SLRNode> SLRproNum = new List<SLRNode>(50);
    public List<SLRNode> SLRobjNum = new List<SLRNode>(50);
    public List<SLRitemsets> proitemset = new List<SLRitemsets>(100);
    public List<int> Gy_obj = new List<int>(50);
    public List<int> Gy_itemset = new List<int>(50);
    public List<char> Nchar = new List<char>(50);
    public List<char> Echar = new List<char>(50);

    Dictionary<char, HashSet<char>> first = new Dictionary<char, HashSet<char>>();
    Dictionary<char, HashSet<char>> follow = new Dictionary<char, HashSet<char>>();

    public string RStr = '';
    public string RStr_obitemset = '';
    public string RStr_DFA = '';
    public string RStr_ANA = '';

    public Table[][] GET_ANA()
    {
        SLRAnaly();
        RStr_ANA += '\r\nSLR(1)分析表:\r\n    ';
        int i;
        for (i = 0; i < Echar.Count; i++)
        {
            RStr_ANA += Echar[i].ToString() + '     ';
        }
        for (i = 0; i < Nchar.Count; i++)
        {
            RStr_ANA += Nchar[i].ToString() + '     ';
        }
        RStr_ANA += '\r\n';
        for (i = 0; i < proitemset.Count; i++)
        {
            RStr_ANA += i.ToString() + '  ';
            for (int j = 0; j < Echar.Count + Nchar.Count; j++)
            {
                if (SLRAna[i][j].error)
                {
                    RStr_ANA += '  ' + '    ';
                }
                else if (i == 1 && j == Echar.Count - 1)
                {
                    RStr_ANA += 'AC' + '    ';
                }
                else if (SLRAna[i][j].type != 'N')
                {
                    RStr_ANA += SLRAna[i][j].type.ToString() + SLRAna[i][j].id.ToString() + '    ';
                }
                else
                    RStr_ANA += SLRAna[i][j].id.ToString() + '    ';
            }
            RStr_ANA += '\r\n';
        }

        return SLRAna;
    }

    public void SLRAnaly()
    {
        // 构造SLR(1)项目集
        SLRitemsets I0 = new SLRitemsets();
        I0.Container.Add(0);
        proitemset.Add(Closure(I0.Container));

        int index = 0;
        while (index < proitemset.Count)
        {
            for (int i = 0; i < Echar.Count + Nchar.Count; i++)
            {
                List<int> Goto = GOTO(proitemset[index], i);
                if (Goto.Count == 0)
                    continue;
                if (isnexist(proitemset, Goto))
                    proitemset.Add(Closure(Goto));
                dfa[Pindex++] = new DFA(index, (i < Echar.Count) ? Echar[i] : Nchar[i - Echar.Count], GetIndex(proitemset, Goto));
            }
            index++;
        }

        // 构造SLR(1)分析表
        SLRAna = new Table[proitemset.Count][];
        for (int i = 0; i < proitemset.Count; i++)
        {
            SLRAna[i] = new Table[Echar.Count + Nchar.Count];
            for (int j = 0; j < Echar.Count; j++)
            {
                SLRAna[i][j] = new Table();
                List<int> Goto = GOTO(proitemset[i], Echar[j]);
                if (Goto.Count == 0)
                    continue;
                int k = GetIndex(proitemset, Goto);
                if (isExist(Gy_obj, k))
                    SLRAna[i][j] = new Table('R', Gy_obj.IndexOf(k));
                else if (isExist(proitemset[k], '·'))
                    SLRAna[i][j] = new Table('S', k);
                else
                    SLRAna[i][j] = new Table('G', k);
            }
            for (int j = 0; j < Nchar.Count; j++)
            {
                SLRAna[i][Echar.Count + j] = new Table();
                List<int> Goto = GOTO(proitemset[i], Nchar[j]);
                if (Goto.Count == 0)
                    continue;
                int k = GetIndex(proitemset, Goto);
                if (isExist(Gy_obj, k))
                    SLRAna[i][Echar.Count + j] = new Table('R', Gy_obj.IndexOf(k));
                else if (isExist(proitemset[k], '·'))
                    SLRAna[i][Echar.Count + j] = new Table('S', k);
                else
                    SLRAna[i][Echar.Count + j] = new Table('G', k);
            }
        }

        // 填写归约状态
        for (int i = 0; i < proitemset.Count; i++)
        {
            for (int j = 0; j < proitemset[i].Count; j++)
            {
                if (SLRobjNum[proitemset[i][j]].Right.EndsWith('·'))
                {
                    Gy_obj.Add(proitemset[i][j]);
                    Gy_itemset.Add(i);
                    // 使用Follow集判断归约操作
                    foreach (char c in follow[SLRproNum[proitemset[i][j]].Left])
                    {
                        int indexC = Echar.IndexOf(c);
                        if (indexC != -1)
                        {
                            if (SLRAna[i][indexC].error)
                            {
                                SLRAna[i][indexC] = new Table('R', Gy_obj.IndexOf(proitemset[i][j]));
                            }
                            else
                            {
                                // 出现冲突
                                Success = false;
                                return;
                            }
                        }
                    }
                }
            }
        }

        // 接受状态
        if (SLRAna[1][Echar.Count - 1].error)
        {
            SLRAna[1][Echar.Count - 1] = new Table('A', 0);
        }

        Success = true;
    }

    // 其他函数
    public List<int> Closure(List<int> I)
    {
        // ...
    }

    public List<int> GOTO(List<int> I, int X)
    {
        // ...
    }

    public List<int> GOTO(List<int> I, char X)
    {
        // ...
    }

    public bool isnexist(List<SLRitemsets> I, List<int> J)
    {
        // ...
    }

    public int GetIndex(List<SLRitemsets> I, List<int> J)
    {
        // ...
    }

    public bool isExist(List<int> I, int J)
    {
        // ...
    }

    public bool isExist(List<int> I, string J)
    {
        // ...
    }

    public bool isFinalsymbol(char c)
    {
        // ...
    }

    // 计算First集和Follow集
    public void CalculateFirstAndFollow()
    {
        // ...
    }
}

注意: 上述代码中省略了部分函数的具体实现,如ClosureGOTOisnexistGetIndexisExistisFinalsymbolCalculateFirstAndFollow等,你需要根据你的具体语法规则来实现这些函数。

希望以上代码可以帮助你理解如何将LR(0)分析表的构造算法改进为SLR(1)分析表的构造算法。

总结

SLR(1)分析表是LR(0)分析表的一种改进,它通过考虑Follow集来解决LR(0)分析表中可能存在的移进/归约冲突。在实际应用中,SLR(1)分析表比LR(0)分析表应用更加广泛

LR(0)分析表构造算法到SLR(1)分析表构造算法的改进

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

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