public class SLRNode
        {
            public string Left;
            public string Right;
            public HashSet<char> First;
            public HashSet<char> Follow;
            public SLRNode(string Left, string Right)
            {
                this.Left = Left;
                this.Right = Right;
                First = new HashSet<char>();
                Follow = new HashSet<char>();
            }
        }
        //项目集类
        public class SLRitemsets
        {
            public List<int> Container
                = new List<int>(100);
            //记录项目在项目集合中的序号
            public HashSet<char> LookAhead
                = new HashSet<char>();
            //记录展望符
        }

        //DFA结点
        public struct DFA
        {
            public int from;
            public char symbol;
            public int to;
            public HashSet<char> LookAhead;
            public DFA(int from, char symbol, int to, HashSet<char> LookAhead)
            {
                this.from = from;
                this.symbol = symbol;
                this.to = to;
                this.LookAhead = LookAhead;
            }
        }

        //分析表 结点
        public class Table
        {
            public bool error;//是否为ERROR
            public char type;//结点类型
            public int id;//数值
            public Table()
            {
                this.error = true;
            }
            public Table(char type, int id)
            {
                this.type = type;
                this.id = id;
                this.error = false;
            }
        }

        public DFA[] dfa = new DFA[100];
        public int Pindex = 0; //dfa数组指针
        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>>();//非终结符的First集
        Dictionary<char, HashSet<char>> follow = new Dictionary<char, HashSet<char>>();//非终结符的Follow集

        public string RStr = '';
        public string RStr_obitemset = '';//输出返回
        public string RStr_DFA = '';
        public string RStr_ANA = '';

        public void ComputeFirst()
        {
            //初始化 First 集
            foreach (char c in Nchar)
            {
                first.Add(c, new HashSet<char>());
            }
            foreach (char c in Echar)
            {
                first.Add(c, new HashSet<char>() { c });
            }
            //计算 First 集
            bool flag = true;
            while (flag)
            {
                flag = false;
                foreach (SLRNode node in SLRproNum)
                {
                    HashSet<char> temp = new HashSet<char>();
                    bool canEpsilon = true;
                    foreach (char c in node.Right)
                    {
                        if (Echar.Contains(c))
                        {
                            temp.UnionWith(first[c]);
                            if (!first[c].Contains('ε'))
                            {
                                canEpsilon = false;
                                break;
                            }
                        }
                        else
                        {
                            canEpsilon = false;
                            temp.UnionWith(first[c]);
                            break;
                        }
                    }
                    if (canEpsilon)
                    {
                        temp.Add('ε');
                    }
                    if (!temp.SetEquals(first[node.Left]))
                    {
                        first[node.Left].UnionWith(temp);
                        flag = true;
                    }
                }
            }
        }

        public void ComputeFollow()
        {
            //初始化 Follow 集
            foreach (char c in Nchar)
            {
                follow.Add(c, new HashSet<char>());
            }
            follow[SLRproNum[0].Left].Add('#');
            //计算 Follow 集
            bool flag = true;
            while (flag)
            {
                flag = false;
                foreach (SLRNode node in SLRproNum)
                {
                    for (int i = 0; i < node.Right.Length; i++)
                    {
                        if (Nchar.Contains(node.Right[i]))
                        {
                            HashSet<char> temp = new HashSet<char>();
                            bool canEpsilon = true;
                            for (int j = i + 1; j < node.Right.Length; j++)
                            {
                                if (Echar.Contains(node.Right[j]))
                                {
                                    temp.UnionWith(first[node.Right[j]]);
                                    if (!first[node.Right[j]].Contains('ε'))
                                    {
                                        canEpsilon = false;
                                        break;
                                    }
                                }
                                else
                                {
                                    canEpsilon = false;
                                    temp.UnionWith(first[node.Right[j]]);
                                    break;
                                }
                            }
                            if (canEpsilon)
                            {
                                temp.UnionWith(follow[node.Left]);
                            }
                            if (!temp.SetEquals(follow[node.Right[i]]))
                            {
                                follow[node.Right[i]].UnionWith(temp);
                                flag = true;
                            }
                        }
                    }
                    if (node.Right.EndsWith(Nchar.ToString()))
                    {
                        if (!follow[node.Left].SetEquals(follow[node.Right[node.Right.Length - 1]]))
                        {
                            follow[node.Right[node.Right.Length - 1]].UnionWith(follow[node.Left]);
                            flag = true;
                        }
                    }
                }
            }
        }

        public void CreateItemsets()
        {
            //初始化第一个项目集
            SLRitemsets itemset0 = new SLRitemsets();
            itemset0.Container.Add(0);
            itemset0.LookAhead.Add('#');
            itemset0 = Closure(itemset0);
            proitemset.Add(itemset0);
            //构造所有项目集
            bool flag = true;
            while (flag)
            {
                flag = false;
                for (int i = 0; i < proitemset.Count; i++)
                {
                    for (int j = 0; j < Echar.Count + Nchar.Count; j++)
                    {
                        char symbol = j < Echar.Count ? Echar[j] : Nchar[j - Echar.Count];
                        HashSet<char> lookAhead = new HashSet<char>();
                        foreach (int index in proitemset[i].Container)
                        {
                            if (SLRobjNum[index].Right.Contains('.') && SLRobjNum[index].Right.IndexOf('.') < SLRobjNum[index].Right.Length - 1 && SLRobjNum[index].Right[SLRobjNum[index].Right.IndexOf('.') + 1] == symbol)
                            {
                                if (SLRobjNum[index].Right.Length - 1 == SLRobjNum[index].Right.IndexOf('.') + 1)
                                {
                                    lookAhead.UnionWith(proitemset[i].LookAhead);
                                }
                                else
                                {
                                    bool canEpsilon = true;
                                    for (int k = SLRobjNum[index].Right.IndexOf('.') + 2; k < SLRobjNum[index].Right.Length; k++)
                                    {
                                        if (Echar.Contains(SLRobjNum[index].Right[k]))
                                        {
                                            lookAhead.UnionWith(first[SLRobjNum[index].Right[k]]);
                                            if (!first[SLRobjNum[index].Right[k]].Contains('ε'))
                                            {
                                                canEpsilon = false;
                                                break;
                                            }
                                        }
                                        else
                                        {
                                            canEpsilon = false;
                                            lookAhead.UnionWith(first[SLRobjNum[index].Right[k]]);
                                            break;
                                        }
                                    }
                                    if (canEpsilon)
                                    {
                                        lookAhead.UnionWith(proitemset[i].LookAhead);
                                    }
                                }
                            }
                        }
                        if (lookAhead.Count > 0)
                        {
                            SLRitemsets newItemset = new SLRitemsets();
                            foreach (int index in proitemset[i].Container)
                            {
                                if (SLRobjNum[index].Right.Contains('.') && SLRobjNum[index].Right.IndexOf('.') < SLRobjNum[index].Right.Length - 1 && SLRobjNum[index].Right[SLRobjNum[index].Right.IndexOf('.') + 1] == symbol)
                                {
                                    SLRNode newNode = new SLRNode(SLRobjNum[index].Left, SLRobjNum[index].Right.Insert(SLRobjNum[index].Right.IndexOf('.') + 2, '$'));
                                    if (!SLRobjNum.Contains(newNode))
                                    {
                                        SLRobjNum.Add(newNode);
                                        newItemset.Container.Add(SLRobjNum.Count - 1);
                                        newItemset.LookAhead.Add(symbol);
                                    }
                                    else
                                    {
                                        int index2 = SLRobjNum.IndexOf(newNode);
                                        newItemset.Container.Add(index2);
                                        newItemset.LookAhead.Add(symbol);
                                    }
                                }
                            }
                            newItemset = Closure(newItemset);
                            if (!proitemset.Contains(newItemset))
                            {
                                proitemset.Add(newItemset);
                                flag = true;
                            }
                            dfa[Pindex++] = new DFA(i, symbol, proitemset.IndexOf(newItemset), lookAhead);
                        }
                    }
                }
            }
        }

        public void CreateDFA()
        {
            RStr_DFA += '
SLR1分析器DFA:
';
            RStr_DFA += '状态|';
            foreach (char c in Echar)
            {
                RStr_DFA += c + '|';
            }
            foreach (char c in Nchar)
            {
                RStr_DFA += c + '|';
            }
            RStr_DFA += '
';
            for (int i = 0; i < Pindex; i++)
            {
                RStr_DFA += i + '    |';
                for (int j = 0; j < Echar.Count + Nchar.Count; j++)
                {
                    if (dfa[i].to == -1)
                    {
                        RStr_DFA += '     |';
                    }
                    else
                    {
                        if (dfa[i].symbol == (j < Echar.Count ? Echar[j] : Nchar[j - Echar.Count]))
                        {
                            RStr_DFA += dfa[i].to + ',' + string.Join('', dfa[i].LookAhead) + '|';
                        }
                        else
                        {
                            RStr_DFA += '     |';
                        }
                    }
                }
                RStr_DFA += '
';
            }
        }

        public void CreateSLRTable()
        {
            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 + Nchar.Count; j++)
                {
                    SLRAna[i][j] = new Table();
                }
            }
            for (int i = 0; i < Pindex; i++)
            {
                if (dfa[i].symbol == '#' && dfa[i].to != -1)
                {
                    foreach (int index in proitemset[dfa[i].to].Container)
                    {
                        if (SLRobjNum[index].Right.EndsWith('.'))
                        {
                            SLRAna[dfa[i].from][Echar.Count + Nchar.Count - 1] = new Table('A', index);
                            break;
                        }
                    }
                }
                for (int j = 0; j < Echar.Count + Nchar.Count; j++)
                {
                    if (dfa[i].symbol == (j < Echar.Count ? Echar[j] : Nchar[j - Echar.Count]) && dfa[i].to != -1)
                    {
                        SLRAna[dfa[i].from][j] = new Table('S', dfa[i].to);
                    }
                }
                for (int k = 0; k < proitemset.Count; k++)
                {
                    foreach (int index in proitemset[k].Container)
                    {
                        if (SLRobjNum[index].Right.EndsWith('.'))
                        {
                            foreach (char c in proitemset[k].LookAhead)
                            {
                                if (c != '#' && c != 'ε')
                                {
                                    int index2 = Echar.IndexOf(c);
                                    SLRAna[k][index2] = new Table('R', index);
                                }
                            }
                        }
                    }
                }
            }
            RStr_ANA += '
