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)分析器。本文通过代码示例详细介绍了这两种分析器的实现方法,希望能帮助读者更好地理解和掌握语法分析的相关知识。

LR(0)和SLR(1)语法分析器实现与代码解析

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

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