如何在Haskell中解析时正确区分词干字符和文字字符

时间:2016-11-06 20:25:59

标签: parsing haskell parsec

我对Haskell相当新,我正在尝试制作一个简单的Parser,而我正在使用Parsec模块。我的解析器的语法是:

data Frag
  = Lt String
  | St
  deriving (Eq, Show)

type Template = [Frag]

type FileT = Template
type CommandT = Template

data Rule
  = Rule [FileT] [FileT] [CommandT]
  deriving (Eq, Show)

type Makefile = [Rule]

我已经实现了一直到片段(这将是一组字符)。这是我试图处理文字字符的剪辑,但我不知道如何处理Stem字符:

template :: Parser [Frag]
template = 
    do result <- many frag
       return result
frag :: Parser Frag
frag = do Lt x <- (many (noneOf ['\n','\t','\r',':','.']))
          return x

但是我得到了这个错误,我不知道为什么:

Parser\Impl.hs:72:11: error:
    • Couldn't match expected type ‘[Char]’ with actual type ‘Frag’
    • In the pattern: Lt x
      In a stmt of a 'do' block:
        Lt x <- (many (noneOf ['\n', '\t', '\r', ':', ....]))
      In the expression:
        do { Lt x <- (many (noneOf ['\n', '\t', ....]));
             return x }

Parser\Impl.hs:73:11: error:
    • Couldn't match type ‘[Char]’ with ‘Frag’
      Expected type: Text.Parsec.Prim.ParsecT
                       String () Data.Functor.Identity.Identity Frag
        Actual type: Text.Parsec.Prim.ParsecT
                       String () Data.Functor.Identity.Identity String
    • In a stmt of a 'do' block: return x
      In the expression:
        do { Lt x <- (many (noneOf ['\n', '\t', ....]));
             return x }
      In an equation for ‘frag’:
          frag
            = do { Lt x <- (many (noneOf ['\n', ....]));
                   return x }

输入:

"aaa : bbb ccc"
"\:aaa : \%bbb \\ccc

输出:

[["aaa"] , ["bbb"] , ["ccc"]]
[[":aaa"] , ["%bbb"] , ["\ccc"]]    

1 个答案:

答案 0 :(得分:1)

frag :: Parser Frag
frag = do Lt x <- (many (noneOf ['\n','\t','\r',':','.']))
          return x

many,此处生成Parser [Char]。您试图将[Char]结果与Frag模式匹配,从而导致类型错误。相反,你想......

frag :: Parser Frag
frag = do x <- (many (noneOf ['\n','\t','\r',':','.']))
          return (Lt x)

......或简单地说:

frag :: Parser Frag
frag = fmap Lt (many (noneOf ['\n','\t','\r',':','.']))

P.S。:在你的另一个定义中......

template :: Parser [Frag]
template = 
    do result <- many frag
       return result

...绑定result仅用于立即使用return是多余的。你可以写:

template :: Parser [Frag]
template = many frag

P.P.S。:正如您所注意到的(也许正如您所料),many frag不足以做您想做的事情。您需要以某种方式指定如何划分碎片。