快捷搜索:  汽车  科技

编程需要有编译器吗?程序是用编程语言写的

编程需要有编译器吗?程序是用编程语言写的要说到C编译器的发展,必须要提到这两位大神——C语言之父Dennis Ritchie和Ken Thompson。Dennis和Ken在编程语言和操作系统的深远贡献让他们获得了计算机科学的最高荣誉,Dennis和Ken于1983年赢得了ACM图灵奖。下面的内容是我参考了别人的文章,由于找不到这位大师的署名,只好在此先献上我真挚的敬意,感谢他对求知者的奉献。1.英语老师教学生英语,学生成了英语老师后又可以教其他学生英语。2.写新的书需要参考其它旧书,新的书将来又会被更新的书参考,就像本书编写过程一样,要参考许多前辈的著作。这张图片在网络上非常火,它常常与励志类的文字相关。起初看到这个雕像在雕刻自己时,我着实被感动了,感受到的是一种成长之痛。今天把它贴过来的目的是想告诉大家,起初的编译器也是功能简单,不成规范,然而经过不断自我“雕刻”,它才有了今天功能的完善。

编程需要有编译器吗?程序是用编程语言写的(1)

我爱七龙珠

首先肯定的是先有的编程语言,哪怕这个语言简单到只有一个符号。先是设计好语言的规则,然后编写能够识别这套规则的编译器,否则若没有语言规则做为指导方向,编译器编写将无从下笔。

第1个编译器是怎么产生的,这个问题我并没有求证,不过可以谈下自己的理解,请大伙儿辩证地看。

这个问题属于哲学中鸡生蛋,蛋生鸡的问题,这种思维回旋性质的本源问题经常让人产生迷惑。可是现实生活中这样的例子太多了,如:

1.英语老师教学生英语,学生成了英语老师后又可以教其他学生英语。

2.写新的书需要参考其它旧书,新的书将来又会被更新的书参考,就像本书编写过程一样,要参考许多前辈的著作。

这张图片在网络上非常火,它常常与励志类的文字相关。起初看到这个雕像在雕刻自己时,我着实被感动了,感受到的是一种成长之痛。今天把它贴过来的目的是想告诉大家,起初的编译器也是功能简单,不成规范,然而经过不断自我“雕刻”,它才有了今天功能的完善。

下面的内容是我参考了别人的文章,由于找不到这位大师的署名,只好在此先献上我真挚的敬意,感谢他对求知者的奉献。

要说到C编译器的发展,必须要提到这两位大神——C语言之父Dennis Ritchie和Ken Thompson。Dennis和Ken在编程语言和操作系统的深远贡献让他们获得了计算机科学的最高荣誉,Dennis和Ken于1983年赢得了ACM图灵奖。

编译器是靠不断学习,不断积累才发展起来的,这是自我学习的过程,下面来看看他们是如何让编译器长大的。

我们都知道转义字符,转义字符是以’\’开头的多个字符,通常表示某些控制字符,它们通常是不可键入的,也就是这些字符无法在键盘上直接输入,比如’\n’表示回车换行,’\t’表示tab。由于以’\’开头的字符表示转义,因此要想表示’\’字符本身,就约定用’\’来转义自己,即’\\’表示字符’\’。转义字符虽然表示的是单个字符的意义,在编译器眼里转义字符是多个字符组成的字符串,比如’\n’是字符’\’和’n’组成的字符串,好啦,交待完毕。

起初的c编译器中并没有处理转义字符,为叙述方便,我们现在称之为老编译器。如果待编译的代码文件中有字符串’\\’,这在老编译器眼里就是’\\’字符串,并不是转义后的单个字符’\’。为了表明编译器与做为其输入的代码文件的关系,我们称做为输入的代码文件为应用程序文件,尽管被编译的代码文件是实现了一个编译器,而在编译器眼里,它只是一个应用程序级的角色。例如,gcc –c a.c中,a.c就是应用程序文件。

现在想在编译器中添加对转义字符的支持,那就需要修改老编译器的源代码,假设老编译器的源代码文件名为compile_old.c。被修改后的编译器代码,已不属于老编译器的源代码,故我们命名其文件名为compile_new_a.c,下面是修改后的内容。

编程需要有编译器吗?程序是用编程语言写的(2)

代码compile_new_a.c

其中,函数next()的功能是返回待处理文本(即被编译的源码文件)中的下一字符,强调一下是单个字符,并不是记法分析中的单词(即token)。

用老编译器将新编译器的源代码compile_new_a.c编译,生成可执行文件,该文件就是新的编译器,我们取名为新编译器_a。为了方便理清他们的关系,将他们列入表格中。

编译器自身源代码

