gpt4 book ai didi

haskell - 为什么这些 Haskell Parsec 组合器的顺序很重要?

转载 作者:行者123 更新时间:2023-12-05 03:16:53 25 4
gpt4 key购买 nike

我想制作一个简单的解析器来解析加法表达式。这是我的代码:

import Text.Parsec.Char
import Text.Parsec.String
import Text.ParserCombinators.Parsec

data Expr = Number Float |
Add Expr Expr |

number :: Parser Expr
number = do
n <- try $ many1 digit
return $ Number $ read n

add :: Parser Expr
add = do
e1 <- number
char '+'
e2 <- number
return $ Add e1 e2

expr :: Parser Expr
expr = try number <|> try add


p :: String -> Either ParseError Expr
p = parse (do{e <- expr; eof; return e}) "error"

但这是输出

ghci> parse add "err" "1+2"
Right (Add (Number 1.0) (Number 2.0))
ghci> p "1"
Right (Number 1.0)
ghci> p "1+2"
Left "error" (line 1, column 2):
unexpected '+'
expecting digit or end of input

但是如果我改变 expr 的顺序组合器

expr :: Parser Expr
expr = try add <|> try number

然后输出变为

ghci> p "1+2"
Right (Add (Number 1.0) (Number 2.0))

为什么会这样?我以为 try关键字强制我正在组合的解析器在每个 <|> 之后重新启动.

我计划把它做得更大,所以我想确定我明白为什么现在会发生这种情况。

我的实际程序已经更大了,但这仍然独立地导致了一个问题。

最佳答案

您面临的问题是当字符串 "1+2"number 解析,它成功(无可否认,有一些未解析的字符)。 try的使用仅在失败时才重要。

也许另一种展示方式是考虑示例 try (string "a") <|> try (string "ab") .这将成功匹配任何以字符 a 开头的字符串。 , 但它永远不会匹配以 "ab" 开头的字符串.

如果你尝试过

exprAll :: Parser Expr
exprAll = try (number <* eof) <|> try (add <* eof)

然后您可能会得到您正在寻找的行为。在这种情况下,“try”d 解析器在到达文件结束字符之前不会成功,所以当 +遇到,number <* eof的解析尝试失败,然后使用 add <* eof 重新开始解析.

关于haskell - 为什么这些 Haskell Parsec 组合器的顺序很重要?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74415726/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com