2

I'm trying to implement a whitespace sensitive parser using FParsec, and I'm starting off with the baby step of defining a function which will parse lines of text that start with n chars of whitespace.

Here's what I have so far:

let test: Parser<string list,int>
  = let manyNSatisfy i p = manyMinMaxSatisfy i i p

    let p = fun (stream:CharStream<int>) ->
      let state = stream.UserState

      // Should fail softly if `state` chars wasn't parsed
      let result = attempt <| manyNSatisfy state (System.Char.IsWhiteSpace) <| stream

      if result.Status <> Ok 
        then result
        else restOfLine false <| stream

    sepBy p newline

My issue is that when I run

runParserOnString test 1 "test" " hi\n there\nyou" |> printfn "%A"

I get an error on "you". I was under the impression that attempt would backtrack any state changes, and returning Error as my status would give me soft failure.

How do I get ["hi"; "there"] back from my parser?

4

2 回答 2

3

亲,好尴尬。

我想要sepEndBy,也就是说我应该终止对分隔符的解析。

于 2012-07-24T08:43:57.450 回答
0

这看起来更地道。我已经硬编码1,但很容易提取为参数。

let skipManyNSatisfy i = skipManyMinMaxSatisfy i i
let pMyText =
    (                                               // 1st rule
        skipManyNSatisfy 1 System.Char.IsWhiteSpace // skip an arbitrary # of WhiteSpaces
        >>. restOfLine false |>> Some               // return the rest as Option
    )
    <|>                                             // If the 1st rule failed...
    (                                               // 2nd rule
        skipRestOfLine false                        // skip till the end of the line
        >>. preturn None                            // no result
    )
    |> sepBy <| newline                             // Wrap both rules, separated by newLine
    |>> Seq.choose id                               // Out of received string option seq, select only Some()
于 2012-07-25T12:20:34.560 回答