【发布时间】:2021-10-24 15:18:26
【问题描述】:
我正在尝试在 Hakell 中创建表达式评估器:
data Parser i o
= Success o [i]
| Failure String [i]
| Parser
{parse :: [i] -> Parser i o}
data Operator = Add | Sub | Mul | Div | Pow
data Expr
= Op Operator Expr Expr
| Val Double
expr :: Parser Char Expr
expr = add_sub
where
add_sub = calc Add '+' mul_div <|> calc Sub '-' mul_div <|> mul_div
mul_div = calc Mul '*' pow <|> calc Div '/' pow <|> pow
pow = calc Pow '^' factor <|> factor
factor = parens <|> val
val = Val <$> parseDouble
parens = parseChar '(' *> expr <* parseChar ')'
calc c o p = Op c <$> (p <* parseChar o) <*> p
我的问题是,当我尝试使用具有相同优先级的两个运算符(例如 1+1-1)评估表达式时,解析器将失败。
我怎么能说add_sub 可以是另外两个add_subs 之间的操作而不创建无限循环?
【问题讨论】:
-
你试过
add_sub = calc Add '+' add_sub <|> calc Sub '-' add_sub <|> mul_div吗?同样,mul_div = calc Mul '*' mul_div <|> calc Div '/' mul_div <|> pow等。 -
(我假设这里有一个像 parsec 这样的 LL 解析器组合器。如果它是更强大的东西,我可能会错在这里)
calc恰好使用了两次p。同样p我们得到类似(伪代码)addsub = muldiv + muldiv | ....而不是addsub = muldiv + addsub | ...的东西。这不是唯一的问题:您的语法不是 LL,因为例如muldiv + .... | muldiv - ... | ...不能在 LL 中处理,因为这两个选项都以相同的前缀开头——你可能应该重构你的语法。 -
@WillNess 我试过这个,它会创建一个无限循环
-
Parser的定义是什么?和Expr? -
@chi 感谢这个解释,我在 calc 的定义中将第二个
p更改为expr似乎已经解决了问题
标签: parsing haskell evaluation