编译原理翻译成四元式例题_编译原理笔记04——语法分析(一)

本文介绍了编译原理中的语法分析,包括自顶向下和自底向上的方法。重点讨论了提取左公因子、消除左递归和消除二义性的技术,以构建语法分析树。通过实例展示了如何处理这些问题,为后续的编译器设计打下基础。
摘要由CSDN通过智能技术生成

编译原理是这学期的两门硬核课程之一,一直计划着把前面几章都过一遍,现在正好在学习语法分析,就顺便整理一下,就当复习了。

Introduction

首先还是来看目标,也就是我们希望做什么,最后的实验要求是要对于一个已经词法分析过的字串进行语法树的构建。语法树,我个人看来就是对数据的运算逻辑的一种比较高效地表示,语法树相当精确地揭示了一个语句的构造顺序。龙书中则是这样介绍的:“语法分析器构造出一棵语法分析树,并传递给编译器的其他部分进一步处理”。

常见的有两种,自顶向下和自底向上的方法。需要指出的是,输入总是从左到右,每次扫描一个符号。

设计文法

首先从自顶向下的文法入手,设计文法。

提取左公因子

我们在进行自顶向下的语法分析时会用到这项技术来提高效率。简单来说,对于左部相同的不同产生式来说,我们会有不同的选择,如

,我们读入
后,不知道接下来改如何处理,因为有两条路。如果选择了一条错误的路,就需要回溯。
减少回溯就意味着提高了效率。我们希望改写产生式,可以使得我们这个决定推后,当我们读入足够多的输入之后,再进行选择。

给出提取左公因子的算法:

对于A(

),考虑A的
最大公共前缀
,则转化A的所有产生式:

则我们可以替换:

比如刚才的式子就可以表示为:

消除左递归

如果文法中出现了类似

,我们就称之为左递归的。自顶向下语法分析不能处理左递归文法,因此需要转化。

注意的是,递归是不可以消除的,即可以转化为别的形式的递归,但递归本身是存在的。

首先考虑

的情形。有可能出现的最终的字符的形式:

由此归纳可以得出:

原理类似,下面考虑复杂一点的情形。

可以看出出现左递归的场景无非是含有本身作为前缀的产生式。参考
提取公因子的想法,我们可以改写:

类似地,可以看成上述的归纳过程,但是终结符号有了更多的选择而已。除此以外,基本相同。

消除二义性

比如对于含有

的文法来说,就会产生二义性,比如对于下面的文法:

af8e2ceed1221826a5724f4aed9d2ac7.png

我们构造语法分析树:

d873f9d847a4eaee7c89a876822968cb.png

是有两种选择的。其实很好理解,因为出现了两个if但是只有一个else,势必会在else和哪个if配对的问题上产生冲突。一般来说,我们会规定就近原则:即else和最近的if配对。其基本思想是在一个then和else之间出现的语句基本是已匹配的。这里的话并没有特别着重介绍,以后有空填。

自顶向下的语法分析

现在我们就可以进行自顶向下的语法分析了。回顾一下开头的话,语法分析可以看成是构造一棵语法分析树的过程。从根节点开始,进行深度优先遍历。我们一龙书上的例题举例:

7646b06e0dd271ebadf7b02e6ebf305e.png

对于这个文法构造分析树。这里的文法显然是消除了左递归的。书上的分析过程如下:

ccbecb070c90a741db22f975a8c312ae.png

可以看出我们的一个难题是如何选择合适的产生式。使得可以和输入区匹配。一般来说,朴素的想法显然会想到回溯,但我们这里的想法显然避免了这样的方式。那该如何实现呢?

算法其实是有点妙的,也很难想到,但核心还是很朴素的,就是所谓的预测。这里我就从个人进行构造的情况来谈谈。我们为什么会产生回溯?是因为产生冲突。为什么产生冲突?是因为新读入的字符和我预想的对不上号。那么,如果我做了正确的预判,是不是就可以避免这样的问题呢?那就需要我们提前读入后面的输入符号。假如,我读入一个字符,可以根据当前的状态寻找合适的处理,问题自然解决了。

以上就是问题的朴素的想法。而这一想法的具体实现,则是通过维护一张“预测分析表”来实现的。具体的细节,会在下一篇整理。


2020年12月17日21点43分

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值