当有人写一个新的编程语言,他们写什么?

请原谅我的无知。 我正在涉足PHP,并开始浏览所以我不得不提出一个我一直想知道的问题:

当你写一个全新的编程语言,你写什么

这对你们所有的程序员来说听起来都很愚蠢,对于这个程序员我非常尊敬,但是这对我来说是一个令人困惑的鸡与鸡蛋。 你是做什么? 对自己说, 今天我要发明一种新的语言! 然后启动…记事本? 所有的编译器都是build立在以前的现有语言之上的吗?如果有人打扰,可以将所有编程语言都绘制到一个可怕的分支树上,最终在… …我不知道,有点老了?

用我微弱的智慧,我觉得这个迷人的…请教育我!

这不是一个愚蠢的问题。 这是一个很好的问题。

正如已经回答的那样,简短的回答是“另一种语言”。

那么导致一些有趣的问题? 如果它是为你的特定硬件写的第一语言呢? 在embedded式设备上工作的人是一个非常现实的问题。 正如已经回答“另一台计算机上的语言”一样。 事实上,一些embedded式设备永远不会得到一个编译器,他们的程序将总是在不同的计算机上编译。

但是,你可以把它推回更远。 那写过的第一个程序呢?

那么“高级语言”的第一个编译器就会被写成所谓的“汇编语言”。 汇编语言是一种语言,其中每种语言的指令对应于CPU的单个指令。 它的语言水平非常低,而且非常冗长而且非常劳动密集。

但是,即使编写汇编语言也需要一个称为汇编程序的程序来将汇编语言转换为“机器语言”。 我们再往前走。 第一个汇编程序是用“机器代码”编写的。 一个完全由二进制数组成的程序,与计算机本身的原始语言直接一一对应。

但它还没有结束。 即使是只有原始数字的文件仍然需要翻译。 您仍然需要将这些原始数据存入计算机。

不要相信早期的电脑在它们前面有一排开关。 你翻转开关,直到它们代表一个二进制数字,然后你popup另一个开关,并将这个单一的数字加载到计算机内存中。 然后,你不断地轻弹切换,直到你加载了一个最小的计算机程序,可以从磁盘文件或穿孔卡读取程序。 你轻弹另一个开关,它开始运行程序。 当我在80年代上大学的时候,我看到有这种容量的计算机,却从来没有被赋予用交换机加载程序的工作。

而且甚至比计算机程序还要早到插接板的硬连线!

最常见的答案是C 大多数语言都是用C语言或C语言与callback函数以及像Flex这样的“词法分析器”和像YACC这样的分析器生成器的混合体来实现的。 这些是用于一个目的的语言 – 描述另一种语言的语法。 有时,在编译语言时,它们首先在C中实现,然后使用第一个语言版本来创build一个新的版本,依此类推。 (像Haskell一样)

很多语言都是自举的,都是自己编写的 。 至于你为什么要这样做, 吃自己的狗粮通常是一个好主意。

我提到的维基百科文章讨论了鸡和鸡蛋的问题。 我想你会觉得很有趣。

几乎任何语言,尽pipe使用适合于graphics和其他复杂数据结构的工作将使许多事情变得更容易。 由于性能原因,生产编译器通常用C或C ++语言编写,但OCaml,SML,Prolog和Lisp等语言对于原型语言来说可能更好。

语言devise中也有几种“小语言”。 Lex和yacc用于指定语法和语法,例如,它们编译为C.(其他语言也有端口,例如ocamllex / ocamlyacc以及许多其他类似的工具)。

作为一种特殊情况,新的Lisp方言通常build立在现有的Lisp实现上,因为它们可以搭载大部分相同的基础设施。 写一个Scheme解释器可以在一个代码页的Scheme中完成,在这一点上可以很容易地添加新的function。

从根本上讲,编译器只是读取某些内容并将其转换为其他内容的程序 – 将LaTeX源代码转换为DVI,将C代码转换为程序集,然后转换为机器语言,将语法规范转换为parsing器的C代码等。源格式(parsing)的结构,这些结构的含义,如何简化数据(优化)以及生成输出的types。 口译员阅读信息源并直接执行。 (译员通常比较容易写,但速度要慢得多。)

在技​​术上写“一种新的编程语言”不涉及任何代码。 它只是为您的语言的外观和工作原理制定一个规范。 一旦你了解你的语言是什么样子的话,你可以写译员和口译员,让你的语言“工作”。

翻译者用一种语言input程序,并以另一种语言输出等效程序。 解释器用某种语言input程序并运行它。

