当有人写一门新的编程语言时,他们用啥来写?

Posted

技术标签:

【中文标题】当有人写一门新的编程语言时,他们用啥来写?【英文标题】:When someone writes a new programming language, what do they write it IN?当有人写一门新的编程语言时,他们用什么来写? 【发布时间】:2010-12-10 09:55:24 【问题描述】:

请原谅我的无知。我正在涉足 php 并开始涉足浏览 SO,并且不得不问一个我多年来一直想知道的问题:

当您编写一门全新的编程语言时,您会用什么编写它?

这对你们所有的程序员来说可能听起来很傻,我非常尊重他们,但对我来说这是一件令人费解的鸡和蛋的事情。你做什么工作?对自己说今天我要发明一门新语言!然后开火。记事本?是否所有编译器都建立在先前存在的语言上,这样一个令人费心的编译器可以将所有编程语言绘制到一个巨大的分支树上,最终扎根于......我不知道,有些东西旧的? em>

以我微弱的智力,我觉得这很有趣。请教教我!

【问题讨论】:

【参考方案1】:

通常您可以使用您喜欢的任何语言。例如,PHP 是用 C 语言编写的。如果您无法访问任何编译器,您将不得不求助于编写汇编语言并手动将其编译为机器代码。

【讨论】:

您不必编译机器代码。根据定义,它是 CPU 的本地语言。 是的。我的意思是“手动从汇编语言或类似的东西编译机器代码”。我可能是错的,但我猜很少有人直接将代码输入为二进制/十六进制。【参考方案2】:

最常见的答案是C。大多数语言都是用 C 或 C 与回调和“词法分析器”(如 Flex)和解析器生成器(如 YACC)的混合实现的。这些是用于一个目的的语言 - 描述另一种语言的语法。有时,当涉及到编译语言时,它们首先在 C 中实现。然后使用该语言的第一个版本来创建新版本,依此类推。 (比如Haskell。)

【讨论】:

有些语言是用汇编语言编写的,比如 picolisp。 (blog.kowalczyk.info/article/picoLisp-Arc-before-Arc.html) lex/yacc (flex/bison) 程序怎么样?这些是否被认为是用 C 创建语言的补充? 你有什么可以证明最常见的答案是 C 吗? 我在这里开始浏览列表:google.com/Top/Computers/Programming/Languages/Open_Source 然后我不小心在语言 10 左右关闭了我的编辑器窗口,失去了浏览的动力。无论如何,到目前为止,大约有一半是用 C 语言实现的,其余的大部分是自己引导的。 我认为你必须提到 Lex/Yacc(或替代品)。人们通常不会开始用 C 语言编写语言,而是使用词法分析器和解析器,然后 C 代码支持它们。【参考方案3】:

实际上,您几乎可以用任何您喜欢的语言写作。没有什么可以阻止您在 Ruby 中编写 C 编译器。您所要做的“全部”就是解析程序并发出相应的机器代码。如果你能读/写文件,你的编程语言可能就足够了。

如果您是在新平台上从头开始,您可以进行交叉编译:为您的新平台编写一个编译器,该编译器可以在 Java 中运行,也可以在 x86 上原生运行。在您的 PC 上开发,然后将程序转移到您的新目标平台。

最基本的编译器大概是Assembler和C。

【讨论】:

这种“任何”语言应该支持递归调用。否则实现语法分析器和解析器将是一个真正的挑战。 如果您为某项任务选择了不合适的语言,那是您自己的错。任何项目都可能发生这种情况,而不仅仅是编译器/解释器。【参考方案4】:

几乎可以使用任何语言,尽管使用适合处理图形和其他复杂数据结构的语言会使许多事情变得更容易。出于性能原因,生产编译器通常使用 C 或 C++ 编写,但 OCaml、SML、Prolog 和 Lisp 等语言可以说更适合语言的原型设计。

在语言设计中还使用了几种“小语言”。例如,Lex 和 yacc 用于指定语法和文法,它们编译为 C。(还有其他语言的端口,例如 ocamllex / ocamlyacc 和许多其他类似工具。)

