
编译原理
文章平均质量分 73
汪星人来地球
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
后缀表达式 (1) ——中缀表达式与后缀表达式的手动转换
后缀表达式基本概念在我们的现实生活中,用的最多的是中缀表达式。所谓中缀表达式,是指表达式的运算符在运算元的中间。例如在表达式 a+ba+b 中运算元有两个,即aa和bb, 它们表示两个数字;而加法运算符++在这个两个运算元中间。但是中缀运算符不能很好地表征运算的次序。例如对于表达式 a+b∗ca+b*c 如果单纯地从表达式来看,我们无法确切地知道到底是先执行加法运算还是先执行乘法运算。当然,原创 2016-08-28 13:57:31 · 928 阅读 · 0 评论 -
左递归
空串产生式最常出现的情形——左递归的消除。左递归是产生式的一种特殊形式。它的形式如下。A→AαA\rightarrow A \alpha其中A是非终结符,而α\alpha是由终结符和非终结符组成的字符串。注意,α\alpha不能是空串,否则产生式变为A→AA\rightarrow A没有任何意义。左递归会对文法分析造成困扰。因为,根据产生式,我们可以不断进行如下推导。A→→→→AαAααAααα..原创 2017-01-08 17:43:12 · 11083 阅读 · 0 评论 -
词法分析与正则文法(二)
集合的运算设L和D都是某些字符串的集合,定义L∪DL\cup D为两个集合的并。 LDLD为两个集合的连接,即LD=αβ:α∈L,β∈DLD={\alpha\beta: \alpha \in L, \beta\in D}。 LkL^k为两集合L的k次自连接。例如L3=LLL=(LL)LL^3=LLL=(LL)L。特别地,记L0={ϵ}L^0=\{\epsilon\},其中ϵ\epsilo原创 2017-01-11 23:44:32 · 876 阅读 · 0 评论 -
词法分析与正则表达式(三)
对编译原理有基本了解的人都知道,正则表达式与有限状态自动机存在等价的关系。换句话说,它们能够识别的语言集合是一样的。但是在C语言的词法分析中,我们不需要运用有限状态自动机的知识,因此相关的介绍都略去。本文介绍如何实现C语言的语法分析。需要指出的是,我们不打算实现C语言的所有功能。因为这既耗时,也完全没有必要。通过实现一些简单的功能,就足以理解编译原理的全貌了。我们词法分析程序,识别的关原创 2017-01-16 19:04:24 · 1065 阅读 · 0 评论 -
python特性(四):for语句的工作原理
对于如下的for语句for obj in iterable_obj: do something with obj首先会调用iter方法获取关于iterable_obj对象的迭代器,然后不断调用迭代器对象的next方法,直至抛出异常位置。为了说明这一点,看下面的例子。myiter = MyIterator(1, 4)for i in myiter:原创 2017-02-17 18:23:02 · 1162 阅读 · 0 评论 -
python特性(五):序列诱导的迭代器
如果我们自己要实现iter方法,通过一个序列对象构造出一个迭代器,会怎么做呢?首先需要定义一个迭代器类。class MyIteratorFromSequence: def __init__(self, sequence): self.start = 0 self.sequence = sequence def next(self):原创 2017-02-17 18:50:32 · 499 阅读 · 0 评论 -
python特性(六):yield与迭代器生成器
迭代器是非常高效的类型,无论是从时间复杂度,还是从空间复杂度。而实现迭代器的代码虽然简单,却也繁琐。为此,python定义了一个yield关键字,专门用来构造迭代器。yield有生成,产生的意思。yield的功能和return非常类似,它们都只能在方法中使用。不同的是,包含yield语句的方法被称为生成器方法。当调用生成器方法时,会返回一个生成器对象。例如,看下面的例子。原创 2017-02-20 19:35:12 · 651 阅读 · 0 评论 -
python特性(一):序列与xrange对象
说到序列,我们第一想到的是一组有序元素组成的集合。同时,每个元素都有唯一的下标作为索引。在python中,有许多内界的序列。包括元组tuple,列表list,字符串str等。上面提到的序列类型(list,tuple,str)有一个共同的特点,就是当序列对象创建时,需要开辟专门的内存空间,保存序列中的所有元素。换句话说,这些序列对象本质上,是一个集合。例如,下面代码创建了一个原创 2017-02-12 12:19:07 · 1828 阅读 · 0 评论 -
python特性(二):迭代器与for语句
网上许多文章说Python的for语句中,in关键字后面的对象是一个集合。例如for i in [1,2,3] print i上面代码中in关键字后面的对象[1,2,3]是一个list,也是一个集合。但in关键字后面的对象其实不必是一个集合。一个序列对象也是合法的。 例如myrange = MyRange(0, 10)for i in myrange: p原创 2017-02-12 16:50:12 · 903 阅读 · 0 评论 -
词法分析与正则表达式 (一)
严格来说,词法分析是语法分析的一部分。可是将词法分析从语法分析中抽离出来,有如下好处。1. 简化语法分析器的设计。如果把空白字符和去除注释这些功能都交给语法分析器来处理,那语法分析器的结构会变得非常简单。2. 提高编译器效率。编译器耗时最大的部分消耗在词法分析阶段。因为词法分析涉及到文件读操作。而将词法分析器抽离出来,有利于设计更有效的专门的处理器。3. 增强编译器的移植性。与原创 2017-01-10 20:24:20 · 1904 阅读 · 0 评论 -
空串产生式
在上下文无关文法的定义中,要求产生式的左部是一个非终结符,而产生式的右部是非终结符和终结符串。但是有一类产生式非常特殊。它们形如V→ϵV\rightarrow\epsilon这里V是非终结符,而ϵ\epsilon是一个特殊的字符,表示空串。在处理空串时需要特别注意。因为一个空串可以看做是两个空串的链接。这样一生二,二生三,无穷无尽,不知道何处是个头。因此在语法分析时,空串产生式不是随处可用。那么在什原创 2017-01-08 17:01:40 · 3138 阅读 · 0 评论 -
去除代码中的注释(三) 实现 下
上一篇博文介绍了对输入字符流的预处理,将字符流转化为Token流。经过这一步转化后,就可以使用上下文无关文法进行分析了。本文介绍对Token流的分析过程。我们使用递归下降法来实现语法的解析。递归下降法的特点是,为每一个非终结符定义一个函数,在这个函数里需要定义所有以该非终结符为左部的产生式。我们定义了下面的非终结符。表示整个源代码段,它是文法定义中的初始非终结符原创 2017-01-07 21:08:38 · 392 阅读 · 0 评论 -
后缀表达式 (2) —— 表达树与后缀表达式的运算
后缀表达式的生成树在上一篇博客 后缀表达式(1)中已经提到过,后缀表达式的优点在于它便于计算机和识别与处理。我们编程解析后缀表达式的过程,其实是生成该表达式的生成树的过程。虽然我们并不一定在代码中显式地把这棵树构造出来,但我们确实隐含地运用了生成树的结构。因此,手工把这棵生成树画出来,对于理解后缀表达式的运算过程非常有用。这里,我们依然假设运算符都是二元的,这样构造出来的生成树必然是一个二叉树。对于原创 2016-08-30 16:00:45 · 2151 阅读 · 0 评论 -
后缀表达式(3)——后缀表达式的计算,递归实现
有了博客后缀表达式(2)的分析,要实现后缀表达式的计算已经非常容易了。 首先,我们构造一个结构体。这个结构体表示后缀表达式中的一个元素。这个元素可能是运算符,也可能是运算元。这里我们假设运算符有加减乘除四种,而运算元始终是正整数。结构体的定义如下。typedef struct str_ele{ bool is_op; int val;} Element;结构体成员原创 2016-09-05 16:33:00 · 3469 阅读 · 0 评论 -
后缀表达式(4)-——中缀表达式到后缀表达式的转换,递归实现
本篇是介绍的是后缀表达式最难,也是最基本的一个问题。即如何将一个中缀表达式转化为后缀表达式。在网上可以找到许多非递归实现的示例代码,它们比本节介绍的代码要简洁且高效,可是不利于理解。本节舍近求远,介绍后缀表达式的递归实现方式,为的是把变换的中心思想解释清楚。问题描述输入: 是一串字符串,它表示的是包含加减乘除四则运算以及括号运算的中缀表达式。为了简单起见,我们假设表达式中的原创 2016-10-16 22:46:59 · 3869 阅读 · 0 评论 -
编译原理概述
编译原理的应用准备系统地整理学习编译原理的相关知识。虽然这部分知识很多时候非常抽象,却能够很高的提高程序员内在的修养。如果每一种程序语言是一套招式,那么编译原理就是内功。不管程序语言如何变,都摆脱不了编译原理研究的BNF范式。具体来说,学习编译原理可能有以下几个方面的用处。在平常写代码中的需要。我们在处理结构化文本(例如去除文本中的干扰内容,解析web页面等),计算原创 2016-11-09 20:21:31 · 942 阅读 · 0 评论 -
语法概述
所谓语法,定义的是一种语言。而语言,是语句的集合。所以一们语法定义的是一组语句组成的集合。但是,一个语言包含的语句通常是无穷无尽的。因此,不可能通过枚举的方法来描述一门语言。为此,便有了语法规则的概念。具体来说,一个语言由下面4部分组成。终结符组成的集合。一门语言的终结符是语句中不能分割的语法单元。例如在汉语中,可以将单个汉字看成是终结符,英语中将单词看成是终结符。而在编程语言中,终结符包括运算符原创 2016-11-16 21:13:35 · 567 阅读 · 0 评论 -
上下文无关文法及其分析树
上下文无关文法是程序设计语言所使用的语法。它的特点是同样的字符串在不同的语境下,意思不变。满足上下文无关文法的语言便于计算机识别和处理。我们已经介绍过,语言是语句的集合,而语句是通过产生式定义的。上下文无关文法要求产生式的左部有且仅有一个非终结符。例如:考虑如下文法G,其非终结符集合为{L, D},终结符集合为{0,1,2,…,9,+,-},开始符号为L,产生式集合为L→L+D|L−D|DL \ri原创 2016-12-09 17:24:10 · 8009 阅读 · 3 评论 -
去除代码中的注释(二) 实现 上
上一篇博文介绍了去除代码注释的思想。我们发现,代码注释准确来说,不属于上下文无关文法的范畴。也就是同样的一个字符串,在不同的上下文环境下语义有所不同。为了对付这种情况,需要在字符解析时引入状态变量。我们实现的过程,主要分为两个部分。首先将输入字符串整理成一个Token。这里的Token在文法规则中对应的终结符。有了第一部分的工作,生成的Token流就可以通过上下文无关文原创 2017-01-04 21:54:46 · 732 阅读 · 0 评论 -
去除代码中的注释(一)设计思想
编译器的第一个工作是需要去除代码中的注释。这里分析的代码是C源代码。我们知道在C代码中,有两种类型的注释。1. 块注释。以/*开头,以*/结尾,可以饱含多行。2. 行注释。以//开头直至末尾。要去除这两块的注释本身不是难事,比较麻烦的是处理有双引号的情形。例如考虑下面的代码段。int main(){ printf("/* Hello the world");}在这段代码中,虽原创 2016-12-11 16:54:37 · 1999 阅读 · 0 评论 -
python特性(三):iter方法
iter方法是python的一个内建方法,它会返回一个迭代器对象。它定义如下iter(o[, sentinel])第一个参数o可以是一个可迭代对象,也可以是一个可调用对象。当参数o是可迭代对象时,第二个参数可省。这里又分为两种情况。如果参数o实现了__iter__方法,则直接调用该方法,创建迭代器。如果参数o没有实现__iter__方法,那么它比是一个序列对象。iter方法原创 2017-02-12 17:37:06 · 10948 阅读 · 0 评论