Baffled by Parsec

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Baffled by Parsec

Colin Paul Adams
The tutorials I've found don't tell me what I want to know :-(

I have lines that begin with an integer, then white-space, and then
further structure to the end-of-line.

So for a starter, could you show me how to write a parser for the
integer (returning an Int), and how to combine it with a parser for
the rest of the line (take that as written - it isn't, but I'll try to
do that myself given such a kick-start).

Thanks.
--
Colin Adams
Preston Lancashire
Reply | Threaded
Open this post in threaded view
|

Baffled by Parsec

Daniel Fischer-4
Am Samstag, 21. Februar 2009 21:04 schrieb Colin Paul Adams:

> The tutorials I've found don't tell me what I want to know :-(
>
> I have lines that begin with an integer, then white-space, and then
> further structure to the end-of-line.
>
> So for a starter, could you show me how to write a parser for the
> integer (returning an Int), and how to combine it with a parser for
> the rest of the line (take that as written - it isn't, but I'll try to
> do that myself given such a kick-start).
>
> Thanks.

-- could also be Parser Int, if you don't need user-state
parseInt :: GenParser Char st Int
parseInt = do
        neg <- (char '-' >> return True) <|> (optional (char '+') >> return False)
        digs <- many1 digit
        let n | neg = negate $ read digs
              | otherwise = read digs
        return n

parseLine :: GenParser Char st LineStructure
parseLine = do
        -- spaces here, if there may be whitespace at the beginning of lines
        num <- parseInt
        spaces
        things <- parseRemainderOfLine
        return (combine num things)


The strategy is always the same, you write parsers for small things and
combine their results.
Note that things are somewhat tricky if the structure you want to parse isn't
very strict, if one of your possible parsers at some point in the parsing
process can fail, but not immediately and you need to backtrack, you have to
use the 'try' combinator as in

combo = (try parser1) <|> parser2

, but try is bad for performance, so use it only where it's necessary.
The latter part is notoriously difficult to identify for the inexperienced, so
until you know parsec better, it's okay to insert a few 'try's more than
necessary.

HTH, otherwise ask again,
Daniel

Reply | Threaded
Open this post in threaded view
|

Baffled by Parsec

Magnus Therning
In reply to this post by Colin Paul Adams
Colin Paul Adams wrote:
> The tutorials I've found don't tell me what I want to know :-(
>
> I have lines that begin with an integer, then white-space, and then
> further structure to the end-of-line.
>
> So for a starter, could you show me how to write a parser for the
> integer (returning an Int), and how to combine it with a parser for
> the rest of the line (take that as written - it isn't, but I'll try to
> do that myself given such a kick-start).

Maybe one of my old blog posts can help?

http://therning.org/magnus/archives/289

/M

--
Magnus Therning                        (OpenPGP: 0xAB4DFBA4)
magnus?therning?org          Jabber: magnus?therning?org
http://therning.org/magnus         identi.ca|twitter: magthe

Haskell is an even 'redder' pill than Lisp or Scheme.
     -- PaulPotts

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 197 bytes
Desc: OpenPGP digital signature
Url : http://www.haskell.org/pipermail/beginners/attachments/20090221/1ab208fc/signature.bin
Reply | Threaded
Open this post in threaded view
|

Baffled by Parsec

Colin Paul Adams
In reply to this post by Daniel Fischer-4
>>>>> "Daniel" == Daniel Fischer <[hidden email]> writes:

Thanks.

In fact all I need is:

parse_integer :: Parser Int
parse_integer = do
  digits <- many1 digit
  let n = read digits
  return n

as the format does not permit a sign.

What I was missing was digits. Where does it come from? I can't find
it with Hoggle.
--
Colin Adams
Preston Lancashire
Reply | Threaded
Open this post in threaded view
|

Baffled by Parsec

Felipe Lessa
On Sun, Feb 22, 2009 at 4:23 AM, Colin Paul Adams
<[hidden email]> wrote:
> parse_integer :: Parser Int
> parse_integer = do
>  digits <- many1 digit
>  let n = read digits
>  return n

'digits' come from 'digits <- many1 digit', and 'digit' comes from
Parsec itself[1] (and is the same as 'satisfy isDigit'[2,3]). I should
note that it is more idiomatic to write 'parse_integer' as

> import Control.Monad (liftM)
>
> parse_integer :: Parse Int
> parse_integer = read `liftM` many1 digit

if you don't need signs.

HTH,

[1] http://hackage.haskell.org/packages/archive/parsec/3.0.0/doc/html/Text-Parsec-Char.html#v%3Adigit
[2] http://hackage.haskell.org/packages/archive/parsec/3.0.0/doc/html/src/Text-Parsec-Char.html#digit
[3] http://hackage.haskell.org/packages/archive/base/4.0.0.0/doc/html/Data-Char.html#v%3AisDigit

--
Felipe.
Reply | Threaded
Open this post in threaded view
|

Baffled by Parsec

Colin Paul Adams
>>>>> "Felipe" == Felipe Lessa <[hidden email]> writes:

    Felipe> On Sun, Feb 22, 2009 at 4:23 AM, Colin Paul Adams
    Felipe> <[hidden email]> wrote:
    >> parse_integer :: Parser Int parse_integer = do digits <- many1
    >> digit let n = read digits return n

    Felipe> 'digits' come from 'digits <- many1 digit', and 'digit'
    Felipe> comes from Parsec itself[1] (and is the same as 'satisfy

Thanks. I meant digit, not digits.

    Felipe> [1]
    Felipe> http://hackage.haskell.org/packages/archive/parsec/3.0.0/doc/html/Text-Parsec-Char.html#v%3Adigit

OK - I see it here, but I was looking in
Text.ParserCombinators.Parsec.Char, where I can't see it (I can see
satisfy). I can't see how I am supposed to make that apparently
disconnected leap (other than by asking here, which works :-) )

--
Colin Adams
Preston Lancashire
Reply | Threaded
Open this post in threaded view
|

Baffled by Parsec

Felipe Lessa
On Sun, Feb 22, 2009 at 4:50 AM, Colin Paul Adams
<[hidden email]> wrote:
> OK - I see it here, but I was looking in
> Text.ParserCombinators.Parsec.Char, where I can't see it (I can see
> satisfy). I can't see how I am supposed to make that apparently
> disconnected leap (other than by asking here, which works :-) )

