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);
            //记录项目在项目集合中的序号
        }

        //DFA结点
        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;//是否为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 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 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>> follow = new Dictionary<char, HashSet<char>>();//非终结符的Follow集

        public string RStr = '';
        public string RStr_obitemset = '';//输出返回
        public string RStr_DFA = '';
        public string RStr_ANA = '';
        public Table[][] GET_ANA()
        {
            SLR0Analy();
            return SLRAna;
        }
        public void SLRAnaly()
        {
            //构造SLR分析表
            //初始化分析表
            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 < proitemset.Count; i++)
            {
                for (int j = 0; j < Echar.Count; j++)
                {
                    char ch = Echar[j];
                    List<int> Goto = GOTO(proitemset[i].Container, ch);
                    if (Goto.Count > 0)
                    {
                        int k = getitemset(Goto);
                        if (isFinalsymbol(ch))
                            SLRAna[i][j] = new Table('S', k);
                        else
                            SLRAna[i][j + Echar.Count] = new Table('G', k);
                    }
                }
                for (int j = 0; j < proitemset[i].Container.Count; j++)
                {
                    int k = proitemset[i].Container[j];
                    if (SLRobjNum[k].Right.IndexOf('.') == SLRobjNum[k].Right.Length - 1)
                    {
                        if (SLRobjNum[k].Left == 'S'')
                            SLRAna[i][Echar.Count - 1] = new Table('A', 0);
                        else
                        {
                            HashSet<char> followset = follow[SLRobjNum[k].Left[0]];
                            foreach (char ch in followset)
                            {
                                int index = Echar.IndexOf(ch);
                                if (index != -1)
                                    SLRAna[i][index] = new Table('R', k);
                            }
                        }
                    }
                }
            }
        }

        public void SLR0Analy()
        {
            //构造LR0项目集
            LR0itemset();
            //构造DFA
            LR0DFA();
            //构造SLR分析表
            SLRAnaly();
        }

        //获取非终结符ch的FIRST集
        public HashSet<char> first(char ch)
        {
            HashSet<char> set = new HashSet<char>();
            for (int i = 0; i < SLRproNum.Count; i++)
            {
                if (SLRproNum[i].Left[0] == ch)
                {
                    if (isFinalsymbol(SLRproNum[i].Right[0]))
                        set.Add(SLRproNum[i].Right[0]);
                    else
                    {
                        HashSet<char> temp = first(SLRproNum[i].Right[0]);
                        foreach (char c in temp)
                        {
                            set.Add(c);
                        }
                    }
                }
            }
            return set;
        }

        //获取非终结符ch的FOLLOW集
        public HashSet<char> followset(char ch)
        {
            HashSet<char> set = new HashSet<char>();
            if (ch == 'S')
                set.Add('#');
            for (int i = 0; i < SLRproNum.Count; i++)
            {
                for (int j = 0; j < SLRproNum[i].Right.Length; j++)
                {
                    if (SLRproNum[i].Right[j] == ch)
                    {
                        if (j == SLRproNum[i].Right.Length - 1)
                        {
                            if (SLRproNum[i].Left[0] != ch)
                            {
                                HashSet<char> temp = followset(SLRproNum[i].Left[0]);
                                foreach (char c in temp)
                                {
                                    set.Add(c);
                                }
                            }
                        }
                        else
                        {
                            if (isFinalsymbol(SLRproNum[i].Right[j + 1]))
                                set.Add(SLRproNum[i].Right[j + 1]);
                            else
                            {
                                HashSet<char> temp = first(SLRproNum[i].Right[j + 1]);
                                foreach (char c in temp)
                                {
                                    set.Add(c);
                                }
                                if (temp.Contains('ε'))
                                {
                                    if (SLRproNum[i].Left[0] != ch)
                                    {
                                        HashSet<char> temp2 = followset(SLRproNum[i].Left[0]);
                                        foreach (char c in temp2)
                                        {
                                            set.Add(c);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return set;
        }

        //构造SLR分析表
        public void SLRAnaly()
        {
            //初始化follow集
            foreach (char ch in Nchar)
            {
                follow[ch] = new HashSet<char>();
            }
            follow['S'] = new HashSet<char>();
            follow['S'].Add('#');
            for (int i = 0; i < SLRproNum.Count; i++)
            {
                for (int j = 0; j < SLRproNum[i].Right.Length; j++)
                {
                    if (isNonfinalsymbol(SLRproNum[i].Right[j]))
                    {
                        if (j == SLRproNum[i].Right.Length - 1)
                        {
                            HashSet<char> temp = followset(SLRproNum[i].Left[0]);
                            foreach (char ch in temp)
                            {
                                follow[SLRproNum[i].Right[j]].Add(ch);
                            }
                        }
                        else
                        {
                            HashSet<char> temp = first(SLRproNum[i].Right[j + 1]);
                            foreach (char ch in temp)
                            {
                                if (ch != 'ε')
                                    follow[SLRproNum[i].Right[j]].Add(ch);
                            }
                            if (temp.Contains('ε'))
                            {
                                HashSet<char> temp2 = followset(SLRproNum[i].Left[0]);
                                foreach (char ch in temp2)
                                {
                                    follow[SLRproNum[i].Right[j]].Add(ch);
                                }
                            }
                        }
                    }
                }
            }
            //构造SLR分析表
            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 < proitemset.Count; i++)
            {
                for (int j = 0; j < Echar.Count; j++)
                {
                    char ch = Echar[j];
                    List<int> Goto = GOTO(proitemset[i].Container, ch);
                    if (Goto.Count > 0)
                    {
                        int k = getitemset(Goto);
                        if (isFinalsymbol(ch))
                            SLRAna[i][j] = new Table('S', k);
                        else
                            SLRAna[i][j + Echar.Count] = new Table('G', k);
                    }
                }
                for (int j = 0; j < proitemset[i].Container.Count; j++)
                {
                    int k = proitemset[i].Container[j];
                    if (SLRobjNum[k].Right.IndexOf('.') == SLRobjNum[k].Right.Length - 1)
                    {
                        if (SLRobjNum[k].Left == 'S'')
                            SLRAna[i][Echar.Count - 1] = new Table('A', 0);
                        else
                        {
                            HashSet<char> followset = follow[SLRobjNum[k].Left[0]];
                            foreach (char ch in followset)
                            {
                                int index = Echar.IndexOf(ch);
                                if (index != -1)
                                    SLRAna[i][index] = new Table('R', k);
                            }
                        }
                    }
                }
            }
        }

上述代码中,SLRAnaly() 函数是核心构造 SLR 分析表的函数,其中 follow 字典用于存储非终结符的 FOLLOW 集,在该函数中,我们会利用 follow 字典来填充分析表中的归约项。

此外,需要补充 LR0itemset()LR0DFA()GOTO()getitemset()isFinalsymbol()isNonfinalsymbol() 等辅助函数,这些函数用于构造 LR0 项目集,构建 DFA,以及判断终结符和非终结符等操作。

以下给出 first()followset() 函数的实现代码:

// 获取非终结符ch的FIRST集
        public HashSet<char> first(char ch)
        {
            HashSet<char> set = new HashSet<char>();
            for (int i = 0; i < SLRproNum.Count; i++)
            {
                if (SLRproNum[i].Left[0] == ch)
                {
                    if (isFinalsymbol(SLRproNum[i].Right[0]))
                        set.Add(SLRproNum[i].Right[0]);
                    else
                    {
                        HashSet<char> temp = first(SLRproNum[i].Right[0]);
                        foreach (char c in temp)
                        {
                            set.Add(c);
                        }
                    }
                }
            }
            return set;
        }

        // 获取非终结符ch的FOLLOW集
        public HashSet<char> followset(char ch)
        {
            HashSet<char> set = new HashSet<char>();
            if (ch == 'S')
                set.Add('#');
            for (int i = 0; i < SLRproNum.Count; i++)
            {
                for (int j = 0; j < SLRproNum[i].Right.Length; j++)
                {
                    if (SLRproNum[i].Right[j] == ch)
                    {
                        if (j == SLRproNum[i].Right.Length - 1)
                        {
                            if (SLRproNum[i].Left[0] != ch)
                            {
                                HashSet<char> temp = followset(SLRproNum[i].Left[0]);
                                foreach (char c in temp)
                                {
                                    set.Add(c);
                                }
                            }
                        }
                        else
                        {
                            if (isFinalsymbol(SLRproNum[i].Right[j + 1]))
                                set.Add(SLRproNum[i].Right[j + 1]);
                            else
                            {
                                HashSet<char> temp = first(SLRproNum[i].Right[j + 1]);
                                foreach (char c in temp)
                                {
                                    set.Add(c);
                                }
                                if (temp.Contains('ε'))
                                {
                                    if (SLRproNum[i].Left[0] != ch)
                                    {
                                        HashSet<char> temp2 = followset(SLRproNum[i].Left[0]);
                                        foreach (char c in temp2)
                                        {
                                            set.Add(c);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return set;
        }

通过这些代码,您可以将 LR0 分析器改造为 SLR1 分析器,并实现 SLR1 分析表的构造。请注意,您需要根据具体的语法规则和产生式列表来完善代码,并确保所有辅助函数的正确实现。

SLR1 语法分析器实现:从 LR0 到 SLR1 分析表构造

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

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