5

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

a * b => multiply(a,b)

或后缀“平方”运算符:

a squared => a * a

或者是 C 或 Java 风格的三元运算符,它涉及两个散布在变量中的关键字:

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

显然,在这种语言中存在很多歧义,但如果它是静态类型的(使用类型推断),则可以消除大多数歧义,并且可以将剩余的歧义视为语法错误(通过添加括号来纠正合适的)。

是否有一些我看不到的原因会使这变得极其困难、不可能,或者只是一个糟糕的主意?

编辑:许多人向我指出了可能执行此操作或类似操作的语言,但我实际上对如何实现我自己的解析器的指针感兴趣,或者如果这样做我可能会遇到的问题。

4

4 回答 4

15

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

x + y + z

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

您需要注意的另一种情况是,当您有

prefix (e) postfix

whereprefixpostfix具有相同的优先级。这种情况还需要括号来消除歧义。

我的论文Unparsing Expressions with Prefix and Postfix Operators在后面有一个示例解析器,你可以下载代码,但它是用 ML 编写的,所以它的工作原理对于业余爱好者来说可能并不明显。但是对固定性等整个业务进行了非常详细的解释。

于 2009-01-09T05:15:35.637 回答
2

您将如何处理操作顺序?

a * b squared
于 2009-01-09T04:32:03.807 回答
1

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

于 2009-01-09T04:45:58.363 回答
0

Haskell正是您想要的。

于 2009-01-09T04:14:28.100 回答