Parsing Haskell ReadP至少解析列表中的一个
我尝试用ReadP标准库解析命令(create)。我的命令应该以字符串Parsing Haskell ReadP至少解析列表中的一个,parsing,haskell,parsec,parser-combinators,Parsing,Haskell,Parsec,Parser Combinators,我尝试用ReadP标准库解析命令(create)。我的命令应该以字符串create开头,然后至少包含一个单词/tag/due,可能还有一个选项。下面是我的实际表达: createxpr::ReadP[Arg] createxpr=do 滑雪场 cmd一个简单的解决方案是使用Control.Monad中的guard 假设函数像isOpt::Arg->Bool,它与 isOpt :: Arg -> Bool isOpt (AddOpt _) = True isOpt _ =
create
开头,然后至少包含一个单词/tag/due,可能还有一个选项。下面是我的实际表达:
createxpr::ReadP[Arg]
createxpr=do
滑雪场
cmd一个简单的解决方案是使用Control.Monad中的guard
假设函数像isOpt::Arg->Bool
,它与
isOpt :: Arg -> Bool
isOpt (AddOpt _) = True
isOpt _ = False
然后您对createExpr
的定义将更改为
createExpr :: ReadP [Arg]
createExpr = do
skipSpaces
cmd <- SetCmd <$> cmdAliasExpr ["create", "add"]
skipSpaces
rest <-
many1
$ (AddWord <$> wordExpr)
<|> (AddTag <$> addTagExpr)
<|> (SetDue <$> dueExpr)
<|> (AddOpt <$> optExpr)
guard $ at_least_one_non_optional rest
skipSpaces
return $ cmd : rest
where at_least_one_non_optional = not . null . filter (not . isOpt)
createxpr::ReadP[Arg]
createxpr=do
滑雪场
cmd您可以检查rest
是否至少有一个单词/tag/due(filter
,然后检查null
),并使用Control.Monad中的guard
确保解析器在这种情况下失败。我不确定是否完全理解您所说的内容。你能给我举个例子吗?不要给问题添加答案……你读了所有的评论了吗?多亏了我得到的帮助,我找到了解决办法。我让店主(M.Aroosi)用我的发现更新他的答案,然后我会验证它。我明白你的意思。我用isJust$find atLeastOne rest实现了同样的效果。但这会导致另一个问题。如果我键入create--opt
,我有[([SetCmd“create”,AddWord”--json“],”)]
。我猜这是因为optExpr
失败了,它返回到wordExpr
@soywod这听起来像你的wordExpr
和optExpr
都接受“--json”
,在这种情况下解析器(AddWord-wordExpr)(AddTag addTagExpr)(SetDue dueepr)(AddOpt-optExpr)
尝试了wordExpr
和optExpr
这两种方法都成功了。你说两种方法都尝试是什么意思?只有第一个失败了,它才会尝试一个,不是吗?事实上,wordExpr
就像“垃圾”。与opt/tag/due不匹配的所有内容都将以单词结尾。()
定义为(+++)
对于可交换的ReadP
,它会尝试所有选项并返回所有结果。例如,尝试使用解析器(0确实是,(
createExpr :: ReadP [Arg]
createExpr = do
skipSpaces
cmd <- SetCmd <$> cmdAliasExpr ["create", "add"]
skipSpaces
rest <-
many1
$ (AddWord <$> wordExpr)
<|> (AddTag <$> addTagExpr)
<|> (SetDue <$> dueExpr)
<|> (AddOpt <$> optExpr)
guard $ at_least_one_non_optional rest
skipSpaces
return $ cmd : rest
where at_least_one_non_optional = not . null . filter (not . isOpt)