LR(0)和SLR(1)语法分析器实现与代码解析
LR(0)和SLR(1)语法分析器实现与代码解析
概述
LR(0)和SLR(1)是两种自底向上的语法分析技术,常用于编译器构建语法分析器。LR(0)分析器简单易懂,但分析能力有限;SLR(1)分析器在LR(0)的基础上进行了改进,分析能力更强,能够处理更多语法。
LR(0)分析器
LR(0)分析器使用一个栈和一个分析表进行语法分析。分析表包含两部分:ACTION表和GOTO表。ACTION表根据当前状态和输入符号决定下一步操作(移进、规约、接受或报错);GOTO表根据当前状态和非终结符决定下一个状态。
**代码实现:**csharpclass LR{ // ... 其他代码 ...
//分析句子 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 void Buildprod(string str) { // ... 代码实现 ... }
public Table[][] GET_ANA() { // ... 代码实现 ... } //求项目集 public void Creteitemsets() { // ... 代码实现 ... }
//构造闭包 public List<int> Closure(List<int> I) { // ... 代码实现 ... }}
代码解析:
Buildprod(string str): 该函数用于根据输入的文法规则构建LR(0)分析表。*Creteitemsets(): 该函数用于计算文法的项目集,项目集是LR(0)分析表构建的基础。*Closure(List<int> I): 该函数用于计算项目集的闭包。*GET_ANA(): 该函数用于生成LR(0)分析表。
SLR(1)分析器
SLR(1)分析器在LR(0)分析器的基础上引入了FOLLOW集的概念,通过FOLLOW集来解决LR(0)分析器的一些冲突。SLR(1)分析器的分析表构建过程与LR(0)类似,只是在规约操作时需要考虑FOLLOW集。
**补充代码实现:**csharpclass SLR : LR{ // ... 其他代码 ...
//求FOLLOW集 public void Follow() { int i, j, k; List<int> temp = new List<int>(100); for (i = 0; i < Nchar.Count; i++) { temp.Clear(); for (j = 0; j < LRproNum.Count; j++) { for (k = 0; k < LRproNum[j].Right.Length; k++) { if (LRproNum[j].Right[k].ToString() == Nchar[i].ToString()) { if (k == LRproNum[j].Right.Length - 1) // A->aB { if (LRproNum[j].Left != Nchar[i].ToString()) // A->aB, B不是最后一个符号 { temp = first(LRproNum[j].Right.Substring(k + 1)); add(FollowSet[Nchar[i]], temp); } if (LRproNum[j].Left != Nchar[i].ToString() && !isexist(Nchar[i], LRproNum[j].Left[0])) { FollowSet[LRproNum[j].Left[0]].Add(Nchar[i]); } } else // A->aBb { temp = first(LRproNum[j].Right.Substring(k + 1)); if (isexist(temp, '#')) { temp.Remove('#'); add(temp, FollowSet[LRproNum[j].Left[0]]); } add(FollowSet[Nchar[i]], temp); } } } } } FollowSet[Nchar[0]].Add('#'); }
//求FIRST集 public List<int> first(string str) { List<int> result = new List<int>(100); int i; for (i = 0; i < str.Length; i++) { if (isFinalsymbol(str[i])) { result.Add(str[i]); break; } else { add(result, FirstSet[str[i]]); if (!isexist(FirstSet[str[i]], '#')) break; } } if (i == str.Length) result.Add('#'); return result; }
//添加集合 public void add(List<int> a, List<int> b) { for (int i = 0; i < b.Count; i++) { if (!isexist(a, b[i])) a.Add(b[i]); } }
//判断是否存在 public bool isexist(List<int> a, int b) { for (int i = 0; i < a.Count; i++) { if (a[i] == b) return true; } return false; }
//判断是否为终结符 public bool isFinalsymbol(char ch) { if (ch >= 'A' && ch <= 'Z') return false; return true; }}
代码解析:
Follow(): 该函数用于计算文法中每个非终结符的FOLLOW集。*first(string str): 该函数用于计算符号串的FIRST集。*add(List<int> a, List<int> b): 该函数用于将集合b中的元素添加到集合a中。*isexist(List<int> a, int b): 该函数用于判断元素b是否存在于集合a中。*isFinalsymbol(char ch): 该函数用于判断字符ch是否为终结符。
总结
LR(0)和SLR(1)是两种常用的语法分析技术,SLR(1)分析器在分析能力上优于LR(0)分析器。本文通过代码示例详细介绍了这两种分析器的实现方法,希望能帮助读者更好地理解和掌握语法分析的相关知识。
原文地址: https://www.cveoy.top/t/topic/f0l9 著作权归作者所有。请勿转载和采集!