从零开始写个编译器吧 - LL(1)

虚树涟漪
• 阅读 6267

上一章中,我说 Parser 的工作就是依据文法定义,找到一个与源代码匹配的展开方案就可以了。听起来我们只要先给出一个 tao 语言的文法定义,然后写一个找匹配方案的的程序就可以了。
然而事情情况并非如此简单。因为假如我们不对文法定义的形式加诸任何限制的话,让 Parser 找到匹配方案并非很轻易的事情。

因此,我规定,tao 语言的将用 LL(1) 文法来定义

在简单介绍 LL(1) 文法之前,我还要说明一种比较特别的产生式。

A → ε

希腊字母 ε 表示“空”,这个产生式表明非终结符 A 可以产生一个空。具体来说,如果有如下文法。

S → αAβ

A → ε

那么:

S → αβ

非终结符可以产生空这一特性,令文法的形式更加复杂,但是却是必不可少的。少了这一特征,就很难描述 tao 语言的语法细节了。

此外,对于一个文法之中的非终结符,还有 FIRST 集、FOLLOW 集的概念。

  • 对于一个非终结符 A 而言,它的 FIRST 集指 A 可能展开的各种形式中,位于第一的所有终结符所组成的集合。记为 FIRST(A)。

  • 而 FOLLOW 集,指在整个文法中,非终结符 A 后面可能接的所有终结符组成的集合。记为 FOLLOW(A)。

这么描述可能有点绕,细节先不管,但有一点很重要,即无论是 FIRST 集还是 FOLLOW 集,它们都只能包含终结符

那么,LL(1) 又是怎样一种文法呢?

对于一个文法而言,如果它的每一个非终结符的产生式

A → α | β | γ ……

都满足如下三个条件,则将这个文法称之为 LL(1) 文法。

  1. 对于所有不能导出 ε 的表达式 α、β、γ……,都有,FIRST(α)、FIRST(β)、FIRST(γ)……两两互不相交。

  2. 最多只有一个表达式可以导出 ε。

  3. 如果有一个表达式可以导出 ε,那么对于其他不可以导出 ε 的表达式 ξ,有,FIRST(ξ) ∩ FOLLOW(A) = Φ。

最后一条有加粗,当然并非因为它对 LL(1) 本身很重要,而是因为我在实现 Parser 的时候并没有完全遵守这一条。某种意义上说,tao 语言的 Parser 并非严格遵守 LL(1) 文法,因此在此加粗这条,以便与后面的章节呼应。

点赞
收藏
评论区
推荐文章
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Wesley13 Wesley13
4年前
UIWebView长按保存图片和识别图片二维码的实现方案(使用缓存)
0x00需求:长按识别UIWebView中的二维码,如下图长按识别二维码0x01方案1:给UIWebView增加一个长按手势,激活长按手势时获取当前UIWebView的截图,分析是否包含二维码。核心代码:略优点:流程简单,可以快速实现。不足:无法实现保存UIWebView中图片,如果当前We
Peter20 Peter20
4年前
mysql中like用法
like的通配符有两种%(百分号):代表零个、一个或者多个字符。\(下划线):代表一个数字或者字符。1\.name以"李"开头wherenamelike'李%'2\.name中包含"云",“云”可以在任何位置wherenamelike'%云%'3\.第二个和第三个字符是0的值wheresalarylike'\00%'4\
Stella981 Stella981
4年前
Python Challenge Level 18
初学Python,挑战一下流行的PythonChallenge,很不幸,卡在了18关~~被字符字节码之间的转换搞得焦头烂额,不过终于搞定了还是很happy的~~~主要的问题就是16进制形式的字符如何转成字节码(注意:不是encoding)如:\'89','50','4e','47','0d','0a','1a','0a','00
Stella981 Stella981
4年前
Kerberos无约束委派的攻击和防御
 0x00前言简介当ActiveDirectory首次与Windows2000Server一起发布时,Microsoft就提供了一种简单的机制来支持用户通过Kerberos对Web服务器进行身份验证并需要授权用户更新后端数据库服务器上的记录的方案。这通常被称为Kerberosdoublehopissue(双跃点问题),
Wesley13 Wesley13
4年前
JAVA记录
singleton作用域:当把一个Bean定义设置为singleton作用域是,SpringIoC容器中只会存在一个共享的Bean实例,并且所有对Bean的请求,只要id与该Bean定义相匹配,则只会返回该Bean的同一实例。值得强调的是singleton作用域是Spring中的缺省作用域。prototype作用域:protot
Wesley13 Wesley13
4年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
4年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
4年前
EasyUI combobox下拉列表实现搜索过滤(模糊匹配)和placeholder效果
实现搜索功能:  项目中的某个下拉列表长达200多个项,这么巨大的数量一个一个找眼镜都得看花,于是就得整了个搜索功能。看网上别人帖子有只能前缀匹配的方案,但只能前缀匹配的话用起来也不是很方便。于是就记录一下模糊匹配的方案。实现效果:!(https://oscimg.oschina.net/oscnet/8d1b270fe6
Stella981 Stella981
4年前
Hibernate纯sql查询结果和该sql在数据库直接查询结果不一致
问题:今天在做一个查询的时候发现一个问题,我先在数据库实现了我需要的sql,然后我在代码中代码:selectdistinctd.id,d.name,COALESCE(c.count_num,0),COALESCE(c.count_fix,0),COALESCE(c