- 博客(16)
- 资源 (8)
- 收藏
- 关注
原创 关于编译技术和语言理论的书籍
>我是看这本书入门的,内容很简单,实现了一个tiny的微型语言,各个理论分支浅尝辄止。>这本书我同时买了英文影印和中文版,对于喜欢的书大都这样;毋庸多言,每个喜欢编译技术或是计算机科学的人都会读过它。>差不多是lcc完全注释,非常详细,也非常易懂。我买的是英文原版,花了近500RMB,刚拿到的时候好一阵兴奋,可是差不多半年后,它毫无征兆的从中断裂开来,并且在随后的日子里时不时飞散出零碎的几页。>这
2005-12-29 13:35:00 2499 3
原创 How To Build a Yacc Series
必须要承认,写文章的工作比写代码难的多。 How To Build a Yacc Series的代码全部列举完,目前我能做的就是把以前写好的代码按某些预定的步骤copy&paste, 而要解释他们还需要至少3倍以上的时间。重构的方法论认为,一项工作,无论开始的方法有多么糟糕,先完成它,然后改进它。写文档也可以这么干。
2005-12-28 01:57:00 1831 1
原创 How To Build a Yacc?(14)
既然已经生成了DFA,按照之前的描述写出shift_reduction算法就不是什么了不起的工作了。class Compiler def initialize(rule_file, src_file) @yacc = Yacc.new(rule_file) @lex = ExtendLex.new(src_file) @parse_stack = Array.new end
2005-12-28 01:49:00 1606 1
原创 How To Build a Yacc?(13)
实际上,有了上面的准备后,计算DFA的算法很清楚:class DFA SHIFT = 1 REDUCE = 2 ERROR = 3 ACCEPT = 4 def initialize() @state_set = Array.new @current_state = 0 @max_state = 0 @action_table = Hash.
2005-12-28 01:44:00 1394
原创 How To Build a Yacc?(12)
生成DFA的第1步,计算first集合和follow集合。first_set和follow_set都是一个hast set结构,这个hash的key是一个 vocab,而value是一个集合,用一个array表示,这与普通的hash不同,因此写了一个HashDup的module,其中重写了hash的store方法,用来满足上述要求:###### hashdup.rb ###########modu
2005-12-28 01:41:00 1332
原创 How To Build a Yacc?(11)
分析完rule_file, 最后一个关键的步骤是生成DFA。这是一个比较复杂的过程,首先我们要建立一个Item结构,这样才能构造状态(states)item 应该是一个rule和一个相关的position(当前识别位置)组成。class TestCompiler def test_item rule = Rule.parse("function_decl := / functi
2005-12-28 01:30:00 1235
原创 How To Build a Yacc?(10)
将Vocab和Rule功能组合起来作为一个RuleParser类来提供分析rule_file的功能是个不错的主意,因为对这两个类而言并没有太大的重用的意义,只不过是为了将错误的出现尽可能的控制在局部。class TestCompiler def test_rule_parser create_rule_file p = RuleParser.new("rulefile") a
2005-12-28 01:06:00 1264
原创 How To Build a Yacc?(9)
考虑该怎么样设计Yacc类。显然,Yacc面临的第1个问题就是分析rule_file的内容。Yacc类本身不应该实现这个功能,因为还有一个功能是生成DFA,这是两个没有多大关系的功能,按照SRP(单一职责原则),不应该在一个类里实现。按照这个设计原则,很容易做出的决定,需要一个类Vocab识别rule_file定义的所有符号(TERMINAL,NONTERMINAL,EOF,START_SYMBO
2005-12-28 00:53:00 1325
原创 How To Build a Yacc?(8)
搞定lex后,很显然,我们要将它加入到Compiler中。class Compiler def initialize(rule_file, src_file) @lex = ExtendLex.new(src_file) end def run return true end end要想在run里面真正的干点事,就需要一个shift-reduction算法来识别sr
2005-12-26 11:11:00 1383
原创 How To Build a Yacc?(7)
代码,还是代码! 要完成一个这样相对复杂的功能,是需要写一些代码,不过我保证,他最终将比你想象的少的多。 我对Lex类还有些不尽满意,实际上,我更希望lex.get_token_string能取得当前符号流中的任何一个符号,而不仅仅是当前的一个符号。。 lex = Lex.new(src) lex.get_next_token assert ( lex.get_token_stri
2005-12-19 17:51:00 1219
原创 How To Build a Yacc?(6)
显然,Compiler至少分为两个明显的部分:一部分是读入源代码,将其转换成符号流,一部分是读入语法规则文件,生成DFA。 先来讨论字符流转换成符号流的部分,由于这部分不是讨论的重点,就利用了目前已经相当通用的技术lex。 如果要想在ruby环境中利用lex工具生成的c代码,只有把c代码封装成ruby的扩展库。 lex怎么工作的? 首先编写一个lex的输入文件: // prog.l %{
2005-12-19 17:42:00 1347
原创 How To Build a Yacc?(5)
现在是时候来讨论How To Build a Yacc?(1)中的最初提出的问题了。。 如何判断一段代码是否符合预定义的syntax rules,毫无疑问:用你的眼睛和大脑配合也能完成这个任务,或许你还需要一张白纸,以计算syntax rules生成的DFA和stack。但是在有计算机的情况下,谁还会用人脑去代替计算机呢? 用计算机来实现这个功能,有了上面的讨论后,一切似乎很明了:读入synt
2005-12-19 17:41:00 1354
原创 How To Build a Yacc?(4)
有了DFA,接下来的事情好办多了,只要写一个DFA识别算法就完了,通常我们把这个算法称为移进-规约算法(shift-reduction)。借助一个stack来描述shift-reduction:1) 初始时,stack存放初始状态S12) 取符号流中下一个符号(token),在DFA中查找是否有边S1(token) --> SX,如果有,将符号(token)移进stack, 并
2005-12-19 17:40:00 1249
原创 How To Build a Yacc?(3)
在(2)中,我们阐述了一个简单高效的分析方法,最终产生一个文法的最左推导(即每次优先扩展左边的NONTERMINAL) 但是递归下降算法有些许局限性,比如:对于两个不同的NONTERMINAL,如果他们的FIRST集合有交集的话,就会产生歧义,很显然,当目前的符号分别属于两个不同的NONTERMINAL的FIRST集合时,就无法决定采用哪个产生式了。 我们来考虑另外一种分析方法,与递归下降相反
2005-12-19 17:38:00 1575
原创 How To Build a Yacc?(2)
如何识别一段代码是否符合定义的文法? 如上面的例子: function foo(kick, so, by); 首先,技术上来说,代码文本是一段字符流,f, u, n, c....,而我们文法识别的最小级别是符号(token), 所以需要将其转化为符号流,这个功能可以很容易的用lex实现,这个步骤不是讲述重点,不加详细叙述。 最直接的识别方法,以function_decl文法为例,我们从符号流
2005-12-19 17:36:00 1371
原创 How To Build a Yacc?(1)
Yacc 是什么?编译器的编译器。简单来说,Yacc读入一套语法定义规格(syntax rules), 然后分析一段代码(source code), 判断代码是否符合定义好的syntax rules。语法定义规格是由形式化的BNF表达式来定义;目前大多数语言都可以用它来定义。一个BNF表达式由一个NONTERMINAL(非终结符)和它的产生式组成,产生式可以是终结符(T
2005-12-19 17:34:00 1759 1
面向模式的软件体系结构 Vol.1
2008-09-16
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人