人们如何创建新的编程语言?

我是新手程序员,学习C.

总是让我感到困惑的是人们如何创建新的编程语言?

子/相关问题:

  1. 他们用什么语言写的?
  2. 语言必须是高级语言和机器代码之间的语言吗?
  3. 创建编程语言的阶段/元素是什么?例如 – C或C ++(从我的基础研究中我已经意识到所有编程语言都需要编译器或解释器,但我并不真正理解这两者之间的区别)

正如我所说,我是一个完整的新手,但我对编程非常感兴趣,并且真的想了解更多。 我就像一个真正的垃圾网球运动员,想要了解网球的一切! 我在Google上搜索过它,但无法得到满意的答案。

它可以让您了解计算机的起始位置以及它们的进展情况以及它们的进展情况。

如果你想进入计算机的历史,我会看看诸如提花织机和巴贝奇差异引擎之类的东西。 这两项发明可能对早期现代计算产生了最大的早期影响。 使用穿孔卡(Jacquard)和机械’计算’(Babbage)提供了很好的基础。

那么让我们从计算机的工作原理开始吧。 每台计算机的核心都是晶体管(之前是真空管)。 晶体管背后的重要一点是,它可以通过两种不同的方式发电,具体取决于它的状态*。 这允许创建逻辑电力流。 有了这个,我们可以创造各种奇妙的东西**:nand gate,gate,half adders,multiplexes等。

现在我们已经有了这些电子构建块,基本上有两种类型的信号进入它们。 告诉电子设备做什么的信号,以及电子设备计算的实际数据。 所以要添加的命令,可以说从寄存器1获取数据,并将其添加到寄存器2中的数据,并将该信息存储在寄存器3中。该命令的作用是将计算机设置为处于寄存器1的状态和2表示加法器的输入,寄存器3存储结果。 对于减法乘法等也是如此。还有一些命令可以说跳转到某一行,从内存中读取信息等。

二进制命令这些二进制命令是’设置cpu所必需的机器代码。

到目前为止,我还没有真正解决你的问题,但我已经奠定了一些框架来了解正在发生的事情。 (你说你想学习一切= P)

所以现在我们有一台运行在机器代码上的计算机。 更不用说了。 这是一台非常难以使用的机器。 因此,汇编几乎总是最先创建的语言之一。 要使用程序集,我们需要创建一个汇编程序。 汇编程序本质上是一个编译器,它将汇编语言转换为机器代码。 因此,使用机器代码命令,汇编语言为1比1。 这个想法是因为我们用二进制编码,所以保持简单是个好主意。 所以现在我们有了一些可以将汇编语言变成机器代码的东西。

所以现在我们有两个级别的’语言’0 – 机器代码:这是cpu理解的代码,它是二进制的,而不是非常用户友好的1 – 汇编语言:这使用了一些“英语类似”的术语,但仍然是相对的笨重的,用机器代码1到1命令。

所以让我们添加第三个,

2-高级语言。

高级语言更接近于英语,例如C语言。我们有循环和数据结构以及其他有用的东西。 要使用C,我们必须编写一个编译器。 编译器接受用C语言编写的代码并创建目标代码(类似于汇编语言)。 然后另一个程序将该目标代码转换为机器语言。 为了提高效率,这两个步骤通常组合成一个。 现在我们有了你的第一个定义。 编译器将高级语言转换为对象(或机器)代码***。

现在我们有了第一个高级语言(C),除非我们必须再次使用汇编语言,否则看起来很愚蠢和痛苦。 所以现在我们可以用C语言编写新的语言和编译器,或者我们现在制作的任何其他语言****。

所以现在让我们撕成一名翻译。 解释器是一个程序,它自己读取并执行程序。 这不是将一个将高级代码转换为机器代码的程序,而是读取高级代码(通常一次一行)并执行它。

我们以java为例。 Java是一种解释型语言,基本上这意味着有人创建了一个程序(比方说C)这个C程序,读取java并执行它。 所以计算机和代码之间还有另一层。

