Parsec: No newline after last line and 'many'
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
On Sun, Apr 07, 2002 at 07:44:42PM +0200, Till Doerges wrote:
Eventually I want to be able to use my parser 'linep' with 'many' on no matter which text-files.
'manyTill linep eof' and is what I wanted (looking at my first name, I should have gotten that one earlier... ;-) Bye -- Till
Hi Till, My guess is that you want to break up a text file into a list of lines with Parsec. (ie. "lines" functionality). A text file consists of non-newline characters seperated by newline characters:
import Parsec
plines :: Parser [String] plines = (many (noneOf "\n")) `sepBy` newline
You don't need any "try" or "manyTill" here. It seems to work on my system but I haven't tested it exhaustively.
TestLine> parseTest linep ("hi\nTill") ["hi","Till"]
TestLine> parseTest linep ("hi\nTill\n") ["hi","Till",""]
TestLine> parseTest linep ("hi\n\nTill\n") ["hi","","Till",""]
I hope this helps, All the best, Daan. ----- Original Message ----- From: "Till Doerges" <till@doerges.net> To: <haskell@haskell.org> Sent: Sunday, April 07, 2002 11:04 PM Subject: Re: Parsec: No newline after last line and 'many'
On Sun, Apr 07, 2002 at 07:44:42PM +0200, Till Doerges wrote:
Eventually I want to be able to use my parser 'linep' with 'many' on no matter which text-files.
'manyTill linep eof' and is what I wanted (looking at my first name, I should have gotten that one earlier... ;-)
Bye -- Till _______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
participants (2)
-
Daan Leijen -
Till Doerges