[英]Parsec try : should try to go to next option
Currently, I have the following code:目前,我有以下代码:
import Control.Applicative ((<|>))
import Text.Parsec (ParseError, endBy, sepBy, try)
import Text.Parsec.String (Parser)
import qualified Data.Char as Char
import qualified Text.Parsec as Parsec
data Operation = Lt | Gt deriving (Show)
data Value =
Raw String
| Op Operation
deriving (Show)
sampleStr :: String
sampleStr = unlines
[ "#BEGIN#"
, "x <- 3.14 + 2.72;"
, "x < 10;"
]
gtParser :: Parser Value
gtParser = do
Parsec.string "<"
return $ Op Gt
ltParser :: Parser Value
ltParser = do
Parsec.string ">"
return $ Op Lt
opParser :: Parser Value
opParser = gtParser <|> ltParser
rawParser :: Parser Value
rawParser = do
str <- Parsec.many1 $ Parsec.satisfy $ not . Char.isSpace
return $ Raw str
valueParser :: Parser Value
valueParser = try opParser <|> rawParser
eolParser :: Parser Char
eolParser = try (Parsec.char ';' >> Parsec.endOfLine)
<|> Parsec.endOfLine
lineParser :: Parser [Value]
lineParser = sepBy valueParser $ Parsec.many1 $ Parsec.char ' '
fileParser :: Parser [[Value]]
fileParser = endBy lineParser eolParser
parse :: String -> Either ParseError [[Value]]
parse = Parsec.parse fileParser "fail..."
main :: IO ()
main = print $ parse sampleStr
This will fail with the message这将失败并显示消息
Left "fail..." (line 2, column 4):
unexpected "-"
expecting " ", ";" or new-line
To my understanding, since I have try opParser
, after Parsec sees that the token <-
cannot be parsed by opParser
, it should go to rawParser
.据我了解,由于我
try opParser
,在 Parsec 看到令牌<-
无法被opParser
解析后,它应该 go 到rawParser
。 (It is essentially a lookahead). (它本质上是一个前瞻)。
What is my misunderstanding, and how do I fix this error?我的误解是什么,我该如何解决这个错误?
You can replicate the problem with the smaller test case:您可以使用较小的测试用例复制问题:
> Parsec.parse fileParser "foo" "x <- 3.14"
The problem is that fileParser
first calls lineParser
, which successfully parses "x <"
into [Raw "x", Op Gt]
and leaves "- 3.14"
yet to be parsed.问题是
fileParser
首先调用lineParser
,它成功地将"x <"
解析为[Raw "x", Op Gt]
并留下"- 3.14"
尚未解析。 Unfortunately, fileParser
now expects to parse something with eolParser
, but eolParser
can't parse "- 3.14"
because it starts with neither a semicolon nor an endOfLine
.不幸的是,
fileParser
现在希望使用eolParser
解析某些内容,但eolParser
无法解析"- 3.14"
,因为它既不以分号也不以endOfLine
。
Your try opParser
has no effect here because opParser
successfully parses <
, so there's nothing to backtrack from.您的
try opParser
在这里没有效果,因为opParser
成功解析了<
,所以没有什么可以回溯的。
There are many ways you might fix the problem.有很多方法可以解决问题。 If
<-
is the only case where a <
might be misparsed, you could exclude this case with notFollowedBy
:如果
<-
是<
可能被错误解析的唯一情况,您可以使用notFollowedBy
排除这种情况:
gtParser :: Parser Value
gtParser = do
Parsec.string "<"
notFollowedBy $ Parsec.string "-"
return $ Op Gt
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.