views:

99

answers:

1

I'm using Text.ParserCombinators.Parsec and Text.XHtml to parse an input and get a HTML output.

If my input is:

    * First item, First level
    ** First item, Second level
    ** Second item, Second level
    * Second item, First level

My output should be:

<ul><li>First item, First level <ul><li>First item, Second level </li><li>Second item, Second level </li></ul></li><li>Second item, First level</li></ul>

I wrote this, but obviously does not work recursively

list= do{ s <- many1 item;return (olist << s) } item= do{ (count 1 (char '*')) ;s <- manyTill anyChar newline ;return ( li << s) }

Any ideas? the recursion can be more than two levels

Thanks!

+1  A: 
list n = do first <- item n
            rest <- many $ try $ try (list (n+1)) <|> item n
            return $ ulist << (first : rest)

item n = do count n (char '*')
            s <- manyTill anyChar newline
            return $ li << s

Now parse (list 1) "foo" "* a\n** a 1\n** a 2\n* b\n** b 1\n** b 2\n" will return what you asked for.

Note though, that the nested lists should themselves be inside a li, for this to be valid xhtml.

sepp2k
Thanks! but when I do `parse (list 1) "foo" "* a\n** a 1\n** a 2\n* b\n** b 1\n** b 2\n"`returns <ul> <li> a </li> <li> * a 1 </li> <li> * a 2 </li> <li> b </li> <ul> <li> b 1 </li> <li> b 2 </li> </ul> </ul>
Martin
@Martin: Bah, you're right. I didn't read the output carefully enough when I tested.
sepp2k
Could you please help me to improve the output?Thanks!!
Martin
@Martin: Fixed now. I had to add a second try in line two, so it wouldn't fail when reaching the end of a nested list.
sepp2k
Your answer is great!!!
Martin
Shouldn't you add a call to 'space' in item to eat the space between the asterisks and the text?
MtnViewMark