Hi there, here comes yet another beginner question
I am playing around with FParsec and trying to parse a file that looks similar to this:
3 -2 10 0
1 2 -4 0
2 0
Each line has some (at least 1) non-zero numbers separated by spaces and always ends with a 0.
My goal is to parse this input to an int list list
so that each line is in its own sublist and the trailing 0 is omitted. For example, the above instance should be parsed into
[[3; -2; 10]; [1; 2; -4]; [2]]
I looked around quite a lot on the FParsec website and managed to get the parsing to work. The problem I’m currently having is that I want to add each parsed line to the state so that in the end, the state will contain all the lines [[3; -2; 10]; [1; 2; -4]; [2]]
along with he number of lines parsed, 3 in this case. At the moment it only manages to keep track of the number of parsed lines.
I have the following record type to keep track of the lines and the number of lines
type UserState = {
numLines: int;
Lines: int list list
}
and the following parsers. As you can see I am running the addLine
function whenever I parse a line.
// Parse a number and consume the following whitespace
let pnumber: Parser<int32, UserState> =
pint32 .>> pchar ' '
// Parse a line
let pline : Parser<int32 list, UserState> =
manyTill pnumber <| (pchar '0') .>> addLine .>> newline
// Parse multiple lines until end of file
let plines : Parser<int32 list list, UserState> =
manyTill pline eof
The addLine function is defined as follows
let addLine =
updateUserState (fun s ->
{ s with
numLines= s.numLines+ 1
Lines = s.Lines
}
)
Im running this code on the same input example,
let input_string= "3 -2 10 0\n1 2 -4 0\n2 0\n"
// Default state
let defaultState = { Lines=[]; numLines=0 }
match runParserOnString plines defaultState "" input_string with
| Success (result, s, pos) -> printfn "%A %A %A" result s pos
| Failure(msg, error, _) -> printfn "%s %A" msg error
Running this gives me:
[[3; -2; 10]; [1; 2; -4]; [2]] { numLines= 3
Lines = []
} ("", Ln: 4, Col: 1)
So the state keeps track of the number of lines parsed in total, but not their contents…
Any ideas on how I can achieve this? Any help is appreciated!