博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从零开始写个编译器吧 - 分析非终结符
阅读量:7005 次
发布时间:2019-06-27

本文共 1409 字,大约阅读时间需要 4 分钟。

tao 语言的 Parser 的语法分析是不带回溯的,自顶向下的。文法选用 LL(1),这种文法虽然略显薄弱,但还尚可用。

回顾上一章提到的 LL(1) 的定义,可以得出如下结论。

在不考虑 ε 时,对于一个非终结符,它的每一个产生式都有一个FIRST 集与之对应。而这些 FIRST 集彼此不相交。

这个特征很有用,因为这个特征很容易得出以下结论。

对于某个非终结符的所有产生式而言,任取一个终结符,该终结符……

  • 要么不属于任何一个 FIRST 集;

  • 要么仅属于某一个FIRST集,从而找到唯一的一个产生式与之对应。

基于这个结论,Parser 对某个非终结符展开形式的判定就变得明了起来。将从 Tokenizer 处读取到的 Token(即非终结符)递归的与非终结符产生式的 FIRST集做比较,一旦找到一个 FIRST 包含该 Token,即挑选该 FIRST 集对应的产生式。

整个过程可一气呵成,不需要进行任何回溯。

但这么做之前,我们必须知道每一个非终结符的所有产生式的 FIRST 集。嗯,这是必要的,赶紧记在小本子上吧,在将来的章节中我们必须要写求 FIRST 集的程序。

好,假设我们已经求出所有非终结符产生式的 FIRST 集了,是不是就可以开始写 Parser 了呢?非也,之前的结论是建立在“不考虑 ε”的前提下。

所以,让我们来讨论允许 ε 的情况。

如果产生式中可能出现 ε,那么每一个产生式中的非终结符都有可能导出 ε 的嫌疑。但 LL(1) 严格的要求一个非终结符最多只能有一个产生式可以导出 ε。这意味着我们必须明确知道每一个非终结符能不能导出 ε。好在这并非难事,让我们观察,对于。

A → α | β | ε

而言,不用说 A 肯定能导出 ε,我都抓到现行了你还说没有?!不解释,它就可以导出 ε。

对于,

B → abide

可以肯定,不能导出 ε,因为产生式右边全是终结符,终结符是不可能再展开的,因此我眼睛没看到 ε,它就导不出 ε。

但是,这种情况就比较暧昧了,

C → αβγ

因为 α、β、γ 三个是式子,能不能导出 ε 真说不准。不过可以肯定的是,只要有一个式子不能导出 ε,那么 C 一定无法导出 ε。因为那个导不出 ε 的式子永远不会“消失掉”,它霸占的位置最终会变成一组终结符串,故 C 绝不可能为空。反过来,只有当所有的式子都能导出 ε 的时候,C 才能导出 ε。

于是,判断式子是否可以导出 ε 的条件呼之欲出。

  • 终结符一定不能导出 ε。

  • 如果存在产生式 A → ε,则非终结符 A 能导出 ε。

  • 如果 A 的一个产生式 A → αβγ... 右侧所有符号都可以导出 ε,则 A 可以导出 ε。

当某个非终结符可以导出 ε 时,Parser 在发现一个终结符的时候,在与其所有产生式的 FIRST 集比较过一次无果后,还可以与 FOLLOW 集比较。如果FOLLOW 集包含这个终结符,则表明该非终结符需要导出 ε。

至此,看来我们不但要事先求出每个非终结符的所有产生式的 FIRST 集,还要判断每一个非终结符是否能导出 ε。这样,我又要在笔记本上多记一条了。

嗯,到这里我已经连续讲了3章理论了,虽然我原本打算尽量少讲理论的,但是现在发现这些东西似乎避免不了。因为之后我要写的东西全部来自这里头。不过,下一章我还会继续讲理论,然后开始写 Parser。

转载地址:http://pxytl.baihongyu.com/

你可能感兴趣的文章
Netty-ChannelHandler-ChannelPipeline
查看>>
php 上传图片造成内存溢出 Allowed memory size of ... bytes
查看>>
[Doctrine Migrations]数据库迁移组件的深入解析一:安装与使用
查看>>
客户说网页打开白屏了,怎么办?(前端异常日志收集)
查看>>
[LintCode] Three Distinct Factors
查看>>
iOS多线程:『GCD』详尽总结
查看>>
Github pages + Minimal-Mistakes + Disqus建立个人博客记录
查看>>
CSS3属性-webkit-font-smoothing字体抗锯齿渲染
查看>>
对MVVM架构的一些理解
查看>>
Spring IOC 容器源码分析 - 创建单例 bean 的过程
查看>>
MySQL数据库1
查看>>
Android入门篇(五)Activity跳转
查看>>
每天一个lodash方法-differenceBy
查看>>
linux命令之htpasswd
查看>>
Nginx负载均衡配置
查看>>
flow的采集与分析---clickhouse的简介和安装
查看>>
cgo的指针传递
查看>>
JS 实现抛物线动画
查看>>
前端是不是大于后端?
查看>>
小程序onLaunch,onLoad 执行生命周期
查看>>