[Haskell-cafe] Re: Proving my point

Daniel Fischer daniel.is.fischer at web.de
Fri May 16 16:25:40 EDT 2008


Am Freitag, 16. Mai 2008 21:33 schrieb Achim Schneider:
> Andrew Coppin <andrewcoppin at btinternet.com> wrote:
> > Wait... "unexpected end of input; expecting [...] end of input [...]"
> >
> > That's just *wrong*...! ;-)
> >
> > But don't despaire - show us your parser and what it's supposed to
> > parse, and I'm sure somebody [maybe even me] will be able to tell you
> > what's up.
>
> This is what I came up with while simplifying the parser:
>
> import Text.Parsec
>
> identifier = do
>     whiteSpace
>     s <- many1 letter
>     whiteSpace
>     return s
>
> whiteSpace = do
>     eof <|> ((many $ choice [ char ' ', newline ]) >> return ())
>
> main = do
>     let syn = runParser (do
>         char '\\'
>         many1 identifier
>         char ':'
>         whiteSpace
>         identifier
>         whiteSpace
>         ) () "" "\\a b"
>     print syn

running char '\\' on input "\\a b", okay, no problem.
running many1 identifier on remaining input "a b"
1. whiteSpace: no eof, many (choice [char ' ', newline) returns [], all fine, 
nothing consumed
2. many1 letter, remainin input begins with 'a', okay, many1 letter returns 
"a", remaining input " b"
3. whiteSpace: n eof, one ' ' ~> ' ' consumed, remains "b"
first identifier parsed, try another one.
whiteSpace again consumes nothing, many1 letter returns "b", remaining input 
is null. whiteSpace finds eof, second identifier parsed, all input consumed.
Now there are two options for a successful parse,
a) another identifier
b) ':'
a)
1. whiteSpace, finds eof, consumes nothing, success
2. many1 letter fails immediately, nothing consumed, overall, identifier fails 
without consuming anything.
b) char ':' fails without consumption.

Drat, I want an identifier or a ':' here, I don't expect end of input yet.
"unexpected end of input"
"expecting "
Lemme look what would I need here to continue.
Ah, an identifier, how would that start? Oh, yes it could start with
"end of input"
what else? many (choice [char ' ', newline]), 'many', hmm doesn't require 
anything specific, I'll skip that, what then? many1 letter, oh, yes
", letter"
Or I could continue with char ':' here, so
" or \":\""

Oops, bad definition of whiteSpace, I'd say. Don't accept an eof unless you 
really don't want to continue.

>
> Admittedly, this is a quite degenerate case crouching in at least 10
> corners simultaneously. Anyway, I get
>
> % ./test
> Left (line 1, column 5):
> unexpected end of input
> expecting end of input, letter or ":"
>
>
> and if I change it to
>
> whiteSpace = do
>     (many eof >> return ())
>     <|> ((many $ choice [ char ' ', newline ]) >> return ())
>
> Left (line 1, column 3):
> unexpected " "
> expecting letter, end of input or ":"

Sure thing, (many eof) never fails, so the new whiteSpace is in fact
many eof >> return ()
So after having parsed the first identifier, we're trying to either parse 
another one or a ':'. First, identifier is tried. 
many eof succeeds, now try letter, that fails. so we have a successful start 
into many eof, hence, for identifier to succeed, we need more eofs or a 
letter next ~> "expecting end of input, letter"
Or we have no more identifiers, then we need
" or \":\""

>
>
> Please, please don't ask me for the rationale of using eof like this,
> you would get the same answer as if you'd ask me why I cast a stone into
> the sea.

And why did you do that?



More information about the Haskell-Cafe mailing list