class SLR
{
    //产生式结点类
    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 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 void Buildprod(string str)//创建项目集
    {
        SLRNode SLr;
        int i = 0;
        string left = '';
        string right = '';
        left += 'S'';
        right += str[0];
        SLr = new SLRNode(left, right);//拓广文法开始
        SLRproNum.Add(SLr);
        while (i < str.Length)
        {
            left = right = '';//还原
            int j = i;
            while (i < str.Length && str[i] != '\r' && str[i] != '\n')//换行符‘\r\n’
            {
                if (str[i] == ' ')
                {
                    i++;
                    continue;
                }
                if (str[i] == '|')                 //  遇到'|'可构造一条产生式
                {
                    SLr = new SLRNode(left, right);
                    SLRproNum.Add(SLr);
                    right = '';                    //产生式左边相同 右边重新积累
                    i++;                           //跳过'|'
                    continue;
                }
                if ((i - j) == 0)
                {
                    if (!exist(Nchar, str[i]))//如果非终结符集合中不存在str[i],加入Nchar  产生式左边 只有非终结符 不必判断终结符
                        Nchar.Add(str[i]);
                    left += str[i++];
                }
                else if (i - j <= 2)
                    i++;
                else
                {
                    if (isFinalsymbol(str[i]) && !exist(Nchar, str[i]))//如果非终结符集合中不存在str[i],加入Nchar  isfinalsymbol 非终结符返回T 终结符返回F
                        Nchar.Add(str[i]);
                    else if (!isFinalsymbol(str[i]) && !exist(Echar, str[i]))//产生式右边 需要判断终结符
                        Echar.Add(str[i]);
                    right += str[i++];
                }


            }//while

            i++;//跳过换行符
            if (left != '' && right != '')
            {
                SLr = new SLRNode(left, right);//构造每一行最后一个产生式,不存在'|'时就是该行产生式本身
                SLRproNum.Add(SLr);
            }
        }//while
        Echar.Add('#');

        //构造项目 对产生式集合LRproNum中的所有产生式都循环插'.'
        SLRNode Lobj;
        for (i = 0; i < SLRproNum.Count; i++)
        {
            left = '';
            right = '';
            for (int j = 0; j <= SLRproNum[i].Right.Length; j++)//j可以等于length  项目共length+1个
            {
                left = SLRproNum[i].Left;
                right = CreObj(SLRproNum[i].Right, j);//在第j个位置插入'.'
                if (j == SLRproNum[i].Right.Length && SLRobjNum.Count != 1)
                {
                    //在产生式最后的位置插入. 即为归约项目   项目集中1号位置为接受项目
                    Gy_obj.Add(SLRobjNum.Count);//归约项目在项目集中的序号 不用+1 本身就是从0开始的
                }
                Lobj = new SLRNode(left, right);
                SLRobjNum.Add(Lobj);
                left = '';//还原
                right = '';
            }
        }
        Creteitemsets();//项目集
        RStr_obitemset += '\r\n项目集构建:\r\n';
        for (int j = 0; j < proitemset.Count; j++)
        {
            RStr_obitemset += 'I' + j.ToString() + ':' + '\r\n';
            for (i = 0; i < proitemset[j].Container.Count; i++)
            {
                RStr_obitemset += SLRobjNum[proitemset[j].Container[i]].Left.ToString() + '->' + SLRobjNum[proitemset[j].Container[i]].Right.ToString() + '\r\n';
            }
        }
    }

    //求项目集
    public void Creteitemsets()
    {
        proitemset.Add(new SLRitemsets());
        proitemset[0].Container.Add(0);//初始项目集合  只含接受项目
        proitemset[0] = Closure(proitemset[0]);
        int index = 1;
        while (index < proitemset.Count)
        {
            for (int i = 0; i < Echar.Count; i++)//遍历终结符
            {
                for (int j = 0; j < proitemset.Count; j++)//遍历项目集
                {
                    SLRitemsets itemset = Goto(proitemset[j], Echar[i]);//求转移
                    if (itemset.Container.Count != 0)
                    {
                        if (!exist(proitemset, itemset))
                        {
                            proitemset.Add(itemset);//添加新的项目集
                            dfa[Pindex] = new DFA(j, Echar[i], proitemset.Count - 1);//加入DFA
                            Pindex++;
                        }
                        else
                        {
                            dfa[Pindex] = new DFA(j, Echar[i], proitemset.IndexOf(itemset));
                            Pindex++;
                        }
                    }
                }
            }
            index++;
        }
        BuildAnaTable();
    }

