Parsec的setState不会重置消耗状态

时间:2020-01-09 18:22:07

标签: haskell parsec

我试图了解Parsec如何重置其状态以及该状态的一部分。我对以下代码的行为感到惊讶:

parseAbReset :: Parser Char                                                                    
parseAbReset = do                                                                              
    st <- getParserState                                                                  
    char 'A'                                                                              
    ret <- char 'b' <|> (setParserState st >> fail mempty)                                
    return ret                                                                            


parseFinal :: Parser Char                                                                     
parseFinal = parseAbReset <|> (char 'A' >> char 't')

我希望parseFinal成功地解析“ At”。这是我的推理(|表示输入的当前状态): <|>尝试进行parseAbReset的解析,直到“ A | t”为止,然后它在char 'b'上失败而不消耗输入,因此将状态重置回“ | At”,parseAbReset失败(在我看来,它应该在不使用输入的情况下失败,因为它会在使用输入之前重置为某种状态。这样,备用(char 'A' >> char 't')就可以使用“ At”,而我们以“ At |”结束。

在其他示例中,我测试了setParserState成功重置了流中的位置,但是似乎它是否消耗了某些东西的状态似乎没有重置。

任何想法,无论是否消耗掉,我该如何重置?

1 个答案:

答案 0 :(得分:1)

流位置不是解析器状态的一部分,因此重置解析器状态不会影响消耗了哪些输入。在lookahead中可以使用Parsec本身{get,set} ParserState的一种用法。如您所见,除了保留解析器状态外,它还可以保留输入流。它很有帮助地指出,如果在您不希望的情况下使用了输入,则应使用try。这是有道理的:try是用于从部分失败的解析中恢复的典型Parsec工具。

实际上,您要使用try进行的操作非常简单:

parseAbReset :: Parser Char
parseAbReset = try $ char 'A' *> char 'b'