例如,C编译器通常将C源代码(input语言)翻译成汇编语言程序(输出语言)。 然后汇编程序拿出汇编语言程序并产生机器语言。 一旦你有你的输出,你不需要翻译员来运行你的程序。 由于你现在有一个机器语言程序,CPU作为解释器。

许多语言的实现方式不同。 例如, javac是将Java源代码转换为JVM字节码的转换程序。 JVM是运行Java字节码的解释器[1]。 运行javac并获取字节码后,就不需要javac了。 但是,只要你想运行你的程序,你就需要JVM。

翻译人员不需要随时随地运行程序的事实,使得“引导”你的语言成为可能,而不必让它在“其他语言层”上运行。

[1]大多数JVM在幕后进行翻译,但它们并不是真正的翻译者,因为JVM的接口不是“input语言 – >输出语言”。

其实你可以用任何你喜欢的语言写。 没有什么能够阻止你在Ruby中编写C编译器。 所有你需要做的就是parsing程序并发出相应的机器码。 如果你可以读/写文件,你的编程语言可能就足够了。

如果您是从一个新平台开始,可以进行交叉编译:为您的新平台编写一个编译器,这个编译器可以在Java中运行,或者在x86上运行。 在您的PC上开发,然后将程序传输到新的目标平台。

最基本的编译器可能是汇编和C

一般来说,你可以使用任何你喜欢的语言。 例如,PHP是用C编写的。 如果你无法使用任何编译器,你将不得不求助于编写汇编语言并手工编译成机器码。

通常使用适合系统开发的通用编程语言,例如C,Haskell,ML,Lisp等,但是选项列表很长。 另外,通常使用一些语言实现的领域特定语言,即parsing器和词法分析器生成器, LLVM等中间语言。可能还有一些shell脚本,testing框架和构buildconfiguration系统,例如autoconf。

许多语言首先用另一种可用的语言编写,然后自行重新实现并以这种方式引导(或者只是像PHP和Perl一样保持外语的实现),但是像第一个汇编程序那样的一些语言被手动编译为机器代码第一个C编译器被手动编译成程序集。

自从我读了这篇文章以来,我一直对引导感兴趣。 为了学习更多,我尝试自己编写自己的BF超集(我自己称之为EBF )。 EBF的第一个版本有3个额外的原语,我手编译了第一个二进制文件。 这样做的时候我发现了一个两步的节奏。 我在一个版本中使用当前语言实现了一个function,并且有一个甜蜜的版本,我重写了代码以利用实现的function。 这个语言足以expression出来用来做LISP翻译 。

在第一个版本标签中 ,我将手工编译版本与源代码一起使用,代码非常小。 最后一个版本的大小是12倍,而且代码更加紧凑,所以手工编译当前的版本很难。

Edmund Grimley Evans用HEX语言做了类似的事情

你自己做这件事有趣的事情之一是,你明白为什么有些事情是现实的。 我的代码是产品,如果小增量调整,它看起来更像是进化而不是从头开始devise的。 我今天在阅读代码的时候记住了这一点。

大多数编译器都是用C语言编写的,或者像程序一样,如果不是的话,那么汇编语言就是要走的路。但是,当从头开始编写一个新的语言库,并且没有原型语言的macros库或源代码时,您必须定义自己的函数现在用什么语言? 你可以直接写一个名为psedocode的源代码到机器上,它看起来像一个bnf文法,就像Fortran basic algo lisp这样的面向对象的结构化语言。因此,编写一个类似于任何这些语言语法的交叉代码这就是psedo代码

更进一步的二进制或汇编操作必须被转换成函数,即汇编器/编译器的工作,然后转换成对象,从数据和函数,如果你没有一个源文件来看“这些对象的function应该如何表示然后你必须认识“看”的实现,或者定义你自己的函数,过程和数据结构,这就需要很多的知识,你需要问自己什么是函数。然后你的心智就成了语言模拟。这将一个主程序员与其他人分开。

几个月前我也有过这个问题。 我读了几篇文章,看了一些video,帮助我开始写自己的软语言。 它还不完整,但我从这个旅程中学到了很多东西。

基本的东西你应该知道的是编译器如何执行代码片段。 编译器有很多阶段,如词法分析,语义分析器,AST(抽象语法树)等。

我用我的新语言做了什么可以在这里find – http://www.singhajit.com/writing-a-new-programming-language/

如果你是第一次写一种语言,那么一切顺利,你还有很长的路要走。