[Haskell-cafe] Parsec question
Daniel Fischer
daniel.is.fischer at web.de
Fri Apr 17 20:50:33 EDT 2009
Am Samstag 18 April 2009 01:33:44 schrieb Michael P Mossey:
> I've just about got this parser working, but wondering about something.
> Turns out I need "try" inside the "lookahead" here.
>
> parseText :: Parser String
> parseText = manyTill anyChar $ lookAhead (try (string "//"))
>
> Without try, if I give it an input with a single slash, like
>
> "some/text"
>
> It stops with the error "unexpected t; expecting //"
>
>
> I'm curious why that happens when lookAhead is used with manyTill like
> this. I was under the impression that if the end parser given to manyTill
> failed, then manyTill would just continue with the main parser. Apparently
> there are two ways to fail: in some contexts, failing means that manyTill
> will just continue. In other contexts, such as the one above, there is some
> sense in which 'string' demands the entire string to be present. Can anyone
> explain?
>
Looking at the source:
manyTill :: GenParser tok st a -> GenParser tok st end -> GenParser tok st [a]
manyTill p end = scan
where
scan = do{ end; return [] }
<|>
do{ x <- p; xs <- scan; return (x:xs) }
if end fails after consuming some input, manyTill p end fails.
lookAhead :: GenParser tok st a -> GenParser tok st a
lookAhead p = do{ state <- getParserState
; x <- p
; setParserState state
; return x
}
lookAhead fails if p fails, but if p fails, the state is not reset, so if p fails after
consuming some input, like in your example "some/text", where lookAhead (string "//")
consumes the slash and fails because the second expected slash is missing, that is not put
back and since something is consumed, the second branch of scan in manyTill isn't tried.
You could also have
keyword = try $ do
string "//"
kw <- many1 keywordChar
return (Keyword kw)
parseText = manyTill anyChar (lookAhead keyword)
Seems cleaner to have the slashes in keyword.
> Thanks,
> Mike
>
Cheers,
Daniel
More information about the Haskell-Cafe
mailing list