SLR1分析表:
    ';
            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 += '
';
            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 += '
';
            }
        }

        public SLRitemsets Closure(SLRitemsets I)
        {
            for (int index = 0; index < I.Container.Count; index++)//遍历该集合中的所有序号 初始序号就是拓广文法的0 下面的ADD步骤中会扩大他的内容
                for (int i = 0; i < SLRobjNum[I.Container[index]].Right.Length - 1; i++)//遍历第index序号项目右侧字符串 找到.A结构
                {
                    if (SLRobjNum[I.Container[index]].Right[i] == '.' && isFinalsymbol(SLRobjNum[I.Container[index]].Right[i + 1]))
                    {
                        for (int j = 0; j < SLRobjNum.Count; j++)//遍历所有项目,找到以A开头的.a
                        {
                            if (isnexist(I.Container, j))
                                continue;
                            if (SLRobjNum[j].Left == SLRobjNum[I.Container[index]].Right[i + 1].ToString() && SLRobjNum[j].Right[0] == '.')
                                I.Container.Add(j);//ADD:在项目集(序号集合)中加入新成员
                        }
                    }
                }
            return I;

        }
        //判断符号是否为终结符
        public bool isFinalsymbol(char c)
        {
            return Echar.Contains(c);
        }
        //判断项目序号是否在项目集中
        public bool isnexist(List<int> I, int index)
        {
            return I.Contains(index);
        }