It is there, too! =P

http://hackage.haskell.org/packages/archive/parsec/3.0.0/doc/html/Text-ParserCombinators-Parsec-Char.html#v%3Adigit

--
Felipe.
Reply | Threaded
Open this post in threaded view
|

Baffled by Parsec

Colin Paul Adams
>>>>> "Felipe" == Felipe Lessa <[hidden email]> writes:

    Felipe> On Sun, Feb 22, 2009 at 4:50 AM, Colin Paul Adams
    Felipe> <[hidden email]> wrote:
    >> OK - I see it here, but I was looking in
    >> Text.ParserCombinators.Parsec.Char, where I can't see it (I can
    >> see satisfy). I can't see how I am supposed to make that
    >> apparently disconnected leap (other than by asking here, which
    >> works :-) )

    Felipe> It is there, too! =P

    Felipe> http://hackage.haskell.org/packages/archive/parsec/3.0.0/doc/html/Text-ParserCombinators-Parsec-Char.html#v%3Adigit

Hm.

It's not on my local copy of the GHC libraries documentation (ghc
6.10.1), although if I click the source button, I can see it.
--
Colin Adams
Preston Lancashire
Reply | Threaded
Open this post in threaded view
|

Baffled by Parsec

Felipe Lessa
On Sun, Feb 22, 2009 at 5:02 AM, Colin Paul Adams
<[hidden email]> wrote:
> Hm.
>
> It's not on my local copy of the GHC libraries documentation (ghc
> 6.10.1), although if I click the source button, I can see it.

My GHC 6.10.1 was compiled from source and Parsec comes from a
different ebuild (Gentoo), and digit isn't documented as well. It must
be some problem with parsec < 3, because Hackage has the same problem
for old Parsec[1].

[1] http://hackage.haskell.org/packages/archive/parsec/2.1.0.1/doc/html/Text-ParserCombinators-Parsec-Char.html

--
Felipe.
Reply | Threaded
Open this post in threaded view
|

Baffled by Parsec

Antoine Latter-2
On Sun, Feb 22, 2009 at 2:14 AM, Felipe Lessa <[hidden email]> wrote:
>
> My GHC 6.10.1 was compiled from source and Parsec comes from a
> different ebuild (Gentoo), and digit isn't documented as well. It must
> be some problem with parsec < 3, because Hackage has the same problem
> for old Parsec[1].
>
> [1] http://hackage.haskell.org/packages/archive/parsec/2.1.0.1/doc/html/Text-ParserCombinators-Parsec-Char.html
>

>From the sources:

> upper, lower, alphaNum, letter, digit, hexDigit, octDigit :: CharParser st Char

I think I've seen Haddock have trouble documenting declarations which
share a type signature in other places, as well.

Antoine