Parsec-Parser works alright, but could it be done better?
我尝试这样做:
以如下形式解析文本:
Some Text #{0,0,0} some Text #{0,0,0}#{0,0,0} more Text #{0,0,0}
变成一些数据结构的列表:
[Inside"Some Text",Outside (0,0,0),Inside" some Text",Outside (0,0,0),Outside (0,0,0),Inside" more Text",Outside (0,0,0)]
所以这些#{a,b,c}位应该变成与文本其余部分不同的东西。
我有这个代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | module ParsecTest where import Text.ParserCombinators.Parsec import Monad type Reference = (Int, Int, Int) data Transc = Inside String | Outside Reference deriving (Show) text :: Parser Transc text = do x <- manyTill anyChar ((lookAhead reference) <|> (eof >> return (Inside""))); return (Inside x) transc = reference <|> text alot :: Parser [Transc] alot = do manyTill transc eof reference :: Parser Transc reference = try (do{ char '#'; char '{'; a <- number; char ','; b <- number; char ','; c <- number; char '}'; return (Outside (a,b,c)) }) number :: Parser Int number = do{ x <- many1 digit; return (read x) } |
这按预期工作。您可以通过键入
在 ghci 中进行测试
parseTest alot"Some Text #{0,0,0} some Text #{0,0,0}#{0,0,0} more Text #{0,0,0}"
但我认为这不太好。
1) 我的问题真的需要使用
2)
3) 通常是否有更简洁/更智能的方式来实现相同的归档?
1) 我认为您确实需要
2) 是的。
3)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | number2 :: Parser Int number2 = read <$> many1 digit text2 :: Parser Transc text2 = (Inside .) . (:) <$> anyChar <*> manyTill anyChar (try (lookAhead reference2) *> pure () <|> eof) reference2 :: Parser Transc reference2 = ((Outside .) .) . (,,) <$> (string"#{" *> number2 <* char ',') <*> number2 <*> (char ',' *> number2 <* char '}') transc2 = reference2 <|> text2 alot2 = many transc2 |
您可能希望使用
编辑:更改了