解释

1. ComputeFirst() 函数

  • 功能: 计算每个非终结符的 First 集。
  • 步骤:
    • 初始化 First 集: 为每个非终结符和终结符创建空的 First 集,终结符的 First 集包含自身。
    • 迭代计算: 循环遍历每个产生式,从产生式的右部第一个符号开始,将该符号的 First 集加入到产生式左部的 First 集中。
    • 处理 ε: 如果产生式右部的 First 集包含 ε,则将 ε 加入到产生式左部的 First 集中。
    • 重复循环: 直到所有 First 集不再发生改变,循环结束。

2. ComputeFollow() 函数

  • 功能: 计算每个非终结符的 Follow 集。
  • 步骤:
    • 初始化 Follow 集: 为每个非终结符创建空的 Follow 集。
    • 初始化开始符号的 Follow 集: 将 # 加入到开始符号的 Follow 集中。
    • 迭代计算: 循环遍历每个产生式,对于每个非终结符 A,如果 A 出现于产生式右部,且 A 后面还有其他符号,则将该符号的 First 集加入到 A 的 Follow 集中。如果 A 后面没有其他符号,或者 A 后面的符号的 First 集包含 ε,则将产生式左部的 Follow 集加入到 A 的 Follow 集中。
    • 重复循环: 直到所有 Follow 集不再发生改变,循环结束。

