Well, I was too optimistic saying "I can return the updated state". I don't know how to do that actually. Maybe someone else here knows?<br><br><div class="gmail_quote">2009/8/5 Paul Sujkov <span dir="ltr"><<a href="mailto:psujkov@gmail.com">psujkov@gmail.com</a>></span><br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Hi everybody,<br><br>suppose I have two different parsers: one just reads the string, and another one parses some values from it. E.g.:<br>
<br>parseIntList :: Parser [Integer]<br>parseIntList = do<br> char '('<br>
res <- liftM (map read) (sepBy1 (many1 digit) (char ';'))<br> char ')'<br> return res<br><br>parseIntString :: Parser String<br>parseIntString = manyTill anyChar eof<br><br>so for some input like this - "(1;2;3;4)" - I will have two different result:<br>
<br>*Parlog> parseTest parseIntList "(1;2;3;4)"<br>[1,2,3,4]<br>*Parlog> parseTest parseIntString "(1;2;3;4)"<br>"(1;2;3;4)"<br><br>but the thing that I actually want is something like Parser ([Integer], String) - results from both parsers at a time, no matter whether one of them fails or not:<br>
<br>*Parlog> parseTest parseIntListAndString "(1;2;3;4)"<br>([1,2,3,4], "(1;2;3;4)")<br><br>it is impossible at first sight, because first parser to use will consume all the input, and there will be nothing to parse for the second one<br>
<br>Parsec contains "choice" function, but it is implemented via <|> and that is mplus - so it tries second alternative only if the first one fails. Is it possible to use two parsers for the same string (with try-like backtracking, no input actually consumed till the second parser finishes)? I can assume only dirty hacks with the GenParser internals - manual position storing and backtracking - but that is obviously not good<br>
<br>however, my first attempt to solve the problem was kind a like that: to parse string to String, and then to use it as an input for the next level parse call:<br><br>parseIntListAndString :: Parser ([Integer], String)<br>
parseIntListAndString = do<br> str <- parseIntString<br> return (res str, str)<br> where res str = case (parse parseIntList "" str) of<br> Left err -> []<br> Right val -> val<br>
<br>but the problems with such a method began when I switched from Parser to GenParser with user state: function parseIntList have to update the state, but it can't have the same state as the parseIntListAndString any more: it has it's own. I can explicitly pass the state from parseIntListAndString to parseIntList, but I see no suitable way for the parseIntList to update it. I can return the updated state value from the parseIntList function, and call setState on a result - but it seems rather ugly to mee. However, if nothing else will do, that is an alternative<br>
<br>it is of course possible to use two different parsers sequentially, but it is also very ineffective: I need to use such multiple parsing on a relatively small substring of the actual input, so little backtracking would be a much nicier approach. Any suggestions?<br clear="all">
<font color="#888888">
<br>-- <br>Regards, Paul Sujkov<br>
</font></blockquote></div><br><br clear="all"><br>-- <br>Regards, Paul Sujkov<br>