f# - FParsec failing on many -


i have test program:

open fparsec  let test p str =     match run p str     | success(result, _, _)   -> printfn "success: %a" result     | failure(errormsg, _, _) -> printfn "failure: %s" errormsg  let str s = pstring s  let seppart = skipnewline >>. pstring "-"  let part = manychars (notfollowedby seppart >>. anychar)  [<entrypoint>] let main argv =      let s = "aa 12345\nbb 6789\n-----\ncc 9876\ndd 54321\n-----"     test part s     test (many part) s      0 // return integer exit code 

the line {test part s} works expected next line, {test (many part) s} fails , don't understand doing wrong.

edit:

to clarify, trying have {test (many part) s} return ["aa 12345\nbb 6789"; "cc 9876\ndd 54321"]. in words, have input string composed of "pars" or "chunks" separated lines dashes. output want array each element 1 of parts , lines dashes discarded.

when execute example, fparsec throws exception following message:

additional information: (ln: 2, col: 8): combinator 'many' applied parser succeeds without consuming input , without changing parser state in other way. (if no exception had been raised, combinator have entered infinite loop.)

the problem part parser succeeds, if can parse empty string. can solve problem replacing manychars in definition of part many1chars.

if search e.g. "applied parser succeeds without consuming input" you'll find several discussions of similar errors on internet, including 1 in fparse's user guide: http://www.quanttec.com/fparsec/users-guide/parsing-sequences.html#the-many-parser

update: here's straightforward parser definition works:

let seppart = skipnewline                >>? (skipmany1satisfyl ((=) '-') "'-'"                      >>. (skipnewline <|> eof))  let part = many1charstill anychar seppart     let parser = many part 

note i'm using >>? in definition of seppart allow parser backtrack beginning if newline not followed dash. alternatively use attempt (skipnewline >>. ...), backtrack errors after initial dash. documentation many[chars]till p endp states equivalence many (notfollowedby endp >>. p) .>> endp not strictly true, because many[chars]till not backtrack notfollowedby. clarify documentation.

it's better performance if avoid backtracking using many[chars]till or notfollowedby possible. example, parse chunks of lines follows:

let id = manyminmaxsatisfyl 2 2 isupper "id (two capital letters)"  let line = id .>>. (pchar ' ' >>. restofline true)  let separator = many1satisfyl ((=) '-') "dash separator"                 >>. (skipnewline <|> eof)  let chunk = many1 line      let parser = sependby1 chunk separator 

note implementation doesn't require last chunk ended separator. if want that, instead use:

let chunk = many line .>> separator let parser = many chunk 

if want allow empty chunks sependby definition, use:

let chunk = many1 line <|> (notfollowedbyeof >>% []) let parser = sependby1 chunk separator 

Comments

Popular posts from this blog

SPSS keyboard combination alters encoding -

Add new record to the table by click on the button in Microsoft Access -

CSS3 Transition to highlight new elements created in JQuery -