Parsec: No newline after last line and 'many'

Iavor Diatchki diatchki@cse.ogi.edu
Sun, 7 Apr 2002 12:13:34 -0700


hello,

does this work?

> pLine = many (noneOf "\n")
> pLines = pLine `sepEndBy` char '\n'

bye
iavor


On Sun, Apr 07, 2002 at 07:44:42PM +0200, Till Doerges wrote:
> Hi folks,
> 
> when trying to write a parser for unix-style textfiles, I stumbled
> across the problem having to distinguish between lines w/ a newline
> character at the end and lines w/o a newline at the end (i.e. the last
> line in a file doesn't have to have it).
> 
> Eventually I want to be able to use my parser 'linep' with 'many' on
> no matter which text-files.
> 
> The first version I tried, was
> 
> --- snip ---
> skip1 :: Parser()
> skip1 = do
>     anyChar
>     return()
> 
> linep :: Parser(String)
> linep = do { cs <- many (noneOf "\n")
>            ; skip1
>            ; return cs
>            }
> --- snap ---
> 
> Well, this only works, if the last line in the file is also terminated
> by '\n'. So, I tried to be smarter using:
> 
> --- snip ---
> lineWith :: Parser(String)
> lineWith = try (do { cs <- many (noneOf "\n")
> 		   ; skip1
> 		   ; return cs
> 		   })
> 
> lineWithOut :: Parser(String)
> lineWithOut = many anyChar
> 
> linep :: Parser(String)
> linep =     lineWith
> 	<|> lineWithOut
> 	<?> "line"
> --- snap ---
> 
> But this doesn't do the trick either, instead it'll overflow my stack
> if used in conjunction w/ 'many':
> 
> --- snip ---
> parse (do {many linep}) "stdin" (unlines ["hallo","ballo"])
> ^CInterrupted.
> ReadOrig> parse (do {many linep}) "stdin" ("hallo\nballo")
> ^CInterrupted.
> --- snap ---
> 
> Avoiding many OTOH works fine:
> --- snip ---
> parse (do {linep;linep}) "stdin" (unlines ["hallo","ballo"])
> Right "ballo"
> ReadOrig> parse (do {linep;linep}) "stdin" ("hallo\nballo")
> Right "ballo"
> --- snap ---
> 
> Besides these two attempts explicitly spelled out I've made quite a
> few others, but none of them did the trick.
> 
> The documentation for 'try' says that it'll only consume input upon
> success, but why doesn't it work w/ 'many'?
> 
> I know about the Prelude-functions unlines, lines etc., but they don't
> really help, since linep should be used within another parser of mine.
> 
> I am using Parsec as of Jan 25, 2001 (the version included w/ ghc 5.02).
> 
> Any hints/solutions/... would be greatly appreciated!
> 
> Bye -- Till
> _______________________________________________
> Haskell mailing list
> Haskell@haskell.org
> http://www.haskell.org/mailman/listinfo/haskell

-- 
---------------------------------------+----------------------------------------
Iavor S. Diatchki                      | email: diatchki@cse.ogi.edu           
Dept. of Computer Science              | web: http://www.cse.ogi.edu/~diatchki
OGI School of Science and Engineering  | work phone: 5037481631                
OHSU                                   | home phone: 5036434085                
---------------------------------------+----------------------------------------