作为一种特殊情况,新的 Lisp 方言通常建立在现有的 Lisp 实现之上,因为它们可以搭载大多数相同的基础架构。编写 Scheme 解释器可以在 Scheme 中的一页代码下完成,此时可以轻松添加新功能。

从根本上说,编译器只是读取某些内容并将其转换为其他内容的程序 - 将 LaTeX 源代码转换为 DVI,将 C 代码转换为汇编,然后转换为机器语言,将语法规范转换为解析器的 C 代码等。它的设计者指定了源格式的结构(解析)、这些结构的含义、如何简化数据(优化)以及要生成的输出类型。解释器读取源代码并直接执行。 (解释器通常更容易编写,但速度要慢得多。)

【讨论】:

【参考方案5】:

很多语言都是自举的——即written in themselves。至于为什么要这样做,eat your own dogfood 通常是个好主意。

我参考的***文章讨论了the chicken and egg 问题。我想你会觉得这很有趣。

【讨论】:

这在你刚开始的时候是不可能的。 是的——很明显。但是一旦有可能,很多语言都是以这种方式编写的。我想以其他人没有的方式指出这一点,我觉得这很重要。 +1 用于使用术语引导程序。有趣的是你必须编译你的编译器两次。第一次显然是使用您拥有的准系统编译器,第二次使用您刚刚构建的编译器。假设您为编译器添加了优化。您构建的编译器可以生成具有这些优化的代码,但它本身不会运行优化的代码,直到您使用优化编译器再次编译它。 @Les- 是的,引导是一个有趣的概念。 这里随机评论。关于谁先来(鸡还是鸡蛋)这个古老问题的答案是鸡先来。原因是要复制/复制某些东西,您必须首先拥有复制器/复制器才能进行复制/复制。【参考方案6】:

通常使用适合系统开发的通用编程语言,例如C、Haskell、ML、Lisp 等,但选项列表很长。此外,通常使用一些特定于领域的语言进行语言实现,即解析器和词法分析器生成器、LLVM 等中间语言等。可能还有一些 shell 脚本、测试框架和构建配置系统,例如自动配置。

【讨论】:

【参考方案7】:

“编写一种新的编程语言”在技术上不涉及任何代码。它只是针对您的语言的外观及其工作方式提出规范。一旦您了解自己的语言是什么样的,您就可以编写笔译员和口译员来真正让您的语言“工作”。

翻译器输入一种语言的程序并输出另一种语言的等效程序。解释器输入某种语言的程序并运行它。

例如,C 编译器通常将 C 源代码(输入语言)翻译成汇编语言程序(输出语言)。然后汇编器获取汇编语言程序并生成机器语言。一旦你有了你的输出,你就不需要翻译器来运行你的程序了。由于您现在有一个机器语言程序,CPU 充当解释器。

许多语言的实现方式不同。例如,javac 是一个将 Java 源代码转换为 JVM 字节码的转换器。 JVM 是一个运行 Java 字节码的解释器 [1]。运行javac 并获取字节码后,您不再需要javac。但是,无论何时要运行程序,都需要 JVM。

翻译者不需要在身边运行程序这一事实使得它可以“引导”您的语言,而不会最终“在”其他语言的层和层上运行。

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

【讨论】:

【参考方案8】:

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

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

这会引出一些有趣的问题吗?如果它是第一种语言会怎样? 您的特定硬件?对于在嵌入式设备上工作的人来说,这是一个非常现实的问题。正如已经回答的“另一台计算机上的语言”。事实上,有些嵌入式设备永远不会有编译器,它们的程序总是在不同的计算机上编译。

但你可以把它推得更远。曾经编写的第一个程序呢?

“高级语言”的第一个编译器应该是用所谓的“汇编语言”编写的。汇编语言是一种语言,其中语言中的每条指令对应于 CPU 的一条指令。它的语言非常低级,写起来非常冗长且劳动强度大。

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

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