有很多东西,这种响应类型的釉,如何构建一个CPU,制作语言的考虑因素,相同的语言如何在不同的cpu上运行。 解释器优于编译器等等。但希望它能提供大量的背景和信息,您可以自己阅读和研究。

1)他们用什么语言写的?

这完全取决于程序员。 在C,C ++上实现了几种语言。 其他几个人都是自助式的。 ( C用C语言写成 )。 链接的摘录:

Bootstrapping: Basically you start with a very minimal process/set of functions that can be used to compile the code that defines a slightly more functional compiler. This creates your next compiler which then can then be used to build code that can do even more. You repeat this process until you have a full blown compiler that can compile all the language features. 

实际上,它是用某种语言编写的compilerinterpreter compiler 。 例如, Go是一种语言,有两个编译器, gcgccgogc是用C语言编写的, gccgo是一个主要用C++编写的gcc前端。

2)语言必须是高级语言和机器代码之间的语言吗?

不必要。 如前所述,编译器或解释器也可以用高级语言编写。 编写语言基本上意味着为您的语言定义一组规则,或者描述您的语言规范。

3)创建编程语言的阶段/元素是什么?例如 – C或C ++(从我的基础研究中我已经意识到所有编程语言都需要编译器或解释器但我并不真正理解它们之间的区别二)

简单来说 :

  1. 准备您的语言的语义。 为您的语言绘制语法。
  2. 确定您的语言是使用编译器还是解释器。
    两者之间的差异(更多关于这里的差异部分。 ):

在解释的世界中,您的用户通常会在编辑器中编辑您的程序,并直接在解释器上运行它; 在编译世界中,您的用户将编辑您的程序,编译它,将生成的可执行文件保存在某处并运行它。

编译器将整个程序作为输入。 解释器将单个指令作为输入。

在编译器中检查整个程序后显示错误,而对每个解释的指令(如果有)显示错误。

  1. 写前端:用户将如何看到错误,警告等。

  2. 使用解析器信息来编写目标代码或中间表示。

  3. 编写将所有内容绑定在一起的执行程序或代码生成器。

  4. 测试和文档。

关于你的第一个问题。 所有语言都需要编译器,这是正确的,但是每种语言都有自己不同的编译方式。 例如,Java使用JDK进行编译并使用JVM来执行。 无论您编写哪种语言(如同高级语言一样),您将拥有将代码转换为机器代码(也称为二进制代码)的中间层。 那些中间层是用中级语言制作的(有很多中间版本,你可以在这里阅读它们http://en.wikipedia.org/wiki/Timeline_of_programming_languages )并且在今天最常用于低级编程(仍然不是机器代码)是C.

就像第一个答案一样,有不同的编程语言级别,但您需要记住的第一个也是最重要的事情是计算机理解二进制代码,即1或0,并且1和0字符串的系列一起定义程序的作用。 计算机所做的一切都可以减少到它。

到目前为止,我希望我已经回答了你的两个问题。

关于第三个,技巧总是在编译器中,如果你想要一个新的编程语言,你需要一个编译器,这样你就可以将你的代码转换成机器代码。 您现在可以看到的所有内容,例如在编译代码之前带有颜色和错误validation的某些关键字,这些都是IDES(您可以在这里阅读它们http://en.wikipedia.org/wiki/Integrated_development_environment )。

例如,如果你想要“兔子”作为你的代码中的关键词,并且你也希望兔子只是在逗号之后使用,那么编译器应该是一个中间层程序,通过阅读你的代码来确定它是否被正确使用。

编译器有不同的阶段:您需要能够读取代码并确定所有依赖项(代码中编写的其他文件)和当前代码行是否正常。 之后,您需要将“兔子”转换为您希望程序每次使用时都要执行的操作。 最后,您将生成一个文件,可以由机器或您自己的其他应用程序直接读取,因为Java使用JVM。

希望这会给你一些启发。

1)他们用什么语言写的?

无论他们想要什么; 这取决于语言的重点和他们使用的任何东西。 您可以编写从汇编到Haskell的任何编译器。 这取决于实现需要多复杂,这取决于您正在创建的语言规则。 例如,编写C编译器相对容易,因为语言规则相当简单。 C ++。 没那么多。

2)语言必须是高级语言和机器代码之间的语言吗?

