【编译原理龙书笔记】(二)一个简单的语法制导翻译器(仍未完成)

本文介绍了编译器的基础知识,包括简单语法制导翻译器的概念。详细阐述了上下文无关文法的定义,如文法元素、推导过程和语法分析树,同时讨论了二义性、运算符的结合性和优先级在编译器设计中的重要性。

这篇博客是根据自己学习龙书,因为博主习惯了英语环境,在强行从英语转化为中文的时候难免会有些不自然,请大家谅解。

配套的练习题答案可以在 https://github.com/Oh233/Dragon_book_exercise 看到。

感谢沉鱼姐姐,很多答案都是参考了她的github,虽然无缘认识,但也算是一位领路人。


正文:

一个简单的语法制导翻译器

在本章中,要先给一个编译器大致的idea,而并非一开始就专注于各种编译器过程的细节。

2.1 引言

首先快速浏览一下编译器的前端模型,也就是词法分析,语法分析,中间代码生成的这三个过程。

源程序通过词法分析器得到了一个个的词法单元,之后这些词法单元通过语法分析器被构造成了一棵抽象语法树。之后传给中间代码生成器,会产生树或者三地址形式的中间形式表达。

2.2 语法定义

我们要介绍的是一种用于描述程序设计语言语法的表示方法——“上下文无关文法”。

2.2.1 文法定义

一个上下文无关文法(context free grammar)由以下四个元素组成:

  1. 一个终结符号集合。终结符号是该文法所定义的语言的基本符号的集合。
  2. 一个非终结符号集合。每个非终结符号表示一个终结符号串的集合。
  3. 一个产生式集合。产生式的结构包括产生式头(左部)的非终结符号,一个箭头,和一个产生式体(右部)的由终结符号和非终结符号组成的序列。产生式主要用来描述一种非终结符号的结构体是如何被定义的,即一种非终结符号的书写方式。
  4. 指定一个非终结符号作为开始符号。

为了更好地理解上下文无关文法,我们在此举一个例子。

终结符号为 + - 0 1 2 3 4 5 6 7 8 9
list list + digit
list list - digit
list digit
digit 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

上述例子说明了digit是一个非终结符号,这个非终结符号digit是由数字0123456789之中的某些单一数字组成的。而list这个非终结符号,是由另一个list 加上(注意这里只是表达式的加减,不会做出结果)digit 形成。根据开始符号的定义,我们还能看到这段文法的开始符号就是 list 。

零个终结符号组成的串成为空串,记为 ϵ .

2.2.2 推导

我们可以根据文法推导所有可能生成的符号串,比如可以从开始符号出发,不断将某个非终结符号替换为该非终结符号产生式的体(右部),这样可以推导得到所有终结符号串能得到的集合。这一套集合被称为语言。

在语法分析(parsing)的过程中,我们的目的是接受一个终结符号串作为输入,找出从文法的开始符号推导出这个串的方法。如果不能从文法的开始符号推导得到该输入的终结符号串,则报告语法错误。

用上面例子中的一套定义的话,我们如果输入 9 - 5 + 2,编译器就会开始推导说这个表达式是一个list,所以没有语法错误。这个即是推导的作用。

2.2.3 语法分析树

在上述从文法的开始符号推导到给定的终结符号串的过程中,我们可以用树状结构来简化(更好的描述)我们的推导过程。我们把具有以下性质的树称作是语法分析树:

  1. 根节点的标号是文法的开始符号
  2. 每个叶子节点的编号为一个终结符号或者是空串 ϵ
  3. 每个内部节点的标号都是一个非终结符号。
  4. 如果非终结符号A是某个内部节点的标号,并且它的子节点的标号从左到右分别为 X1,
### 编译原理语法制导翻译方案的概述 语法制导翻译方案(Syntax-Directed Translation)是一种通过语法分析树来指导中间代码生成的技术。它利用语法分析过程中构造的语法树,结合语义规则,在遍历语法树的同时完成翻译任务[^1]。语法制导翻译的核心思想是将语义动作与语法产生式相关联,在语法分析的过程中直接执行这些语义动作,从而生成目标代码或中间代码。 在《编译原理中,语法制导翻译方案通常被描述为一种结合了语法分析和语义分析的过程。例如,当解析器识别到某个语法单元时,会触发相应的语义动作,这些动作可以包括变量声明、类型检查、表达式求值等操作[^2]。此外,语法制导翻译还可以通过属性文法(Attribute Grammar)的形式进行更精确的定义和实现。 以下是一个简单语法制导翻译示例: #### 示例:算术表达式的翻译 假设有一个简单的算术表达式 `E -> E + T | T` 和 `T -> num`,其中 `E` 表示表达式,`T` 表示项,`num` 表示数字。我们可以为每个产生式附加语义动作,以生成三地址代码(Three-Address Code, TAC)。 ```python # 语法规则及语义动作 E -> E1 + T { gen(E1.place + " + " + T.place + " -> " + new_temp()) } E -> T { E.place = T.place } T -> num { T.place = num.value } ``` #### 解析过程 假设输入字符串为 `3 + 4`,其解析过程如下: 1. 词法分析器将输入分解为两个词法单元:`num(3)` 和 `num(4)`。 2. 语法分析器根据产生式 `E -> T` 和 `T -> num`,生成初始语法树节点。 3. 在遇到 `+` 符号时,触发语义动作 `gen(E1.place + " + " + T.place + " -> " + new_temp())`。 4. 最终生成的三地址代码为 `t1 = 3 + 4`。 #### 属性文法的扩展 在更复杂的场景下,可以通过引入综合属性(Synthesized Attributes)和继承属性(Inherited Attributes)来增强语法制导翻译的能力。例如,在类型检查中,可以使用继承属性传递上下文信息,如预期的返回类型;使用综合属性存储计算结果或生成的目标代码[^3]。 ### 总结 语法制导翻译方案是编译器设计中的重要技术之一,它将语法分析与语义分析紧密结合,使得编译器能够在解析源代码的同时完成翻译任务。通过属性文法的形式化定义,可以进一步提升语法制导翻译的灵活性和精确性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值