不管你信不信,早期的计算机前面有一排开关。你拨动开关,直到它们代表一个二进制数,然后你拨动另一个开关,然后将那个单一的数字加载到计算机内存中。然后你一直在轻弹切换,直到你加载了一个可以从磁盘文件或穿孔卡片中读取程序的最小计算机程序。你轻弹了另一个开关,它开始运行程序。当我在 80 年代上大学时,我看到了具有这种能力但从未被赋予使用开关加载程序的工作的计算机。

在此之前,计算机程序必须与plug boards 硬连接!

【讨论】:

+1,我觉得这个答案很符合题主的意思。 我曾经上过汇编 II 课,教授问我们为什么选择选修课。我找到了一个有趣的答案:“因为我想要一个简单的 A。”以为我有最好的答案,但我们在城里有一家霍尼韦尔工厂,旁边的人说“我整天都在写微代码,我想学习一门高级语言。” 我强烈推荐代码:计算机硬件和软件的隐藏语言。它基本上涵盖了与此答案相同的材料,从真空管一直到高级语言的编译器。 计算机的进化与人类一样,尽管时间相对较短。 现在这将是一个非建设性的评论,但它必须写出来......这是一个各种形式、形式和信息的绝妙答案:-)【参考方案9】:

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

自从我读到引导程序以来,我就一直对它感兴趣。为了了解更多信息,我尝试自己编写自己的 BF 超集,我称之为 EBF。 EBF 的第一个版本有 3 个额外的原语,我手动编译了第一个二进制文件。这样做时,我发现了两步节奏。我在一个版本中以当前语言实现了一项功能,并发布了一个甜蜜的版本,我重写了代码以利用已实现的功能。该语言具有足够的表现力,可以用来制作LISP interpreter。

我有手工编译的版本以及first release tag中的源代码,代码很小。最后一个版本的大小和代码大了 12 倍,并且允许更紧凑的代码,因此手动编译当前版本很难正确。

Edmund Grimley Evans 对 his HEX language 做了类似的事情

你自己做这件事的一个有趣的事情是你明白为什么有些事情是这样的。如果进行小的增量调整,我的代码就是产品,它看起来更像是经过进化而不是从头开始设计的。我今天在阅读代码时牢记这一点,我认为这看起来有点不对劲。

【讨论】:

【参考方案10】:

大多数编译器都是用 C 或 ac 编写的,如果不是 c,那么汇编语言是可行的方法 但是,当从头开始编写新语言并且您没有宏库或原型语言的源代码时,您必须定义你自己的函数现在用什么语言?您可以只向机器编写一个名为 psedocode 的源代码形式,它看起来像来自面向对象的结构化语言规范(如 Fortran 基本算法 lisp)中的 bnf 语法。所以图像编写类似于任何这些语言语法的交叉代码那是 psedo 代码

【讨论】:

我不认为伪代码应该是机器可读的【参考方案11】:

如果您没有源文件可以查看“这些对象的功能应该如何”,则更进一步的二进制或汇编操作必须转换为函数,这是汇编器/编译器的工作,然后从数据和函数转换为对象在你的语言实现中表示,然后你必须识别“看到”实现,或者定义你自己的函数、过程和数据结构,这需要很多知识,你需要问自己什么是函数。你的头脑就会变成语言模拟。这将大师级程序员与其他人区分开来。

【讨论】:

【参考方案12】:

几个月前我也有这个问题。我阅读了几篇文章并观看了一些视频,这些视频帮助我开始编写自己的语言,称为软。它还没有完成,但我从这次旅程中学到了很多东西。

您应该知道的基本知识是编译器在必须执行代码 sn-p 时是如何工作的。编译器有很多阶段,如词法分析、语义分析器、AST(抽象语法树)等。

可以在这里找到我用新语言所做的事情 - http://www.singhajit.com/writing-a-new-programming-language/

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

【讨论】:

【参考方案13】:

一般来说什么是编程语言?

