IndentParser example

Can someone post a small example using IndentParser? I am looking for an analysis of YAML-like input, for example:

fruits: apples: yummy watermelons: not so yummy vegetables: carrots: are orange celery raw: good for the jaw 

I know there is a YAML package. I would like to learn about using IndentParser.

+8
parsing yaml haskell
source share
1 answer

I sketched the parser below, for your problem, you probably only need the parser block from IndentParser. Note. I did not try to run it so that it could have elementary errors.

The biggest problem for your parsing is not really indentation, but you only have lines and a colon as tokens. You might find that the code below requires quite a bit of debugging, as it should be very sensitive so as not to consume too much input, although I tried to be careful in left factoring. Since you only have two tokens, you cannot take advantage of the Parsec token module.

Note that there is a strange truth to parsing that simple formats are often not easy to parse. For learning to write a parser for simple expressions, it will teach you much more than a more or less arbitrary text format (which can only cause disappointment).

 data DefinitionTree = Nested String [DefinitionTree] | Def String String deriving (Show) -- Note - this might need some testing. -- -- This is a tricky one, the parser has to parse trailing -- spaces and tabs but not a new line. -- category :: IndentCharParser st String category = do { a <- body ; rest ; return a } where body = manyTill1 (letter <|> space) (char ':') rest = many (oneOf [' ', '\t']) -- Because the DefinitionTree data type has two quite -- different constructors, both sharing the same prefix -- 'category' this combinator is a bit more complicated -- than usual, and has to use an Either type to descriminate -- between the options. -- definition :: IndentCharParser st DefinitionTree definition = do { a <- category ; b <- (textL <|> definitionsR) ; case b of Left ss -> return (Def a ss) Right ds -> return (Nested a ds) } -- Note this should parse a string *provided* it is on -- the same line as the category. -- -- However you might find this assumption needs verifying... -- textL :: IndentCharParser st (Either DefinitionTrees a) textL = do { ss <- manyTill1 anyChar "\n" ; return (Left ss) } -- Finally this one uses an indent parser. -- definitionsR :: IndentCharParser st (Either a [DefinitionTree]) definitionsR = block body where body = do { a <- many1 definition; return (Right a) } 
+2
source share

All Articles