Search code examples
f#fparsec

With FParsec how would I parse: line ending in newline <|> a line ending with eof


I'm parsing a file and want to throw away certain lines of the file I'm not interested in. I've been able to get this to work for all cases except for when the last line is a throwaway and does not end in newline.

I've tried constructing an endOfInput rule and joining it with a skipLine rule via <|>. This is all wrapped in a many. Tweaking everything I seem to either get a 'many succeeds without consuming input...' error or a fail on the skipLine rule when I don't try some kind of back track.

let skipLine = many (noneOf "\n") .>> newline |>> fun x -> [string x]

let endOfInput = many (noneOf "\n") .>> eof |>> fun x -> [string x]

test (many (skipLine <|> endOfInput)) "And here is the next.\nThen the last."

** this errors out on the skipLine parser at the last line

I've tried

let skipLine = many (noneOf "\n") .>>? newline |>> fun x -> [string x]

... and ...

let skipLine = many (noneOf "\n") .>> newline |>> fun x -> [string x]

test (many (attempt skipLine <|> endOfInput)) "And here is the next.\nThen the last."

** these produce the many error

Note: the output functions are just place holders to get these to work with my other rules. I haven't gotten into figuring out how to format the output. This is my first time using FParsec and I'm new to F#.


Solution

  • FParsec actually has a built-in parser that does exactly what you're looking for: skipRestOfLine. It terminates on either newlines or eof, just like what you're looking for.

    If you want to try to implement it yourself as a learning exercise, let me know and I'll try to help you figure out the problem. But if you just want a parser that skips characters until the end of the line, the built-in skipRestOfLine is exactly what you need.