SLR分析表构建算法及代码实现
SLR分析表构建算法及代码实现
本文介绍SLR(1)分析表的构建算法,并提供C#代码实现。
1. 算法原理
SLR(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 著作权归作者所有。请勿转载和采集!