SLR分析表构建算法及代码实现

本文介绍SLR(1)分析表的构建算法,并提供C#代码实现。

1. 算法原理

SLR(1)分析表的构建基于以下步骤:

  1. 文法预处理: 对输入的文法进行拓广,添加一个新的起始符号和产生式。2. 项目集族构造: 根据文法构造LR(0)项目集族。每个项目集包含若干个LR(0)项目,表示语法分析过程中的不同状态。3. DFA构建: 根据项目集族构造DFA(确定有限自动机)。DFA的每个状态对应一个项目集,状态之间的转换由文法符号驱动。4. Follow集计算: 计算每个非终结符的Follow集,即该非终结符后面可能出现的终结符集合。5. SLR分析表生成: 遍历DFA的每个状态和每个终结符/非终结符,根据项目集中的项目类型和Follow集信息,填写分析表中的动作和转移。

2. 代码实现 (C#)csharpclass SLR{ // ... (其他类定义)

// 分析表    public Table[][] SLRAna;

// ... (其他成员变量和方法)

// 求First集    private HashSet<char> First(string str)    {        HashSet<char> first_set = new HashSet<char>();        if (str.Length == 0) // 空串        {            first_set.Add('#');            return first_set;        }        if (isFinalsymbol(str[0])) // 终结符        {            first_set.Add(str[0]);            return first_set;        }        int i = 0;        while (i < str.Length)        {            if (isFinalsymbol(str[i])) // 终结符            {                first_set.Add(str[i]);                return first_set;            }            HashSet<char> temp_set = new HashSet<char>();            if (exist(Nchar, str[i])) // 非终结符            {                for (int j = 0; j < SLRproNum.Count; j++)                {                    if (SLRproNum[j].Left[0] == str[i])                    {                        temp_set = First(SLRproNum[j].Right);                        first_set.UnionWith(temp_set);                    }                }                if (!temp_set.Contains('ε')) // 不含ε                {                    return first_set;                }                else // 含ε                {                    first_set.Remove('ε');                    i++;                }            }        }        first_set.Add('ε'); // 全是非终结符且含ε        return first_set;    }

// 求Follow集    private HashSet<char> Follow(char ch)    {        HashSet<char> follow_set = new HashSet<char>();        if (ch == 'S') // 拓广文法        {            follow_set.Add('#');        }        for (int i = 0; i < SLRproNum.Count; i++)        {            if (SLRproNum[i].Right.Contains(ch)) // 产生式右部含有ch            {                int index = SLRproNum[i].Right.IndexOf(ch);                if (index == SLRproNum[i].Right.Length - 1) // ch在右部最后                {                    if (SLRproNum[i].Left[0] != ch) // 避免死循环                    {                        HashSet<char> temp_set = Follow(SLRproNum[i].Left[0]);                        follow_set.UnionWith(temp_set);                    }                }                else                {                    string str = SLRproNum[i].Right.Substring(index + 1, SLRproNum[i].Right.Length - index - 1);                    HashSet<char> temp_set = First(str);                    if (temp_set.Contains('ε')) // 含ε                    {                        temp_set.Remove('ε');                        follow_set.UnionWith(temp_set);                        if (SLRproNum[i].Left[0] != ch) // 避免死循环                        {                            temp_set = Follow(SLRproNum[i].Left[0]);                            follow_set.UnionWith(temp_set);                        }                    }                    else // 不含ε                    {                        follow_set.UnionWith(temp_set);                    }                }            }        }        return follow_set;    }

// 构建SLR分析表    public void SLRAnaly()    {        // 初始化分析表        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 symbol = Echar[j];

            // 查找移进项                List<int> shiftItems = new List<int>();                foreach (int itemId in proitemset[i].Container)                {                    string itemRight = SLRobjNum[itemId].Right;                    int dotIndex = itemRight.IndexOf('.');                    if (dotIndex < itemRight.Length - 1 && itemRight[dotIndex + 1] == symbol)                    {                        shiftItems.Add(itemId);                    }                }

            // 处理移进项                if (shiftItems.Count > 0)                {                    SLRitemsets gotoSet = new SLRitemsets();                    gotoSet.Container = Goto(shiftItems, symbol);                    int gotoState = isexist(gotoSet.Container);                    if (gotoState != -1)                    {                        SLRAna[i][j] = new Table('s', gotoState);                    }                }

            // 查找归约项                List<int> reduceItems = new List<int>();                foreach (int itemId in proitemset[i].Container)                {                    string itemRight = SLRobjNum[itemId].Right;                    int dotIndex = itemRight.IndexOf('.');                    if (dotIndex == itemRight.Length - 1 && SLRobjNum[itemId].Left != 'S'')                    {                        reduceItems.Add(itemId);                    }                }

            // 处理归约项                foreach (int itemId in reduceItems)                {                    char reduceSymbol = SLRobjNum[itemId].Left[0];                    HashSet<char> followSet = Follow(reduceSymbol);                    if (followSet.Contains(symbol))                    {                        int reduceProductionIndex = Array.FindIndex(SLRproNum.ToArray(), p => p.Left == reduceSymbol.ToString() && p.Right == SLRobjNum[itemId].Right.Replace('.', ''));                        SLRAna[i][j] = new Table('r', reduceProductionIndex);                    }                }            }

        // 遍历所有非终结符            for (int j = 0; j < Nchar.Count; j++)            {                char symbol = Nchar[j];

            // 查找GOTO项                List<int> gotoItems = new List<int>();                foreach (int itemId in proitemset[i].Container)                {                    string itemRight = SLRobjNum[itemId].Right;                    int dotIndex = itemRight.IndexOf('.');                    if (dotIndex < itemRight.Length - 1 && itemRight[dotIndex + 1] == symbol)                    {                        gotoItems.Add(itemId);                    }                }

            // 处理GOTO项                if (gotoItems.Count > 0)                {                    SLRitemsets gotoSet = new SLRitemsets();                    gotoSet.Container = Goto(gotoItems, symbol);                    int gotoState = isexist(gotoSet.Container);                    if (gotoState != -1)                    {                        SLRAna[i][j + Echar.Count] = new Table('g', gotoState);                    }                }            }        }

    // 处理接受状态        int acceptState = isexist(new List<int>() { 1 });        if (acceptState != -1)        {            SLRAna[acceptState][Echar.IndexOf('#')] = new Table('a', 0);        }    }

// ... (其他方法

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

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