编写一种编程语言的建议?

16

你有什么建议可以给那些想要编写编程语言或脚本语言的人吗?我不担心如何编程或设计编译器,而是如何使用工具和代码生成器快速开发一个编程语言。

上次我尝试用c ++编写它,状态和语法几乎花费了与编写实际逻辑一样长的时间。我知道下面这些工具会有所帮助。

我在考虑是否可以生成c ++代码,并让gcc编译它。使用上述工具,您估计需要多长时间才能编写一个程序或脚本语言?


这个问题的变体一直以来都被反复提出,早在学习编写编译器时期就有了。以下是有关该主题的SO资源列表,但不完整


我已经尝试过清理这个问题了,但我可能会进一步修改它。 - mmcdole
好的,我重新聚焦标题...并删除了问题中多余的注释。我认为现在这是一个更好的问题。 - mmcdole
你的“重新聚焦”删除了提到antlr和它编译为C ++的想法等信息。我认为你可能编辑得太多了。 - Ned Batchelder
@Ned Batchelder,移除ANTLR是有意的。他列举了5种他“听说过”的编程语言,然后表示他以前从未使用过它们。这些语言与他关于编写语言的问题无关,也没有为他的问题增添任何内容。 - mmcdole
可能是创建自己的编程语言的重复问题。 - nawfal
10个回答

18

估算完成这样的工作需要考虑许多不同因素。例如,一位有经验的程序员可以在几个小时内编写一个简单的算术表达式求值器并进行单元测试,但是新手程序员可能需要学习解析技术、递归下降、表达式树的抽象表示、树遍历策略等等,仅仅为了处理算术表达式就可能需要花费数周甚至更长时间。

然而,不要因此而灰心。正如Jeff和Joel在最近的Stack Overflow podcast中与Eric Sink讨论的那样,编写编译器是学习编程的许多不同方面的绝佳方式。我已经构建了一些编译器,它们是我最难忘的编程项目之一。

关于构建编译器的一些经典书籍包括:


5
Dave Hanson和Chris Fraser花了10年时间打造世界上最精心制作的编译器之一,其中一个主要的教训是不要试图用C或C++编写编译器。
如果你想快速开发,不要生成本地代码;而是针对现有的虚拟机,如CLR、JVM或Lua虚拟机。使用最大匹配原则生成代码。
另一个很好的选择是,如果你正在编写解释器,只需使用底层编程语言的内存管理和其他设施。将其解析为AST,然后通过AST的树遍历进行解释。这将让你快速入门。性能并不是最好的,但是可以接受。(使用这种技术,我曾经在Modula-3中编写了一个PostScript解释器。第一次实现花了一个星期,尽管它后来在词法分析器方面进行了一些性能调优,但它从未被替换。)
避免使用LALR解析器生成器;使用一些可以节省时间的工具,例如ANTLR或Elkhound GLR解析器生成器。

有关 Postscript 解释器的更多信息吗?(我有一个收藏。) - luser droog
@droog 这是 ldb 的源代码的一部分。 - Norman Ramsey

3
我认为每个人都忽略了一个非常重要的点。
你想编写编译器/解释器/解析器等的原因是什么?
这将严重决定你所做的事情。
我曾经参与过很多语言实现,有些非常奇怪,有些是针对特定领域的,有些只是通过命令环境进行脚本化进展(通常后来隐藏了命令环境)。每个实现都需要不同水平的技能。
有许多书籍可供选择。我喜欢的一本是BYTE出版社的书:Threaded Interpreted Languages - 我敢打赌它已经绝版了。
简单的脚本引擎可以通过几个晚上的思考和一些试错来制作。
但我敢打赌现在有在线课程可以节省你大量时间。

3
经典的编译器设计书籍有:
- "编译原理" (Principles of Compiler Design) 作者:Alfred V. Aho 和Jeffrey D. Ullman。这本书已经存在了相当长的时间,其粉色骑士和绿色龙在至少几代计算机科学学生中非常著名。
- 另外一本是 "编译器: 原理、技术与工具"(Compilers: Principles, Techniques, and Tools) 的作者为Alfred V. Aho、Monica S. Lam、Ravi Sethi、Jeffrey D. Ullman。
如果你有兴趣编写编译器,那么这些无疑是最好的起点。

