我想解析一系列任意4个字符。但是,这些字符不应形成特定的字符串(在下面的示例中为@Query(value = "select a from TableA a where a.tableB is null and a.id=?1")
TableA findTableAValues(Long id);
)。因此x
和"bb"
可以,但是"aaaa"
和"abcd"
都不应该匹配。
我编写了以下解析器:
"bbcd"
但是,我注意到它“吃”了单个"abbc"
个字符。例如
ntimes 4 (requireFailure (string "bb") *> anyChar)
结果为b
(但是,按预期结果在parse (ntimes 4 (requireFailure (string "bb") *> anyToken)) "abcde"
和['a', 'c', 'd', 'e']
上失败)。
作为解决方法,我使用了自己的"bbcd"
实现:
"abbc"
所以
requireFailure
按照我的期望提供了requireFailure' : Parser a -> Parser ()
requireFailure' p = do
isP <- p *> pure True <|> pure False
if isP then fail "argument parser to fail"
else pure ()
。
显然光年解析器是backtrack-by-default,除非有人调用parse (ntimes 4 (requireFailure' (string "bb") *> anyToken)) "abcde"
。
所以我的问题是,为什么['a', 'b', 'c', 'd']
的库实现在参数失败的情况下不进行回溯,这是预期的行为吗?
答案 0 :(得分:3)
如果您查看the implementation of requireFailure
,您会发现它以状态us
调用“成功”延续s
,它会在之后运行其参数比以前的ST i pos tw
要好。
requireFailure : ParserT str m tok -> ParserT str m ()
requireFailure (PT f) = PT $ \r, us, cs, ue, ce, (ST i pos tw) =>
f r
(\t, s => ue [Err pos "argument parser to fail"] s)
(\t, s => ce [Err pos "argument parser to fail"] s)
(\errs, s => us () s)
(\errs, s => cs () s)
(ST i pos tw)
文档声称requireFailure
在parsec和that doesn't consume any input中分别称为notFollowedBy
,因此您可以说这是LightYear方面的错误。
您可以打开一个错误报告,建议用类似以下内容的代码替换当前代码(我不知道Idris是否支持@
模式):
requireFailure : ParserT str m tok -> ParserT str m ()
requireFailure (PT f) = PT $ \r, us, cs, ue, ce, s@(ST i pos tw) =>
f r
(\t, s => ue [Err pos "argument parser to fail"] s)
(\t, s => ce [Err pos "argument parser to fail"] s)
(\errs, _ => us () s)
(\errs, _ => cs () s)
s