haskell - 使用 megaparsec + 解析器组合器进行排列解析太宽松

标签 haskell parser-combinators megaparsec

我正在尝试解析标志的排列。我想要的行为是“一个或多个标志以任何顺序,不重复”。我正在使用以下软件包:

  • 兆秒差距
  • 解析器组合器

我的代码正在输出我想要的内容,但对输入太宽松了。我不明白为什么它接受多个相同的标志。我在这里做错了什么?

pFlags :: Parser [Flag]
pFlags = runPermutation $ f <$> 
    toPermutation (optional (GroupFlag <$ char '\'')) <*> 
    toPermutation (optional (LeftJustifyFlag <$ char '-'))
    where f a b = catMaybes [a, b]

示例:

"'-" = [GroupFlag, LeftJustifyFlag] -- CORRECT
"-'" = [LeftJustifyFlag, GroupFlag] -- CORRECT
"''''-" = [GroupFlag, LeftJustifyFlag] -- INCORRECT, should fail if there's more than one of the same flag.

最佳答案

我相信您需要使用toPermutationWithDefault,而不是使用可选toPermutation ,像这样(未经测试):

toPermutationWithDefault Nothing (Just GroupFlag <$ char '\'')

论文“Parsing Permutation Phrases”( PDF ) 中的第 4 节“添加可选元素”(强调添加)描述了推理:

Consider, for example […] all permutations of a, b and c. Suppose b can be empty and we want to recognise ac. This can be done in three different ways since the empty b can be recognised before a, after a or after c. Fortunately, it is irrelevant for the result of a parse where exactly the empty b is derived, since order is not important. This allows us to use a strategy similar to the one proposed by Cameron: parse nonempty constituents as they are seen and allow the parser to stop if all remaining elements are optional. When the parser stops the default values are returned for all optional elements that have not been recognised.

To implement this strategy we need to be able to determine whether a parser can derive the empty string and split it into its default value and its non-empty part, i.e. a parser that behaves the same except that it does not recognise the empty string.

也就是说,排列解析器需要知道哪些元素可以在不消耗输入的情况下成功,否则它会太急于提交到分支。但我不知道为什么这会导致接受一个元素的倍数;也许您还缺少 eof

关于haskell - 使用 megaparsec + 解析器组合器进行排列解析太宽松,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70399808/

相关文章:

string - 你如何在 haskell 中通过字符串过滤字符串列表?

haskell - Data.Typeable.cast 到现有类型

Haskell - 获取只出现一次的项目

Scala解析器 token 定界符问题

Scala PackratParser 忽略失败解析器

parsing - 如何使用 Parsec 制作子解析器?

haskell - 使用 Megaparsec 使用开始和结束符号解析 block 注释

haskell - unsafeRead 导致堆栈溢出

parsing - 如果 attoparsec 回溯,为什么它需要 manyTill?

parsing - 使用 Haskell 解析引号