编程语言只是与计算机对话的一种方式。一开始粗略地说,因为计算机只能理解 0 和 1(由于计算机是由晶体管作为开关组成的,只能采用两种状态,我们将这两种状态称为 0 和 1)并且使用 0,1 很难我们作为人类,因此计算机科学家决定将二进制(0,1)中的每条指令一对一映射到他们称之为汇编语言的更人类可读的形式。

例如,如果我们有这样的指令:

11001101

在汇编中它会被称为:

LOAD_A 15

这意味着将寄存器 a 的内容加载到内存位置 15。正如我所说,这只是一个约定,比如为晶体管的两种状态或计算机中的任何其他状态选择 0 和 1。这样就有一个程序50条指令,记住汇编语言会更容易。因此用户将编写汇编代码,而某些程序(在这种情况下为汇编程序)会将代码转换为他们所称的二进制指令或机器语言。

但是随着计算机每天都在改进,有更多的指令空间可以容纳更复杂的程序,比如 10000 条指令。

在这种情况下,像汇编这样的一对一映射将不起作用,因此创建了其他高级编程语言。他们说,例如,如果与 I/O 设备的关系在用户创建的屏幕上打印某些东西需要大约 80 条指令,让我们在这里做一些事情,我们可以将所有这些代码打包到一个库中并调用它,例如 printf并创建另一个程序,该程序可以将此处的 printf 转换为相关的汇编代码,然后汇编将完成其余的工作。所以他们称之为编译器。

所以现在每个只想在屏幕上打印内容的用户都不必用二进制或汇编语言编写所有指令,他只需键入 printf("something") 和编译器和汇编器等所有程序即可其余的部分。现在稍后其他更长的代码将以相同的方式打包以方便其他人的工作,因为您可以将数千行代码简化为 python 中的一个代码并将其打包以供其他人使用。

假设你已经在 python 中打包了很多不同的代码并创建了一个模块(库、包或任何你想调用它的东西),你把那个模块叫做 mgh(只是我的名字)。现在假设我们以某种方式创建了这个 mgh,任何人说:

import mgh
mgh.connect(ip,port.data)...

可以通过指定的 ip 和端口号轻松连接到远程服务器,然后发送数据(或类似的东西)。现在人们可以使用一行代码来完成所有这些工作,但是会发生很多从 mgh 文件中检索到的代码正在执行。和打包它并不是为了加快执行过程,而是为了方便其他程序员的工作。所以在这里如果有人想先使用你的代码,他应该导入文件,然后python解释器会识别其中的所有代码,所以它可以解释代码。

现在如果你想创建一种编程语言并且你想执行它,首先它需要翻译,例如,假设你创建了一个可以理解语法并将其转换为 c 的程序,在这种情况下是在它之后已翻译成 c ,其余部分将由 c 编译器处理,然后由汇编器、链接器、...处理。 即使你必须付出变慢的代价,因为它必须先转换为 c。

现在您可以做的另一件事是创建一个程序,该程序可以将所有代码翻译成等效的汇编语言,就像 c 发生的那样,但在这种情况下,程序可以直接执行此操作,其余的将是由链接器完成。我们知道这个程序叫做编译器。

所以我要说的是,系统理解的唯一代码是 0,1 ,所以你应该以某种方式将你的语法转换为那个,现在在我们的操作系统中有很多不同的程序,比如汇编器、链接器和 . .. 的创建是为了告诉您,如果您可以将代码转换为汇编,他们可以处理其余部分,或者正如我所说,您甚至可以通过将代码转换为该语言来使用其他编程语言编译器。

【讨论】:

以上是关于当有人写一门新的编程语言时,他们用啥来写?的主要内容,如果未能解决你的问题,请参考以下文章

你用啥来单元测试C代码? [复制]

用啥来替换python中的接口/协议

手机脚本一般用啥写

学c语言和算法时,请问用啥编辑器或工具写伪代码?又如何和真正的代码以及流程图配合使用呢?

如果我不能使用 WebRTC,我现在可以用啥来直播视频

在我的 Qt 应用程序中,我可以用啥来代替 sleep 和 usleep?