parsing - 在 Haskell 中使用组合器进行表达式评估
问题描述
我正在尝试在 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
)评估表达式时,解析器将失败。
我怎么能说 anadd_sub
可以是其他两个add_sub
s 之间的操作而不创建无限循环?
解决方案
正如@chi 所解释的,问题是calc
使用 p 两次,这不允许像这样的模式muldiv + .... | muldiv - ... | ...
我只是将定义更改calc
为:
calc c o p p2 = Op c <$> (p <* parseChar o) <*> p2
其中 p2 是当前优先级(mul_div
在 的定义中mul_div
)
它工作得更好,但计算的顺序是倒退的:
2/3/4
被解析为2/(3/4)
而不是(2/3)/4
推荐阅读
- python - 使用 Python 运行批处理文件时出现问题
- unity3d - 附加到搅拌机模型时纹理变得混乱
- python - 将文件夹上传到 Google 云端硬盘
- php - Laravel:使用 mergeBindings() 的复杂查询
- excel - Excel SUMPRODUCT/COUNTIFS #DIV/0 错误
- sql - 基于条件的 SQL 查询先前的值
- python - 如何使用 python 为远程 selenium webdrive 配置特殊代理设置?
- python-3.x - Azure Web 服务部署如何在本地工作?
- post - 从 Shopify 发送获取请求
- android - Android Studio Gradle 中的 Apache Commons?