    public void BuildAnaTable()//构建分析表
    {
        SLRAna = new Table[proitemset.Count][];
        for (int i = 0; i < proitemset.Count; i++)
        {
            SLRAna[i] = new Table[Echar.Count + Nchar.Count + 1];
            for (int j = 0; j < SLRAna[i].Length; j++)
            {
                SLRAna[i][j] = new Table();
            }
        }
        for (int i = 0; i < Pindex; i++)//DFA数组指针
        {
            if (Echar.Contains(dfa[i].symbol))//是终结符
            {
                SLRAna[dfa[i].from][Echar.IndexOf(dfa[i].symbol)] = new Table('S', dfa[i].to);//S是移进
            }
            else//是非终结符
            {
                SLRAna[dfa[i].from][Echar.Count + Nchar.IndexOf(dfa[i].symbol)] = new Table('G', dfa[i].to);//G是转移
            }
        }
        for (int i = 0; i < Gy_itemset.Count; i++)
        {
            for (int j = 0; j < Gy_obj.Count; j++)
            {
                if (proitemset[Gy_itemset[i]].Container.Contains(Gy_obj[j]))//找到含有归约项目 的项目集   归约项目在项目集合中的序号
                {
                    for (int k = 0; k < Echar.Count; k++)
                    {
                        if (follow[SLRobjNum[Gy_obj[j]].Left[0]].Contains(Echar[k]))//求FOLLOW集
                        {
                            SLRAna[Gy_itemset[i]][k] = new Table('R', j + 1);//R是归约
                        }
                    }
                    SLRAna[Gy_itemset[i]][Echar.Count + Nchar.Count] = new Table('R', j + 1);
                }
            }
        }

        for (int i = 0; i < proitemset.Count; i++)
        {
            for (int j = 0; j < SLRAna[i].Length; j++)
            {
                if (SLRAna[i][j].error == true)
                {
                    if (j < Echar.Count + Nchar.Count)
                        SLRAna[i][j] = new Table('E', -1);
                }
            }
        }
        if (SLRAna[0][Echar.Count + Nchar.Count].type == 'R' && SLRAna[0][Echar.Count + Nchar.Count].id == 1)
        {
            Success = true;
        }
    }

    public bool exist(List<SLRitemsets> list, SLRitemsets itemset)
    {
        for (int i = 0; i < list.Count; i++)
        {
            if (list[i].Container.Count == itemset.Container.Count)
            {
                if (list[i].Container.Except(itemset.Container).Count() == 0)
                {
                    return true;
                }
            }
        }
        return false;
    }

    //求闭包函数
    public SLRitemsets Closure(SLRitemsets itemset)
    {
        SLRitemsets newItemset = new SLRitemsets();
        newItemset.Container.AddRange(itemset.Container);
        int p = 0;
        while (p < newItemset.Container.Count)
        {
            int i = newItemset.Container[p];
            string str = SLRobjNum[i].Right;
            int j = str.IndexOf('.');
            if (j < str.Length - 1)//不是最后一位
            {
                char X = str[j + 1];
                if (exist(Nchar, X))
                {
                    foreach (var item in SLRproNum)
                    {
                        if (item.Left[0] == X)
                        {
                            SLRNode newNode = new SLRNode(item.Left, CreObj(item.Right, 0));
                            if (!exist(SLRobjNum, newNode))
                            {
                                SLRobjNum.Add(newNode);
                                newItemset.Container.Add(SLRobjNum.Count - 1);
                            }
                        }
                    }
                }
            }
            p++;
        }
        return newItemset;
    }

    //求转移函数
    public SLRitemsets Goto(SLRitemsets itemset, char ch)
    {
        SLRitemsets newItemset = new SLRitemsets();
        for (int i = 0; i < itemset.Container.Count; i++)
        {
            int index = itemset.Container[i];
            string str = SLRobjNum[index].Right;
            int j = str.IndexOf('.');
            if (j < str.Length - 1)//不是最后一位
            {
                char X = str[j + 1];
                if (X == ch)
                {
                    string left = SLRobjNum[index].Left;
                    string right = CreObj(SLRobjNum[index].Right, j + 1);
                    SLRNode newNode = new SLRNode(left, right);
                    if (!exist(SLRobjNum, newNode))
                    {
                        SLRobjNum.Add(newNode);
                    }
                    newItemset.Container.Add(SLRobjNum.IndexOf(newNode));
                }
            }
        }
        return Closure(newItemset);
    }

    //判断是否存在
    public bool exist(List<char> list, char ch)
    {
        foreach (var item in list)
        {
            if (item == ch)
                return true;
        }
        return false;
    }

    public bool exist(List<SLRNode> list, SLRNode node)
    {
        foreach (var item in list)
        {
            if (item.Left.Equals(node.Left) && item.Right.Equals(node.Right))
                return true;
        }
        return false;
    }

    //插入'.'
    public string CreObj(string str, int index)
    {
        string left = str.Substring(0, index);
        left += '.';
        string right = str.Substring(index, str.Length - index);
        return left + right;
    }

    public bool isFinalsymbol(char ch)
    {
        return !char.IsLetter(ch);
    }
}
SLR 文法分析器:项目集构建与分析表生成

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

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