编译器

应用程序源代码

输出文件名

compile_old.c

老编译器

compile_new_a.c

新编译器_a,支持’\\’

这下编译出来的新编译器_a可以编译含有转义字符’\\’的应用程序代码了,也就是说,待编译的文件(也就是应用程序代码)中,应该用’\\’来表示’\’。而单独的字符’\’在新编译器_a中未做处理而无法通过编译。所以此时新编译器_a是无法编译自己的源代码compile_new_a.c的,因为该源文件中只是单个’\’字符,新编译器_a只认得’\\’。

先更新他们的关系,见下表。

编译器自身源代码

编译器

应用程序源代码

输出文件名

compile_old.c

老编译器

compile_new_a.c

新编译器_a,支持’\\’

compile_new_a.c

新编译器_a

compile_new_a.c

编译失败

也就是说,现在新编译器_a,无法编译自己的源文件compile_new_a.c,只有老编译器才能编译它。再啰嗦一下,新编译器_a无法正确编译自己的源文件compile_new_a.c的原因是,compile_new_a.c中’\’字符应该用转义字符的方式来引用,即所有用’\’的地方都应该替换为’\\’。再回头看一下新编译器_a的源代码compile_new_a.c,它只处理了字符串’\\’,单个’\’没有对应的处理逻辑。下面修改代码,将新修改后的代码命名为compile_new_b.c。

编程需要有编译器吗?程序是用编程语言写的(3)

代码 compile_new_b.c

其实compile_new_b.c只是更新了转义字符的语法,这是新编译器_a所支持的新的语法,下面还是以新编译器_a来编译新的编译器。

用新编译器_a编译此文件,将生成新编译器_b,将新的关系录入到表格中。

编译器自身源代码

编译器

应用程序源代码

输出文件名

compile_old.c

老编译器

compile_new_a.c

新编译器_a,支持’\\’

compile_new_a.c

新编译器_a

compile_new_a.c

编译失败

compile_new_a.c

新编译器_a

compile_new_b.c

新编译器_b,支持’\\’

继续之前啰嗦两句:用编译器去编译另一编译器的源码,也许有的同学觉得很费解,其实您把被编译的编译器源码当成普通的应用程序源码就特别容易理解了。上面的编译器代码compile_new_b.c,其第3、6、7行的字符串’\\’被新编译器_a处理后,会以单字符’\’来代替(这是新编译器_a源码中return语句的功能),因此最终处理完成后的代码等同于代码compile_new_a.c。

现在想加上换行符’\n’的支持:

编程需要有编译器吗?程序是用编程语言写的(4)

由于现在编译器还不认识’\n’,故这样做肯定不行,不过可以用其ascii码来代替,将其命名为compile_new_c.c。

编程需要有编译器吗?程序是用编程语言写的(5)

compile_new_c.c

用新编译器_a来编译compile_new_c.c,将生成新编译器_c,新编译器_c的代码相当于代码compile_new_c.c中所有’\\’被替换为’\’后的样子,如下所示,暂且称之为代码compile_new_c1.c:

编程需要有编译器吗?程序是用编程语言写的(6)

代码compile_new_c1.c

编译器自身源代码

编译器

应用程序源代码

输出文件名

compile_old.c

老编译器

compile_new_a.c

新编译器_a,支持’\\’

compile_new_a.c

新编译器_a

compile_new_a.c

编译失败

compile_new_a.c

新编译器_a

compile_new_b.c

新编译器_b,支持’\\’

compile_new_a.c

新编译器_a

compile_new_c.c

新编译器_c,间接支持\n

最后再修改compile_new_c.c为compile_new_d.c,将10用’\n’替代。

编程需要有编译器吗?程序是用编程语言写的(7)

代码compile_new_d.c

用新编译器_c编译compile_new_d.c,生成新编译器d,将直接识别’\n’。同理,新编译器d的代码相当于代码compile_new_d.c中,所有字符串’\\’被替换为字符’\’、字符’\n’被替换为数字10后的样子,即等同于代码compile_new_c1.c。

编译器自身源代码

编译器

应用程序源代码

输出文件名

compile_old.c

老编译器

compile_new_a.c

新编译器_a,支持’\\’

compile_new_a.c

新编译器_a

compile_new_a.c

编译失败

compile_new_a.c

新编译器_a

compile_new_b.c

新编译器_b,支持’\\’

compile_new_a.c

新编译器_a

compile_new_c.c

新编译器_c,间接支持\n

compile_new_c.c

新编译器_c

compile_new_d.c

新编译器d,直接支持\n

编译器经过这样不断的训练,功能越来越强大,不过体积也越来越大了。

累死哥了。

猜您喜欢: