[Haskell-cafe] Re: A parsec question
Stephen Tetley wrote: Does this one give the expected error message for Parsec3.1 - unfortunately I can't test as I'm still using Parsec 2.1.0.1. parser = block (many digit ? digit) Unfortunately, no. Cheers Ben ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: A parsec question
On Sun, Oct 3, 2010 at 11:55 AM, Ben Franksen ben.frank...@online.de wrote: Stephen Tetley wrote: Does this one give the expected error message for Parsec3.1 - unfortunately I can't test as I'm still using Parsec 2.1.0.1. parser = block (many digit ? digit) Unfortunately, no. Cheers Ben Hey folks, sorry about this one - my changes to parsec in 3.1 made these error messages worse. I've sent a patch off to the maintainer which fixes the examples in this thread. Antoine ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: A parsec question
On Wed, Sep 29, 2010 at 1:01 PM, Daniel Fischer daniel.is.fisc...@web.de wrote: On Wednesday 29 September 2010 19:10:22, Ben Franksen wrote: Note the last line mentions only '}'. I would rather like to see expecting } or digit since the parser could very well accept another digit here. parsec2 did that, I don't know whether that change is intentional or accidental. I came up with a smaller example which shows a similar problem: bracket = char '{' * return () test = bracket * (bracket | return ()) * char 'a' For the input {b the error message should mention that we can take either a '{' or an 'a', however it only mentions the 'a'. However I know how to fix this one, and it doesn't fix the bug evidenced by the above program. Antoine ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: A parsec question
Am 29.09.2010 20:01, schrieb Daniel Fischer: On Wednesday 29 September 2010 19:10:22, Ben Franksen wrote: Note the last line mentions only '}'. I would rather like to see expecting } or digit since the parser could very well accept another digit here. parsec2 did that, I don't know whether that change is intentional or accidental. Right, parsec2 or parsec-2.1.0.1 still does so. (parsec-3 behaves differently wrt error messages.) Try ghc-pkg hide parsec so that parsec-2.1.0.1 will be taken: import Text.ParserCombinators.Parsec import Control.Monad infixl 1 () :: Monad m = m a - m b - m a () = liftM2 const block p = char '{' p char '}' parser = block (many (digit)) main = parseTest parser {123a} *Main main Loading package parsec-2.1.0.1 ... linking ... done. parse error at (line 1, column 5): unexpected a expecting digit or } (1) What is the reason for this behaviour? (2) Is there another combinator that behaves as I would like? (3) Otherwise, how do I write one myself? ask derek.a.elk...@gmail.com (CCed) Cheers Christian I just saw that Christian Maeder answered a similar question recently. I tried his suggestion of using manyTill and bingo: {-# LANGUAGE NoMonomorphismRestriction #-} import Control.Applicative ((*),(*)) import Text.Parsec block p = char '{' * p * char '}' parser = block (manyTill digit (char '}')) main = parseTest parser {123a} gives parse error at (line 1, column 5): unexpected a expecting } or digit So far so good. I wonder whether this parser is as efficient as the original one. manyTill p end = scan where scan = do{ end; return [] } | do{ x - p; xs - scan; return (x:xs) } I'm not sure, but I suspect it's less efficient. Perhaps manyTill' p end = scan [] where scan acc = do { end; return (reverse acc) } | do { x - p; scan (x:acc) } is more efficient (depends on Parsec's bind which is more efficient), you could test. Also, this style is less modular, as I have to mention the terminator in two places. That's not the main problem. `manyTill' consumes the ending token, so block (manyTill whatever (char '}')) needs two '}' to succeed. You would need block (manyTill digit (lookAhead (char '}')) to replicate the behaviour of block (many digit). Is there a non-greedy variant of 'many' so that modularity gets restored and efficiency is not lost? Cheers Ben ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: A parsec question
Christian Maeder wrote: Am 29.09.2010 20:01, schrieb Daniel Fischer: On Wednesday 29 September 2010 19:10:22, Ben Franksen wrote: Note the last line mentions only '}'. I would rather like to see expecting } or digit since the parser could very well accept another digit here. parsec2 did that, I don't know whether that change is intentional or accidental. Right, parsec2 or parsec-2.1.0.1 still does so. (parsec-3 behaves differently wrt error messages.) Try ghc-pkg hide parsec so that parsec-2.1.0.1 will be taken: I need parsec-3 since I use it as a monad transformer over IO so I can do IO during parsing. And I want efficiency, too, so did not consider parsec-3.0.*. Cheers Ben ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: A parsec question
Ben Franksen wrote: import Control.Applicative ((*),(*)) import Text.Parsec import Text.Parsec.Char block p = char '{' * p * char '}' parser = block (many digit) main = parseTest parser {123a} gives the output parse error at (line 1, column 5): unexpected a expecting } Note the last line mentions only '}'. I would rather like to see expecting } or digit since the parser could very well accept another digit here. (1) What is the reason for this behaviour? (2) Is there another combinator that behaves as I would like? (3) Otherwise, how do I write one myself? I just saw that Christian Maeder answered a similar question recently. I tried his suggestion of using manyTill and bingo: {-# LANGUAGE NoMonomorphismRestriction #-} import Control.Applicative ((*),(*)) import Text.Parsec block p = char '{' * p * char '}' parser = block (manyTill digit (char '}')) main = parseTest parser {123a} gives parse error at (line 1, column 5): unexpected a expecting } or digit So far so good. I wonder whether this parser is as efficient as the original one. Also, this style is less modular, as I have to mention the terminator in two places. Is there a non-greedy variant of 'many' so that modularity gets restored and efficiency is not lost? Cheers Ben ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: A parsec question
On Wednesday 29 September 2010 19:10:22, Ben Franksen wrote: Note the last line mentions only '}'. I would rather like to see expecting } or digit since the parser could very well accept another digit here. parsec2 did that, I don't know whether that change is intentional or accidental. (1) What is the reason for this behaviour? (2) Is there another combinator that behaves as I would like? (3) Otherwise, how do I write one myself? I just saw that Christian Maeder answered a similar question recently. I tried his suggestion of using manyTill and bingo: {-# LANGUAGE NoMonomorphismRestriction #-} import Control.Applicative ((*),(*)) import Text.Parsec block p = char '{' * p * char '}' parser = block (manyTill digit (char '}')) main = parseTest parser {123a} gives parse error at (line 1, column 5): unexpected a expecting } or digit So far so good. I wonder whether this parser is as efficient as the original one. manyTill p end = scan where scan = do{ end; return [] } | do{ x - p; xs - scan; return (x:xs) } I'm not sure, but I suspect it's less efficient. Perhaps manyTill' p end = scan [] where scan acc = do { end; return (reverse acc) } | do { x - p; scan (x:acc) } is more efficient (depends on Parsec's bind which is more efficient), you could test. Also, this style is less modular, as I have to mention the terminator in two places. That's not the main problem. `manyTill' consumes the ending token, so block (manyTill whatever (char '}')) needs two '}' to succeed. You would need block (manyTill digit (lookAhead (char '}')) to replicate the behaviour of block (many digit). Is there a non-greedy variant of 'many' so that modularity gets restored and efficiency is not lost? Cheers Ben ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: [Haskell] Parsec question: attempted 'notMatching' combinator
[To Haskell-cafe...] At 16:57 17/02/04 -0500, Andrew Pimlott wrote: On Tue, Feb 17, 2004 at 07:48:52PM +, Graham Klyne wrote: Thanks! That got me going, though not with quite what you suggested. I ended up with this: [[ notMatching :: Show a = GenParser tok st a - GenParser tok st () notMatching p = do { a - try p ; unexpected (show a) } | return () ]] which does the required job for me. Oops, that does look better. I knew the try had to go somewhere. :-) The only remaining problem is when p succeeds but does not consume any input, eg eof. In this case, the | return () cannot distinguish it from p failing. I didn't realize at first what a dirty trick this function uses: It distinguishes success or failure of p by whether any input from the first part (before | return ()) was consumed. I don't think it is possible (or desirable!) to get this approach 100% right: By erasing the success of p, you lose the information you need. What about a more prosaic implementation: notFollowedBy' :: Show a = GenParser tok st a - GenParser tok st () notFollowedBy' p= do res - do a - try p; return $ Just a | return Nothing case res of Just a - unexpected (show a) Nothing - return () I don't see why that would work where the above case does not; i.e. when p consumes no input. Or indeed, your later, preferred version: [[ notFollowedBy' :: Show a = GenParser tok st a - GenParser tok st () notFollowedBy' p= join $ do a - try p; return (unexpected (show a)) | return (return ()) ]] This works for the tests I've tried, but there's one little quirk with error reporting: I never really cared so much about that bit! #g -- aNoBC = do char 'a' notFollowedBy' $ do char 'b'; char 'c' *Main parseTest (aNoBC char 'e') abe parse error at (line 1, column 2): unexpected e expecting c or e It seems that parsec both misreports which token is unexpected (should be b, and thinks that the failure to match c is a problem, even though notFollowedBy' succeeded. Using your version caused the notMatching parser to be equivalent to: return () presumably, because the failure was protected by the try combinator? Or perhaps more accurately, the success (of p) was protected by the try! Ie, the unexpected and the try together undid the tell-tale token consumption of p. Andrew Graham Klyne For email: http://www.ninebynine.org/#Contact ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: [Haskell] Parsec question: attempted 'notMatching' combinator
On Wed, Feb 18, 2004 at 10:48:39AM +, Graham Klyne wrote: [To Haskell-cafe...] At 16:57 17/02/04 -0500, Andrew Pimlott wrote: On Tue, Feb 17, 2004 at 07:48:52PM +, Graham Klyne wrote: [[ notMatching :: Show a = GenParser tok st a - GenParser tok st () notMatching p = do { a - try p ; unexpected (show a) } | return () ]] notFollowedBy' :: Show a = GenParser tok st a - GenParser tok st () notFollowedBy' p= do res - do a - try p; return $ Just a | return Nothing case res of Just a - unexpected (show a) Nothing - return () I don't see why that would work where the above case does not; i.e. when p consumes no input. Because (in my version) when p succeeds, the left side of | succeeds; in the original, the left side of | always failed. Instead of throwing the error immediately after p succeeds, I package it up in Just a and throw it later. So there is no possibility for the right side of | to be evaluated by accident, as there was in the original. I think the key is to understand the paragraph in a previous message about the original implementation being a dirty trick. Andrew ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe