Haskell parsec解析字符串项
我有一个需要解析的列表,其中除最后一个元素外的所有元素都需要由一个解析器解析,最后一个元素需要由另一个解析器解析Haskell parsec解析字符串项,haskell,parsec,Haskell,Parsec,我有一个需要解析的列表,其中除最后一个元素外的所有元素都需要由一个解析器解析,最后一个元素需要由另一个解析器解析 a = "p1 p1b ... p2" or a = "p2" 最初我试过了 parser = do parse1 <- many parser1 parse2 <- parser2 return AParse parse1 parse2 parser=do parse1如果可以将parser1因子化,则定义如下: pa
a = "p1 p1b ... p2"
or
a = "p2"
最初我试过了
parser = do parse1 <- many parser1
parse2 <- parser2
return AParse parse1 parse2
parser=do parse1如果可以将parser1
因子化,则定义如下:
parser1 = (try parser2) <|> parser1extra
您可能需要也可能不需要try
调用,这取决于这些解析器是否有前缀重叠
如果您不希望返回值是一个列表,而是您的AParse数据,则可以通过以下方式重新写入:
parserList =
do
a <- try parser1extra
prefix a parserList
<|>
do
a <- try parser2
option (AParse [] a) (prefix a parserList)
where prefix a p = do
(AParse as t) <- p
return $ (AParse (a:as) t)
将标点符号从解析器中取出,然后放到parseTest中,这样您就可以使用组合符介于
和endBy
之间来为您完成这项工作。最后,如果try
与parser1
和parser2
匹配公共前缀,endBy
将执行到公共前缀开头的正确完整备份
根据解析器的不同,您可以在子解析器中保留匹配的标点符号,您所需要的可能就是atry
aroundparser1
:
parseTest = do parse1 <- many (try parser1)
parse2 <- parser2
return AParse parse1 parse2
parseTest=do parse1怎么样:
parseTrain car caboose = choice
[ fmap (:[]) $ try (caboose `endBy` eof),
, liftM2 (:) car (parseTrain car caboose)
[
eof让我很烦,因为这使得这个解析器不是组合的。也就是说,你不能说:
char '(' >> parseTrain p1 p2 >> char ')'
对于解析器来说,以兼容的方式执行此操作非常困难。它如何知道如何继续使用char'),而不试图抓住每一个机会,看看是否失败?这样做可能会延长时间
如果你需要它是合成的,你的问题是否有一些额外的结构可以利用?例如,您能解析所有元素的列表,然后处理事实之后的最后一个元素吗?我有点结合了这两种方法:
parserList = try (do a <- parser2
eof
return $ AParse [] a)
<|>
do a <- parser1
prefix a parserList
where
prefix a p = do
(AParse as t) <- p
return $ AParse a:as t
parserList=try(执行a这将实现以下技巧:
parser1 `manyTill` (try parser2)
我在问题中犯了一个错误,并说我有一个项目列表。我应该说我有一个项目字符串。对此很抱歉。我在问题中进行了更正。代码中的第二个示例不起作用,因为parser1将使用整个字符串。感谢您提供的代码。parser1extra不会使用所有字符串吗?idea认为parser1extra只会解析那些应该在parser1中的东西,但不匹配parser2。因此,parser1extra只匹配parser2不匹配的地方。
char '(' >> parseTrain p1 p2 >> char ')'
parserList = try (do a <- parser2
eof
return $ AParse [] a)
<|>
do a <- parser1
prefix a parserList
where
prefix a p = do
(AParse as t) <- p
return $ AParse a:as t
parser1 `manyTill` (try parser2)