如何使用 Parsec 的 Perm 解析排列短语的非连续元素?

How can I parse non-contiguous elements of a permutation phrase using Parsec's Perm?

Haskell 的 Parsec 支持 parsing of permutation phrases via the Perm 模块。在 permute 的文档中,您可以看到如何解析各种排列 "abc"、"aab"、"bc"、"cbaaaaa" 等。虽然该示例显示支持分离同一元素的许多连续实例,如 "aaaa",但它不会解析非连续实例,如 "aabca",大概是因为每个解析器在每个排列中仅包含一次(论文似乎在树中暗示了这一点...)

除了对输入进行排序以使实例连续外,我还有哪些选项可以解析非连续实例?

根据您的实际需要,您可以使用 many $ oneOf ['a','b','c']

如果您确实需要使用排列解析器,请记住允许解析多个相邻字符会引入歧义。例如,在字符串 "bacacbbca" 中,它可以被解析为 perms bacacb bca,或者,如果允许重复字符,则 bacacbb,剩余的非排列 ca.

如果允许重复字母,

{-# LANGUAGE FlexibleContexts #-}

import Text.Parsec
import Text.Parsec.Char
import Text.Parsec.Perm
import Data.Text
import Control.Monad.Identity

perm :: (Stream s Identity Char) => Parsec s u (String,String,String)
perm = permute $ triple <$$>
  (many1 $ char 'a') <||>
  (many1 $ char 'b') <||>
  (many1 $ char 'c')
  where triple a b c = (a,b,c)

multiPerm :: (Stream s Identity Char) => Parsec s u [(String,String,String)]
multiPerm = many $ try $ perm

main :: IO ()
main = parseTest multiPerm $ "bacacbbca" 

main 产生 [("a","b","c"),("a","bb","c")].

如果没有:

perm :: (Stream s Identity Char) => Parsec s u (Char,Char,Char)
perm = permute $ triple <$$>
  (char 'a') <||>
  (char 'b') <||>
  (char 'c')
  where triple a b c = (a,b,c)

你得到了可以说更好的:[('a','b','c'),('a','b','c'),('a','b','c')]