[Haskell-cafe] Need help with Parsec
Nicu Ionita
nionita at lycos.de
Sun Jan 20 12:12:01 EST 2008
Hi,
I'm playing since a few hours with Parsec and trying to write a small html
(fragment) parser, but I'm stuck in a point which I really can't understand.
The problem seem to be either in "parseProperCont" or in "closing" (see code
below). It looks like closing does not work (but it is a very simple
function!) or (also hard to believe) function "try" from Parsec has some
problems.
Anyway I get this answer:
Prelude ParseSHtml> pf parseHtmlFrg "ptest.txt"
Left "ptest.txt" (line 5, column 2):
unexpected "/"
expecting element name
when I'm parsing this file:
<div id="normtext">
one line with break<br />
another line <br /><br />
Mail: <a href="mailto:user at dom.at">user at dom.at</a>
</div>
with this code (sorry for the longer mail):
import Text.ParserCombinators.Parsec hiding (label)
import Text.XHtml.Strict
-- Helper function: parse a string up to one of the given chars
upTo :: [Char] -> Parser [Char]
upTo ds = many1 (noneOf ds)
parseHtmlFrg :: Parser Html
parseHtmlFrg = do many space
choice [parseElem, parseText]
<?> "html fragment"
parseElem :: Parser Html
parseElem = do en <- parseElTag
many1 space
(ats, cnt) <- restElem en
return $ compElem en cnt ! ats
<?> "html element"
-- Compose a html element from tag name and content
compElem en cnt = if isNoHtml cnt then itag en else tag en cnt
parseElTag :: Parser String
parseElTag = do char '<'
en <- elemName
return en
<?> "element tag"
elemName :: Parser String
elemName = many1 lower <?> "element name"
restElem :: String -> Parser ([HtmlAttr], Html)
restElem nm = do ats <- parseAttList
ht <- (restElNoCont <|> restElCont nm)
return (ats, ht)
<?> ("> or /> to close the tag " ++ nm)
-- Rest element with no content
restElNoCont = do char '/'
char '>'
return noHtml
<?> "/>"
-- Rest element with content
restElCont nm = do char '>'
many space
els <- parseProperCont nm
return $ concatHtml els
<?> "element with content"
-- Parse closing tag or proper content(s)
parseProperCont :: String -> Parser [Html]
parseProperCont nm = try (do closing nm
return []
)
<|> (do h <- parseHtmlFrg
hs <- parseProperCont nm
return (h:hs)
)
-- <|> return []
<?> "proper element content"
closing nm = do char '<'
char '/'
nm1 <- elemName
char '>'
if nm1 == nm
then return ()
else fail $ nm ++ ", encountered " ++ nm1
<?> ("closing of " ++ nm)
-- Parse a html attribute
parseAttr :: Parser HtmlAttr
parseAttr = do at <- many1 lower
char '='
va <- parseQuote
many space
return $ strAttr at va
<?> "Attribut"
parseAttList = many1 parseAttr <|> return [] <?> "attribute list"
-- Parse a quoted string
parseQuote :: Parser String
parseQuote = do char '"'
cs <- upTo ['"']
char '"'
return cs
-- Parse a text element
parseText :: Parser Html
parseText = do s <- upTo "<"
return (stringToHtml s)
<?> "some text"
-- For tests:
pf p file = parseFromFile p file
Nicu
More information about the Haskell-Cafe
mailing list