2013-05-14 6 views
5

次のように:How do I test for exactly 2 characters with fparsec?パーサー識別子と自由形式のテキスト。 FParsecでこれを行うことはできますか?

フリーフォームのテキストの後に続く識別子のペアで構成される文字列を解析する必要があります。私は簡単に、改行の形をした識別子と正確に2つの大文字とそれに続くスペースを含むパーサを構築することができます。前の識別子に関連付けられているフリーフォームテキストは、次の識別子までのすべてのもので、次の識別子までは含まれません。例えばので

AB Now is the 
time for all good 
men. 
CD Four score and seven years ago EF our. 

は私の問題は、私が構築する方法がわからない2つの識別子ABCDと自由形式のテキストの2枚

Now is the \ntime for all good men.
Four score and seven years ago EF our.

が含まれていますフリーフォームのテキストと一致するが、識別子と一致しないパーサー。これはバックトラックを行う必要があるケースですか?

どうすればいいですか?

答えて

3

私はあなたが探しているのはnotFollowedByだと思います。これはトリックを行う必要があります:

// adapted from the other question 
let identifier = skipNewline >>. manyMinMaxSatisfy 2 2 CharParsers.isUpper 

let freeform = manyChars (notFollowedBy identifier >>. anyChar) 
4

Tarmilは簡単な解決策を投稿しました。ここで

は先頭に改行を必要としない別の変形は、線のみの最後に次の識別子をチェックします:あなたが使用される第二のパーサーを最適化したい場合は

let id = manyMinMaxSatisfyL 2 2 isUpper "ID" .>> pchar ' ' 

let text = 
    stringsSepBy (restOfLine true) 
       ((notFollowedBy ((id >>%()) <|> skipNewline <|> eof)) >>% "\n") 

let parser = many (id .>>. text) 

あなたはこの質問にコメントしてください可能性があり、

let notFollowedByIdOrEmptyLineOrEof : Parser<string,_> = 
    fun stream -> 
     let cs = stream.Peek2() 
     let c0, c1 = cs.Char0, cs.Char1 
     if c0 = '\r' || c0 = '\n' || c0 = EOS 
      || (isUpper c0 && isUpper c1 && stream.Peek(2) = ' ') 
     then Reply(Error, NoErrorMessages) 
     else Reply("\n") 

let text2 = stringsSepBy (restOfLine true) 
         notFollowedByIdOrEmptyLineOrEof 
+0

こんにちは:https://bitbucket.org/fparsec/main/issue/29/portable-version-of- stringsSepByコンビネータは、次のバージョンでそれを置き換えることができますfparsec – Den

関連する問題