假设这是一个解析器:
data Parser a = MkParser (String -> Maybe (String, a))
runParser :: Parser a -> String -> Maybe a
runParser (MkParser sf) inp = case sf inp of
Nothing -> Nothing
Just (_, a) -> Just a
unParser :: Parser a -> String -> Maybe (String, a)
unParser (MkParser sf1) = sf1
(>>=) :: Parser a -> (a -> Parser b) -> Parser b
-- takes a parser, and a second parser (second parser takes a char)
-- parses `a`, then feeds `a` to second parser...
MkParser pa >>= k = MkParser sf
where
sf inp = case pa inp of
Nothing -> Nothing
Just (as, a) -> unParser (k a) as
-- Question: If the second parser fails, does the first
-- parser still parse? What string does it return?
-- as or inp?
-- parses any char
anyChar :: Parser Char
anyChar = MkParser sf
where
sf "" = Nothing
sf (c:cs) = Just (cs, c)
-- parses the char we want
char :: Char -> Parser Char
char wanted = MkParser sf
where
sf (c:cs) | c == wanted = Just (cs, c)
sf _ = Nothing
假设我这样做
secondFail = anyChar >>= \c -> char c
runParser secondFail "test"
这给了
Nothing
因为
\c -> char c
失败(
e
不是
t
).
我的问题是,第一个解析器运行了吗?输入字符串是否被解析了1次?是“est”还是因为第二个解析器失败,整个事情都失败了,字符串也没有被解析?
我不确定如何编写代码来测试输出,因为输出只是
没有什么
.
编辑:我想我回答了我自己的问题。我添加了这个函数(基本上,如果第一个解析器成功,什么都不做,但如果第一个分析器失败,运行第二个解析器:
(<|>) :: Parser a -> Parser a -> Parser a
-- Choice / Backtrack.
-- takes two parsers
-- tries one parse
-- pa1 stringInput
-- saves the location
-- if it fales, reverts back,
-- gives stringInput (no change) to
-- pa2.
MkParser pa1 <|> pa2 = MkParser sf
where
sf inp = case pa1 inp of
Nothing -> unParser pa2 inp
j -> j
-- I want to be able to produce a parser that gives exactly what I want and
-- doesn't change the input string at all, doesn't touch it
pure :: a -> Parser a
pure a = MkParser (\inp -> Just (inp, a))
添加了以下内容来运行解析器:
runParser2 :: Parser a -> String -> Maybe (String, a)
runParser2 (MkParser pa) inp = pa inp
然后我做了这个:
secondFail = (char 'w' >>= \a -> char 'o' >>= \b -> char 'r' >>= \c -> char 'l') <|> pure 'x'
然后运行它:
runParser2 secondFail "woqld"
这给了
Just ("woqld",'x')
它能给吗
Just ("woqld",'x')
因为
(char 'w' >>= \a -> char 'o' >>= \b -> char 'r' >>= \c -> char 'l')
被视为一个解析器?尽管
w
和
o
解析器成功,此后整个解析器失败
r
失败?因此,它恢复到原始输入并将其提供给
pure 'x'
?