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

    //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 Table[][] GET_ANA()
    {
        SLRAnaly();
        RStr_ANA += '\r\nSLR1分析表:\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 == 0 && j == Echar.Count - 1)
                {
                    RStr_ANA += 'ACC' + '    ';
                }
                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()
    {
        //构造First集
        foreach (char c in Nchar)
        {
            first.Add(c, new HashSet<char>());
        }
        foreach (char c in Echar)
        {
            first.Add(c, new HashSet<char>() { c });
        }
        bool changed = true;
        while (changed)
        {
            changed = false;
            foreach (SLRNode node in SLRproNum)
            {
                int oldCount = first[node.Left].Count;
                if (node.Right == 'ε')
                {
                    first[node.Left].Add('ε');
                }
                else
                {
                    foreach (char c in node.Right)
                    {
                        if (first.ContainsKey(c))
                        {
                            first[node.Left].UnionWith(first[c]);
                            if (!first[c].Contains('ε'))
                            {
                                break;
                            }
                        }
                        else
                        {
                            first[node.Left].Add(c);
                            break;
                        }
                    }
                }
                if (first[node.Left].Count > oldCount)
                {
                    changed = true;
                }
            }
        }

        //构造Follow集
        foreach (char c in Nchar)
        {
            follow.Add(c, new HashSet<char>());
        }
        follow[SLRproNum[0].Left].Add('#');
        changed = true;
        while (changed)
        {
            changed = 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>();
                        if (i == node.Right.Length - 1)
                        {
                            temp.UnionWith(follow[node.Left]);
                        }
                        else
                        {
                            for (int j = i + 1; j < node.Right.Length; j++)
                            {
                                if (first.ContainsKey(node.Right[j]))
                                {
                                    temp.UnionWith(first[node.Right[j]]);
                                    if (!first[node.Right[j]].Contains('ε'))
                                    {
                                        break;
                                    }
                                }
                                else
                                {
                                    temp.Add(node.Right[j]);
                                    break;
                                }
                            }
                            if (temp.Contains('ε'))
                            {
                                temp.Remove('ε');
                                temp.UnionWith(follow[node.Left]);
                            }
                        }
                        int oldCount = follow[node.Right[i]].Count;
                        follow[node.Right[i]].UnionWith(temp);
                        if (follow[node.Right[i]].Count > oldCount)
                        {
                            changed = true;
                        }
                    }
                }
            }
        }

        //构造项目集
        SLRobjNum.Add(new SLRNode(SLRproNum[0].Left, '.' + SLRproNum[0].Right));
        proitemset.Add(new SLRitemsets() { Container = new List<int>() { 0 }, LookAhead = new HashSet<char>() { '#' } });
        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++)
                {
                    HashSet<char> lookAhead = new HashSet<char>();
                    foreach (int index in proitemset[i].Container)
                    {
                        SLRNode node = SLRobjNum[index];
                        if (node.Right.IndexOf('.') < node.Right.Length - 1 && node.Right[node.Right.IndexOf('.') + 1] == Echar[j])
                        {
                            lookAhead.Add('#');
                        }
                        if (node.Right.IndexOf('.') < node.Right.Length - 1 && Nchar.Contains(node.Right[node.Right.IndexOf('.') + 1]))
                        {
                            foreach (char c in follow[node.Right[node.Right.IndexOf('.') + 1]])
                            {
                                lookAhead.Add(c);
                            }
                        }
                    }
                    HashSet<int> temp = Goto(proitemset[i].Container, Echar[j]);
                    if (temp.Count > 0)
                    {
                        for (int k = 0; k < proitemset.Count; k++)
                        {
                            if (proitemset[k].Container.Count == temp.Count && proitemset[k].Container.All(temp.Contains))
                            {
                                proitemset[i].LookAhead.UnionWith(lookAhead);
                                dfa[Pindex++] = new DFA(i, Echar[j], k, lookAhead);
                                flag = true;
                                break;
                            }
                        }
                        if (!flag)
                        {
                            proitemset.Add(new SLRitemsets() { Container = temp, LookAhead = lookAhead });
                            dfa[Pindex++] = new DFA(i, Echar[j], proitemset.Count - 1, lookAhead);
                            flag = true;
                        }
                    }
                }
            }
        }

        //构造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 < dfa.Length; i++)
        {
            if (dfa[i].symbol != 'ε')
            {
                if (Echar.Contains(dfa[i].symbol))
                {
                    SLRAna[dfa[i].from][Echar.IndexOf(dfa[i].symbol)] = new Table('S', dfa[i].to);
                }
                else
                {
                    SLRAna[dfa[i].from][Echar.Count + Nchar.IndexOf(dfa[i].symbol)] = new Table('S', dfa[i].to);
                }
            }
            else
            {
                for (int j = 0; j < proitemset[dfa[i].from].LookAhead.Count; j++)
                {
                    if (Echar.Contains(proitemset[dfa[i].from].LookAhead.ElementAt(j)))
                    {
                        SLRAna[dfa[i].from][Echar.IndexOf(proitemset[dfa[i].from].LookAhead.ElementAt(j))] = new Table('R', proitemset[dfa[i].from].Container[0]);
                    }
                    else
                    {
                        SLRAna[dfa[i].from][Echar.Count + Nchar.IndexOf(proitemset[dfa[i].from].LookAhead.ElementAt(j))] = new Table('R', proitemset[dfa[i].from].Container[0]);
                    }
                }
            }
        }

        for (int i = 0; i < proitemset.Count; i++)
        {
            for (int j = 0; j < SLRproNum.Count; j++)
            {
                if (SLRobjNum[proitemset[i].Container[0]].Right.IndexOf('.') == SLRobjNum[proitemset[i].Container[0]].Right.Length - 1 && SLRobjNum[proitemset[i].Container[0]].Left == SLRproNum[j].Left)
                {
                    for (int k = 0; k < proitemset[i].LookAhead.Count; k++)
                    {
                        if (Echar.Contains(proitemset[i].LookAhead.ElementAt(k)))
                        {
                            SLRAna[i][Echar.IndexOf(proitemset[i].LookAhead.ElementAt(k))] = new Table('R', j + 1);
                        }
                        else
                        {
                            SLRAna[i][Echar.Count + Nchar.IndexOf(proitemset[i].LookAhead.ElementAt(k))] = new Table('R', j + 1);
                        }
                    }
                }
            }
        }
    }

    public HashSet<int> Goto(List<int> I, char symbol)
    {
        HashSet<int> res = new HashSet<int>();
        for (int i = 0; i < I.Count; i++)
        {
            SLRNode node = SLRobjNum[I[i]];
            if (node.Right.IndexOf('.') < node.Right.Length - 1 && node.Right[node.Right.IndexOf('.') + 1] == symbol)
            {
                res.Add(SLRobjNum.IndexOf(new SLRNode(node.Left, node.Right.Substring(0, node.Right.IndexOf('.')) + symbol + '.' + node.Right.Substring(node.Right.IndexOf('.') + 2))));
            }
        }
        return res;
    }
    
    //判断项目是否存在于项目集合中
    public bool isnexist(List<int> I, int j)
    {
        if (I.Contains(j))
            return true;
        else
            return false;
    }

    //判断是否是终结符
    public bool isFinalsymbol(char ch)
    {
        if (Echar.Contains(ch))
            return true;
        else
            return false;
    }
SLR1 分析器实现 -  SLR1 文法分析表构造

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

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