我一直在考虑创建一种非常适合创建DSL的语言,允许定义中缀,后缀,前缀或甚至包含多个单词的函数。例如,您可以按如下方式定义中缀乘法运算符(其中已定义了乘法(X,Y)):

a * b => multiply(a,b)

或后缀“平方”操作者:

a squared => a * a

或者是C或Java风格的三元运算符,它包含两个散布着变量的关键字:

a ? b : c => if a==true then b else c

显然,在这种语言中存在大量的歧义空间,但如果它是静态类型的(使用类型推断),那么大多数歧义都可以被消除,而剩下的那些可以被认为是语法错误(由在适当的地方添加括号。)

是否有某种原因我没有看到这会让这非常困难,不可能,或只是一个简单的坏主意?

编辑:很多人都指出了可以做到这一点或类似事情的语言,但实际上我对如何为它实现自己的解析器的指针感兴趣,或者如果这样做我可能遇到的问题。

有帮助吗?

解决方案

这并不难做到。您需要为每个运营商分配 fixity (中缀,前缀或后缀)和优先级。将优先级设为实数;你以后会感谢我的。优先级高的运算符比优先级较低的运算符绑定得更紧密;在相同的优先级,您可以要求用括号消除歧义,但您可能更愿意允许某些运算符关联以便您可以编写

x + y + z

没有括号。一旦您拥有每个运算符的固定性,优先级和关联性,您就需要编写运算符优先级解析器。这种解析器相当简单;它从左到右扫描令牌并使用一个辅助堆栈。龙书中有一个解释,但我从未发现它非常清楚,部分原因是龙书描述了一个非常一般的运算符优先解析案例。但我认为你不会觉得困难。

另外一个你需要注意的案例是

prefix (e) postfix

其中前缀 postfix 具有相同的优先级。这种情况还需要括号来消除歧义。

我的论文使用前缀和后缀操作符取消表达式后面有一个示例解析器,你可以下载代码,但它是用ML编写的,所以它的工作对业余爱好者来说可能并不明显。但是,整个固定业务等都会详细解释。

其他提示

你打算如何处理行动秩序?

a * b squared

您可能希望查看Scala,它对运算符和方法有一种独特的方法。

Haskell 正是您所需要的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top