编译器是怎么工作的?使用yacc 和lex 写一个计算器(1)

来源:互联网 发布:jsp中使用javascript 编辑:程序博客网 时间:2024/05/16 18:13

编译器是怎么工作的?使用yacc 和lex 写一个计算器


前天开始学yacc 和lex编译器,找了一通文档,发现没有好的文档,都是一上来就给初学者来个下马威讲高深的玩意,

所以我决定写一篇从初学者的观点来看编译器的文章。


让我们从计算器开始

-----------------------------

一听说要学习编译器,马上有同学想到C++,就会痛苦不堪,那一大坨** ,还要编译它?

没关系,我们不编译C++,我们只作和它功能相似的计算器。我们要写一个解释器,能计算诸如:

1+2+3+4+5

的表达式的就可以知道编译器作了哪些事。


分析这个表达式 1+2+3+4+5,先不说计算机, 人是怎么手工计算的?你当然会算:

 1+2 = 3

3+3 = 6

6+4 = 10

10+5 = 15

恩,把两个数相加的结果加到另外一个数上就可以了,整个计算过程加上括号:

((((1+2) +3 ) +4 ) +5 )

考虑上边的计算过程,如果我们的程序也能像人一样,处理以上过程,不就可以处理这些计算了吗?



我的语法,我说了算

----------------

观察

 1+2 = 3

3+3 = 6

6+4 = 10

10+5 = 15

这几组表达式,我们待计算的东西是什么?对, 是一个数 + 另外一个数,我们加出来的还是一个数,即:

数 + 数  = 数  /* number  + number   = number */

这是一个我们定义的加法模式,只要符合这个等式左边模式的,都可以被我们以上的表达式所处理了

 如给已经接受了这种规则的状态,起个新名字为expression,

则我们可以定义我们能够处理(或接受)的输入为:

expression :

number + number

考虑(1+2) +3

因此,我们可以接受的加法计算器表达式变成了以下两种

expression:

number + number 

或  expression + number

如果我们用 | 表示“或”的话,上边的表述则可以变成下边的:

expression:

number + number 

|  expression + number

以后的((((...)))都可以被我们后一条的语法所解析和接受


我们的计算规则: number + number = number 如果代入上式

就变成了:

expression:

number  

|  expression + number


上边的式子的意思是:

一个表达式可是一个数

一个表达式也可以是另外一个表达式加上一个数。


让我们来人肉编译一下这两条规则 

15 OK,应用 第一条规则,15是我们定义的计算器可以接受的

(1+2)+3

先应用第1条规则

变成

(expression + 2) + 3

再应用第二条规则

变成 expression + 3

没错,这也是我们的计算器可以接受的



鸡生蛋生鸡生蛋生鸡生蛋生鸡生蛋生鸡生蛋生鸡生蛋生鸡。。。这就是递递递递递递递递递递递递递归了