使用Parsec解析Haskell的子集

时间:2014-12-22 11:04:00

标签: haskell parsec

我正在尝试使用Parsec编写一个解析器来解析以下内容:

data Nat = Z | S Nat

plusNat :: Nat -> Nat -> Nat
plusNat Z     m = m
plusNat (S n) m = S (plusNat n m)

对于data表达式,我有以下解析器:

parseData = reserved "data" >> DataDefn
         <$> identifier
         <*> parseCnstr `sepBy` reservedOp "|"

parseCnstr = DataCnstr <$> identifier <*> many parseTypeTerm

parseType = buildExpressionParser table parseTypeTerm
    where table = [[function]]
          function = Infix (Function <$ reservedOp "->") AssocRight

parseTypeTerm = TypeVar <$> identifier
             <|> parens parseType

但是,当我在上面的文字中使用此解析器时,parseType抓取plusNat然后错误:

"test.hs" (line 3, column 9):
unexpected ':'
expecting "|" or end of input

我知道问题是什么,因为plusNat被认为是dataCnstr的一部分。如何告诉dataCnstr解析器在到达无缩进的新行时停止?

请注意,我希望能够解析以下内容:

data ReallyLongData reallyLongTypeVariable
    = ReallyLongConstructor1
    | ReallyLongConstructor2
        reallyLongTypeVariable
        (ReallyLongData reallyLongTypeVariable)

concat :: ReallyLongData a -> ReallyLongData a -> ReallyLongData a
concat = ...

1 个答案:

答案 0 :(得分:2)

我使用Text.Parsec.Indent自己解决了这个问题。

parseData = withPos $ <old definition>

parseCntr = (DataCnstr <$> identifier) <*/> parseTypeTerm

这确保使用正确的缩进解析所有类型术语!