FParsec: `sepBy` countdown

Consider the following toy grammar and parser:

(* in EBNF:
  ap = "a", { "ba" }
  bp = ap, "bc"
*)
let ap = sepBy1 (pstring "a") (pstring "b")
let bp = ap .>> (pstring "bc")
let test = run bp "abababc"

I get the following output:

Error in Ln: 1 Col: 7
abababc
      ^
Expecting: 'a'

It is clear that he sepBy1sees the latter band expects him to lead to another aif he does not find him. Is there an option sepBy1that bounces through band makes this parsing successful? Is there a reason why I should not use this instead?

+4
source share
3 answers

This is one way to implement this option sepBy1:

let backtrackingSepBy1 p sep = pipe2 p (many (sep >>? p)) (fun hd tl -> hd::tl)

, . , , ( ), .

+3

FParsec sepBy, , ( ) , sepBy. , , .

, , sepEndBy , , sepEndBy1 . - , Python , : [ 1, 2, 3, ]. sepEndBy1 , , . , sepEndBy1 . .

// This parser will be either a separator *or* a prefix of the next item
let sharedParser = pstring "b"

let ap = sepEndBy1 (pstring "a") sharedParser
let restOfBp = pstring "c"
let bp = restOfBp <|> (pipe2 sharedParser restOfBp (fun b c -> b + c))

pipe2 - , . , , b c bc , > c , . c , b , <|>, b , c , b ; c, , . , , .

sepEndBy1 , b c , , , sepBy, FParsec . FParsec , , , . sepEndBy1 , .

+2

, , , - :

let ap = pstring "a" >>. many (pstring "ba")
let bp = ap .>> pstring "bc"

, pstring "ba" , , pstring ; "ba", , , bp b, .

, (.. ap ), , EBNF, :

ap = "ab", { "ab" }
cp = ap, "c"

FParsec:

let ap = many1 (pstring "ab")
let cp = ap .>> pstring "c"
+1

Source: https://habr.com/ru/post/1683588/


All Articles