我正在尝试使用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 = ...
答案 0 :(得分:2)
我使用Text.Parsec.Indent自己解决了这个问题。
parseData = withPos $ <old definition>
parseCntr = (DataCnstr <$> identifier) <*/> parseTypeTerm
这确保使用正确的缩进解析所有类型术语!