不。 编译器只是另一个程序 ; 它读入一堆文本并发出另一个文本文件或机器代码的二进制文件。 它不必用低级语言编写。 许多编译器都是用C语言编写的,因为这是很多人最了解的,但这并不意味着所有编译器都必须编写C语言或汇编语言。 使用更高级别的语言可能会使任务变得更容易。

3)创建编程语言的阶段/元素是什么?例如 – C或C ++(从我的基础研究中我已经意识到所有编程语言都需要编译器或解释器但我并不真正理解它们之间的区别二)

通常,解释器翻译时运行程序,而编译器只是在不执行代码的情况下翻译代码。 这条线现在非常模糊(例如,Java代码被编译为与平台无关的字节代码,然后由JVM 解释为本机机器代码)。

编译器的重要部分是:

  • 词法分析器 ,将源文本分解为标记 (文字,标识符,标点符号等);
  • 一个解析器 ,它接受这些令牌并将它们与语言语法相匹配;
  • 代码生成器 ,它根据解析器的结果发出目标代码。

代码生成器还可以包含某种优化逻辑,以生成比源代码的字面翻译更有效的机器代码。 例如,当你将某个东西乘以整数字面时,gcc会做一个简洁的小技巧,比如i = a * 10 ; 而不是生成代码

 movl a, %edx ;; write value of a to register edx movl $10, %eax ;; write value of 10 to register eax imull %edx, %eax ;; multiply %edx by %eax, store in %eax 

它会产生

 movl a, %edx ;; same as above movl %edx, %eax ;; copy %edx to %eax sall $2, %eax ;; shift %eax left by 2 places, effectively multiplying by 4 addl %edx, %eax ;; add %edx to %eax addl %eax, %eax ;; double %eax 

如果a3 ,那么这就给了我们

  3 << 2 == 12 12 + 3 == 15 15 + 15 == 30 

对于某些硬件,与乘法相比,移位和加法相对较快,因此即使它看起来效率较低,因为有更多指令,它实际上比天真的imull调用执行得快一些。

我差不多30年前在夏季会议1上参加了一个编译器课程,所以我的技能并不完全是最新的。 但是重要的事情并没有真正改变。 创建新语言的艰苦工作是:a)决定你想要它做什么,b)提出一个人类可读且相当容易解析的语法,以及c)使语义正确。


1.不要这样做。 编译器构建将是CS课程中较为严格的课程之一,不应在短期内进行。

这是一本很棒的书,可以帮助您入门http://www.amazon.com/Language-Implementation-Patterns-Domain-Specific-Programming/dp/193435645X/

构建语言的阶段是

  1. 乐行。 Lexing意味着能够阅读某些类别的令牌。 令牌可以是一系列数字12376或文本字符串,如“Hello”。 lexing查看第一个角色(也可以向前看第二个角色)来确定它是什么。 在数字的情况下,它看到一个数字然后继续读取一系列数字(通过调用子程序),或者在字符串的情况下它看到一个引号然后继续读取一个字符串。 词法分析器的结果是一个标记,它是一种类型(本例中的数字或字符串)和标记的文本。 这通常存储在结构中作为Kind int和Text字符串,其中常量声明为表示种类。

  2. 下一个构建块是解析器。 解析器会看到一系列标记,因此它可能会看到标识符然后向前看会看到=。 然后它将分支到一个任务。 解析器构建一棵树。 在赋值的情况下,它将构建“assign”类型的“节点”,然后它将标识符存储在第一个子节点中,表达式存储在第二个子节点中。 所有树节点都是“操作”,这意味着它们可以执行某些操作。 你不只是一个字符串或整数作为节点,你将“添加”或“追加”等作为节点(除非它是一个表达式,但表达式包含在操作中)。

  3. 最后一部分是执行。 这是通过遍历树并执行节点来完成的。

还有很多其他机器,如Memory,Scope和前瞻机器。 这在上面的链接中解释。