【发布时间】:2019-12-29 13:31:09
【问题描述】:
我尝试使用 ReadP 标准库解析命令(创建)。我的命令应该以字符串create 开头,然后至少包含一个单词/标签/到期,并可能包含一个选项。这是我的实际表达:
createExpr :: ReadP [Arg]
createExpr = do
skipSpaces
cmd <- SetCmd <$> cmdAliasExpr ["create", "add"]
skipSpaces
rest <-
many1
$ (AddWord <$> wordExpr)
<|> (AddTag <$> addTagExpr)
<|> (SetDue <$> dueExpr)
<|> (AddOpt <$> optExpr)
skipSpaces
return $ cmd : rest
问题是,如果我只用一个选项调用create,它就可以很好地解析。但它不应该,因为我希望至少有一个词/标签/到期。我该如何表达?
[编辑] 感谢@M. Aroosi,我找到了解决方案。
事实上,我用错了运算符。 <++,本地、独家、偏左的选择,更符合我的需求。一旦一个表达式被匹配,它不应该检查其他的:
notAnOpt arg = case arg of
AddOpt _ -> False
_ -> True
createExpr :: ReadP [Arg]
createExpr = do
skipSpaces
cmd <- SetCmd <$> cmdAliasExpr ["create", "add"]
skipSpaces
rest <-
many1
$ (AddTag <$> addTagExpr)
<++ (SetDue <$> dueExpr)
<++ (AddOpt <$> optExpr)
<++ (AddWord <$> wordExpr)
skipSpaces
guard $ isJust $ find notAnOpt rest
return $ cmd : rest
【问题讨论】:
-
您可以检查
rest是否至少有 1 个单词/标签/到期(例如,filter然后null检查)并使用Control.Monad中的guard来确保在这种情况下解析器会失败。 -
我不确定完全理解你所说的。你能给我举个例子吗?
-
不要添加问题的答案...
-
你读过所有的cmets吗?多亏了我收到的帮助,我找到了解决方案。我要求所有者(M. Aroosi)用我发现的内容更新他的答案,然后我会验证它。
标签: parsing haskell parsec parser-combinators