[Haskell-cafe] Re: A parsec question

2010-10-03 Thread Ben Franksen
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

2010-10-03 Thread Antoine Latter
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

2010-10-02 Thread Antoine Latter
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

2010-09-30 Thread Christian Maeder
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

2010-09-30 Thread Ben Franksen
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

2010-09-29 Thread Ben Franksen
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

2010-09-29 Thread 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.

 
  (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

2004-02-18 Thread Graham Klyne
[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

2004-02-18 Thread Andrew Pimlott
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