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?
2009/8/5 Paul Sujkov <psuj...@gmail.com> > Hi everybody, > > suppose I have two different parsers: one just reads the string, and > another one parses some values from it. E.g.: > > parseIntList :: Parser [Integer] > parseIntList = do > char '(' > res <- liftM (map read) (sepBy1 (many1 digit) (char ';')) > char ')' > return res > > parseIntString :: Parser String > parseIntString = manyTill anyChar eof > > so for some input like this - "(1;2;3;4)" - I will have two different > result: > > *Parlog> parseTest parseIntList "(1;2;3;4)" > [1,2,3,4] > *Parlog> parseTest parseIntString "(1;2;3;4)" > "(1;2;3;4)" > > 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: > > *Parlog> parseTest parseIntListAndString "(1;2;3;4)" > ([1,2,3,4], "(1;2;3;4)") > > 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 > > 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 > > 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: > > parseIntListAndString :: Parser ([Integer], String) > parseIntListAndString = do > str <- parseIntString > return (res str, str) > where res str = case (parse parseIntList "" str) of > Left err -> [] > Right val -> val > > 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 > > 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? > > -- > Regards, Paul Sujkov > -- Regards, Paul Sujkov
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe