Haskell 解析算术/布尔表达式,但跳过捕获

Haskell 解析算术/布尔表达式,但跳过捕获,haskell,parsec,Haskell,Parsec,给出以下表达式 x = a + 3 + b * 5 我想在下面的数据结构中这样写,我只想捕获RHS上使用的变量并保持字符串的完整性。我对解析更具体的结构不感兴趣,因为我正在做一个从语言到语言的转换,而不是处理计算 Variable "x" (Expr ["a","b"] "a + 3 + b * 5") 我一直以使用作为起点,但我不知道如何在没有buildExpressionParser的情况下编写表达式解析器。这似乎不是我应该采用的方法。我不确定您为什么要避免buildExpression

给出以下表达式

x = a + 3 + b * 5
我想在下面的数据结构中这样写,我只想捕获RHS上使用的变量并保持字符串的完整性。我对解析更具体的结构不感兴趣,因为我正在做一个从语言到语言的转换,而不是处理计算

Variable "x" (Expr ["a","b"] "a + 3 + b * 5")

我一直以使用作为起点,但我不知道如何在没有
buildExpressionParser
的情况下编写表达式解析器。这似乎不是我应该采用的方法。

我不确定您为什么要避免buildExpressionParser,因为它隐藏了使用中缀运算符解析表达式的许多复杂性。这是做事的正确方式

很抱歉,但现在我把那匹老马弄走了,我可以回答你的问题了

首先,这里是一些背景-

为带有中缀运算符的表达式编写解析器比较困难的主要原因是运算符优先级。你想确保

x+y*z
解析如下

  +
 / \
x   *
    /\  
   y  z
而不是这个

    *
   / \
  +   z
 / \
x   y
选择正确的语法树不是一个很难解决的问题。。。。但是如果你不注意,你可以写一些非常糟糕的代码。为什么?表演

忽略优先级的可能解析树的数量随着输入的大小呈指数增长。例如,如果您编写的代码尝试了所有的可能性,然后扔掉了除具有适当优先级之外的所有可能性,那么当您的解析器处理现实世界中的任何事情时,您将感到非常惊讶(请记住,指数复杂性通常不仅仅是缓慢的,它根本不是一个解决方案……您可能会发现,您正在等待半个小时的简单解析,没有人会使用该解析器)

我不会在这里重复“适当”解决方案的细节(谷歌搜索会给出细节),但要注意的是,适当的解决方案在输入大小为O(n)时运行,buildExpressionParser隐藏了为您编写这种解析器的所有复杂性


那么,回到你最初的问题

您需要使用buildExpressionParser从RHS中获取变量,还是有更好的方法

你不需要它

因为你所关心的只是得到右边使用的变量,所以你不关心操作符的优先级。你只需要将所有内容左关联并编写一个简单的O(n)parsetrees是错误的,但是谁在乎呢?你仍然可以得到相同的变量。你甚至不需要上下文无关的语法,这个正则表达式基本上可以做到这一点

<variable>(<operator><variable>)*
()*
(其中,
以明显的方式定义)

然而

我不建议这样做,因为尽管它很简单,但它仍然比使用buildExpressionParser需要做更多的工作,而且扩展起来会更困难(比如添加括号).但最重要的是,稍后,您可能会意外地在确实需要完整解析树的地方使用它,并在一段时间内困惑为什么运算符优先级会如此混乱

另一个解决方案是,你可以重写你的语法来消除歧义(同样,谷歌会告诉你怎么做)……这是一个很好的学习练习,但你基本上是在重复buildExpressionParser在内部做的事情