编程语言和编译器

7

我和朋友正在讨论一个问题,认为这可能是询问此问题的最佳场所?

新语言是如何产生的?这个新语言NEW必须用某种旧语言OLD来编写(例如C++在初始阶段是用C语言编写的),或者它是如何创建的?同时,如果没有针对该语言NEW的编译器,那么该语言NEW如何能够自行运行?因此,必须有一个编译器。那么谁会为其编写编译器呢?

所以,所有这些是如何协同工作的,新语言及其编译器,与其旧基础语言的关系是什么?


1
感谢大家如此迅速的回复。我想我需要一门编译器设计课程。但是,我很好奇你们怎么能如此快速地回复,我的意思是在1-2分钟内,这非常惊人? - seg.server.fault
2
我们都渴望声望点数。请给我们点赞! :-) - Norman Ramsey
@Norman:我是 SO 的新手,对声望并不了解。有时间我会去看看的。我想你现在很开心吧。 :) - seg.server.fault
6个回答

5
你需要使用实现语言编写编译器,直到编译器可以开始编译足够多的新语言代码以用于实现新语言的其余部分。
这就是它的工作原理。
编辑:为了澄清,此回答的评论者也是正确的。编译器并不一定必须用新语言编写,除非你想要这样做。正如所说,有些人不采取这种方法,而是继续使用原始实现语言。

是的,这就是要点。有些人认为,除非可以使用该语言编写自己的编译器,否则它不是真正的语言 :) - wcm
补充Scyllinice的回答:当然,并不是所有语言都可以这样做,很多LISP变体都是纯解释器,没有创建可执行文件的能力,而LISP编译器可以用几乎任何语言编写。OLD和NEW语言实际上并不需要有任何真正的联系。 - Mike
尽管如此,您不一定需要迁移到原始实现语言之外。例如,Tcl和许多(大多数?)脚本语言在新语言成熟稳定后仍使用C或C ++实现语言。 - Bryan Oakley

2

引导是计算机科学中用来描述编写编译器(或汇编器)的技术,其目标是将编译器编写成目标编程语言。这种技术也被称为自举。


1

1
任何编程语言的核心都是链接器和编译器,编译器将源代码转换为中间代码,非常接近机器码。从这个点开始,链接器用于将其附加到其他二进制文件(如库等)。在所有逻辑部分链接到二进制文件之后,它们就成为了机器码的可执行文件(或者像.NET/Java一样的可翻译中间代码)。
大多数“人类”英语到机器语言的翻译都发生在编译器中,有很多关于如何完成这项工作的文章...但对于大多数人来说,这是超自然领域,因为编写一个工作的编译器所需的组织技能是巨大的。
您可以通过查看语言定义(Bjarne Stroustrup的《C++程序设计语言》、Microsoft Press的《C#程序设计语言》)来了解表面级别的翻译,并更深入地了解编译器的工作方式,在其中附录和散布着词汇片段或规则,编译器将使用这些规则以非常逻辑的方式将您的单词翻译成机器码。
如果您希望了解更多信息,我强烈建议阅读您最喜欢的编程语言的语言定义,同时维基百科上的编译器文章也会给您更广泛的了解。

1
我不同意“编写工作编译器所需的组织技能是巨大的”这个说法。在我刚离开大学几年,从未上过编译器课程的时候,我就能够使用lex和yacc创建一种特殊用途语言。虽然困难,但远非难以想象。实际上,这是非常有益的。 - Bryan Oakley
@Bryan: 这取决于情况。如今的编译器生成工具使得创建一个小语言(例如许多特定领域的语言)变得相当容易,但是@Sprague假设你想要创造更重量级的东西。一旦你添加了所有优化、代码生成等方面所需的内容,就像Python、Java或C#这样的主流编程语言,工作量就会变得非常大。此外还有VM设计、GC算法、标准库等相关任务... - Jim Ferrans

1

好问题!

  • 有时,新语言的编译器是用旧语言编写的。

  • 如果新语言N的编译器是用N编写的,则有许多策略,所有这些策略都涉及找到一种在没有编译器的情况下运行语言N程序的方法。

    1. 为语言N编写一个解释器,比如用C(真正的选择语言)编写解释器,然后使用解释器来解释编译器编译自身。

      • 为N编写一个非常糟糕的编译器,比如用C编写,然后使用该编译器来编译编译器的第一个版本。

      • 手工将编译器的第一个版本编译成汇编代码或C代码。

我最喜欢的是策略#1,但它们都有效。

如果您希望深入了解此问题的解决方案,请查看安德鲁·阿普尔(Andrew Appel)的短篇论文 Axiomatic Bootstrapping: A Guide for Compiler Hackers,可从普林斯顿网站免费获取。该论文非常数学化,但在相关工作部分,您将找到参考旧论文的引用,其中包括使用 T-diagrams 显示引导过程的论文,这些论文让许多人感到非常直观。


0

一种编程语言通常只是一个规范。任何一种语言都可以编写成使用你选择的语言的编译器或解释器。首先,我们使用机器代码编写了编译器或解释器。然后出现了汇编语言,然后是其他像C这样的语言。自那时起,C(和C ++)一直是实现一种语言的流行选择。但是C和C ++并不是唯一的选择。

值得指出的是,通常可以使用专用语言(或语言)(如yacc和lex)来实现语言。这些是特定领域的语言,专门设计用于根据规范轻松创建编译器。这消除了手动编写许多可以轻松由计算机生成的代码的乏味。您将规范通过这些工具运行,然后生成实现您的语言的代码。Yacc代表Yet Another Compiler-Compiler。它编译编译器的规范并生成编译器。

其他作者建议,一旦语言足够稳健,编译器就可以被移植到其自身,但这并非必要。许多语言在十年或更久以前用C编写,并且今天仍在C中实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接