Compiler construction 在运行时扩展我的语言

Compiler construction 在运行时扩展我的语言,compiler-construction,interpreter,vm-implementation,Compiler Construction,Interpreter,Vm Implementation,我正在开发一种新的语言,并遵循传统方法: 所以有一个lexer、一个解析器、一个ast和一个执行字节码的虚拟机 当解析器遇到像+这样的运算符时,它会生成一条ADD虚拟机指令,到目前为止一切都正常工作 我想为最终用户提供一种扩展语言的方法,例如,用户可以添加操作符++函数,以便创建自己的增量后操作符。 我不确定正确的方法是什么,因为解析器无法预先知道用户可以添加的所有运算符,所以我想问一下正确的方法是什么。您可以快速完成:在语法中包含运算符声明 在Swift中,它看起来像: infix opera

我正在开发一种新的语言,并遵循传统方法: 所以有一个lexer、一个解析器、一个ast和一个执行字节码的虚拟机

当解析器遇到像+这样的运算符时,它会生成一条ADD虚拟机指令,到目前为止一切都正常工作

我想为最终用户提供一种扩展语言的方法,例如,用户可以添加操作符++函数,以便创建自己的增量后操作符。
我不确定正确的方法是什么,因为解析器无法预先知道用户可以添加的所有运算符,所以我想问一下正确的方法是什么。

您可以快速完成:在语法中包含运算符声明

在Swift中,它看起来像:

infix operator SomeToken { associativity left precedence 150 }
这告诉Swift解析器SomeToken将是一个左联想中缀运算符,并且在任何基于优先级的决策中,该运算符的权重为150。其他运算符将具有更高、更低或相等的优先级度量,这将指导解析器创建AST

,例如在C#中,可以重载的运算符列表是预先知道的,并且重载总是通过使用特殊关键字
operator
来指示,因此解析器已经知道用户正在“添加”运算符。

例如,在Prolog中,可以使用
op(优先级、类型、名称)
指令动态地将新运算符及其求值优先级添加到语言中。Prolog解析器逐行读取并计算输入。每个“行”都以


请参见

使语言无限可扩展的一种方法是允许完整的自反元编程,如Common Lisp或Forth。通过这种方式,用户将能够在现有核心语言的基础上构建任意数量的额外转换,重用该语言中已有的所有内容,包括所有以前的扩展,以实现此类转换


如果你想扩展语法,而不仅仅是语义,你可能想考虑去掉你的词法,而使用一种强大的无需分析的方法,即。一些语言已经在这样做(,)。

本质上,运算符重载将运算符转换为函数调用,但由于您所述的确切问题,很少有语言允许添加新运算符;甚至C++,以它的“厨房沉没”的概念而闻名,它只允许某些现有的操作员超载,并且它们的解析行为是不能改变的。我非常喜欢斯卡拉的方法,其中所有的方法都是操作符,反之亦然。