3
作为一个精通C++的人,你能给那些想要编写编程或脚本语言的人一些什么提示呢?
不要这样做。(或者至少要认真考虑!)
如果你想要编写一个脚本语言来公开一些自定义对象的方法/属性,最好的方法是在Java(或.NET/VB或所有这些令人讨厌的微软技术)中实现它们,然后使用Bean Scripting Framework语言作为你的脚本语言。(在微软端的等效物是什么则不得而知。)

2
@WimCoenen 如果有这样的想法,那么世界上可能应该停止改建筑物、汽车、手机、飞机、武器等等。如果有1,000个人做同样的事情,至少会有1个人最终冒险去看如何改进它。这就是所谓的进步。 - user868935
1
@SpicyWeenie:我的“思维方式”是,每个人都自己造车是低效的。低效会妨碍进步。 - Wim Coenen
1
@WimCoenen 认为每个人都想要建造自己的汽车是不合逻辑和毫无意义的。有些人喜欢设计概念、制造、重建、故障排除、维护以及简单地驾驶它。灯泡和电话被改进了多少次?按照你的过程来看,这将被视为低效。如果世界遵循你的模式,我们仍然会骑在马上用石头互相投掷和互相打击。你的模式不促进独创性和创造力,因为我们所认为理所当然的一切都源于之前的旧思想的重复。 - user868935
@SpicyWeenie:“认为每个人都想造自己的车是不合逻辑和没有意义的。”没错。把汽车制造留给那些有能力组建专家团队并进行创新的人,就像埃隆·马斯克在特斯拉汽车公司所做的那样。 - Wim Coenen
@WimCoenen 除了...编写编译器并不类比于制造汽车。你不需要大量的原材料、租用空间、无限的资金和一支专门的工程师团队仅仅为了建造一个原型,然后如果设计可行就进行批量生产。这就是编译器。这不是特斯拉汽车。 - eazar001
显示剩余3条评论

3

无论提出有关编译器的任何问题,SO上都会有一个答案:“去读龙书,读那本书,这本书……”不管问题内容如何,在几分钟内就会得到答案。所以我跳过了那部分(就像我一开始说的那样)。阅读这些书籍来学习如何使用你想要的工具,就像阅读角动量来学习如何骑自行车一样有用。

那么,回答你的问题,不质疑你的意图,我可以轻松推荐antlr和antlrworks作为入门工具。您可以轻松生成AST(我认为真正的魔力发生在这里),并通过可视化调试语法进行调试。它为您生成了一个工作编译器的很大部分。

如果您精通此领域并想要更多控制权或不喜欢antlr,则可以使用lemon解析器生成器和ragel状态机编译器(具有特殊支持词法分析)组合使用。

如果您不需要太高的性能,并且由于计划生成C/C++代码,您可以跳过自己进行任何优化,并将这些工作留给C/C++编译器。

如果您可以接受较慢的运行时间,您可以通过解释来进一步缩短开发时间,因为这种方法通常更容易实现动态功能。

2

我强烈建议您查看现有的字节码解释器。如果您的语言可以适应CIL (.NET)、Java(甚至其他如Python或Parrot),那么您将节省所有制作可行支持环境的工作量,并可以开始尝试语言概念的实验。


1
如果你打算编写一个解释器或编译器,不要仅仅因为你想写下一个大项目。写它是因为你已经有了一个明确的目的或者是为了学习。如果你这样做,你可能会意外地写出下一个大项目。

1

我用过的一个很好的LALR工具是GOLD Parsing System。它是免费的,语法是Backus-Naur Form,有多个示例,包括用C#、VB.NET、Java等编写的引擎。这使您可以编写语法,将语法编译为文件,然后使用引擎解析语法。

如上所述,我建议针对某种字节码,例如IL。这将使您能够利用现有框架的巨大数量。

祝你好运


0

如果您不想编写编译器将语言转换为汇编/机器码,那么您的下一个选择是编写编译器将其转换为字节码语言虚拟机,例如JVM、PVM或.NET。

当然,如果您甚至不想这样做——您只想创建自己的“领域特定语言”,我会在Common Lisp中构建它。Lisp宏提供了一种相当直接的方法来创建任何您想要的语法并将其解析为Lisp。而且您不必担心字节码或汇编。当然,您需要学习Lisp。


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