3. CreateItemsets() 函数

  • 功能: 构造 SLR1 项目集族。
  • 步骤:
    • 初始化第一个项目集: 将拓广文法的第一个产生式的第一个项目加入到第一个项目集中。
    • 迭代构造: 循环遍历每个项目集,对于每个项目,如果该项目的点号 '.' 不在最右边,则将该项目移点后产生的项目加入到新的项目集中,并且将新的项目集加入到项目集族中。
    • 计算 LookAhead 集: 对于每个项目集中的项目,如果该项目点的右边有符号,则将该符号的 First 集加入到 LookAhead 集中,否则将该项目集的 LookAhead 集加入到 LookAhead 集中。
    • 重复循环: 直到所有项目集不再发生改变,循环结束。

4. CreateDFA() 函数

  • 功能: 构造 SLR1 分析器的 DFA。
  • 步骤:
    • 初始化 DFA: 根据项目集族,初始化 DFA 的状态和转移。
    • 迭代构造: 循环遍历每个状态,对于每个状态,根据状态的 LookAhead 集,构造状态之间的转移。
    • 输出 DFA: 输出 DFA 的状态和转移信息。

5. CreateSLRTable() 函数

  • 功能: 构造 SLR1 分析表。
  • 步骤:
    • 初始化分析表: 为每个状态和每个符号创建一个空的分析表项。
    • 填充分析表: 根据 DFA 的转移,填充分析表中的项目,包括移进 (S)、归约 (R) 和接受 (A) 操作。
    • 输出分析表: 输出 SLR1 分析表的内容。

代码示例

以下是一个简单的 SLR1 分析器构造的示例代码:

public class SLRAnalyzer
{
    // ... (上述代码)

    public static void Main(string[] args)
    {
        // 定义产生式
        List<SLRNode> productions = new List<SLRNode>
        {
            new SLRNode('E', 'E+T'),
            new SLRNode('E', 'T'),
            new SLRNode('T', 'T*F'),
            new SLRNode('T', 'F'),
            new SLRNode('F', '(E)'),
            new SLRNode('F', 'd')
        };

        // 初始化非终结符和终结符集合
        List<char> nonTerminals = new List<char>() { 'E', 'T', 'F' };
        List<char> terminals = new List<char>() { '+', '*', '(', ')', 'd', '#' };

        // 创建 SLR 分析器
        SLRAnalyzer analyzer = new SLRAnalyzer(productions, nonTerminals, terminals);

        // 构造分析表
        analyzer.CreateSLRTable();

        // 输出分析表
        Console.WriteLine(analyzer.RStr_ANA);
    }
}

总结

本文提供了完整的 SLR1 分析器构造代码,并对代码中的各个函数进行了详细的解释,希望可以帮助你理解 SLR1 分析器的实现原理。在实际应用中,你可以根据具体的文法和需求,调整代码,构造出合适的 SLR1 分析器。

SLR1 分析器构造:完整代码示例和解释

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

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