2013-05-14 8 views
5

W następstwie: How do I test for exactly 2 characters with fparsec?Identyfikatory analizatora i tekst w formacie swobodnym. Czy można to zrobić za pomocą FParsec?

Potrzebuję parsować ciąg składający się z par identyfikatorów, a następnie tekstu swobodnego. Mogę łatwo skonstruować analizator składni, który znajdzie identyfikatory, które mają postać nowej linii, po której następują dokładnie dwie wielkie litery, po których następuje spacja. Tekst swobodnego, który jest powiązany z poprzednim identyfikatorem, jest wszystkim następującym po identyfikatorze do następnego identyfikatora, ale bez niego.

Tak na przykład:

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

zawiera dwa identyfikatory AB i CD i dwa fragmenty tekstu nieregularnym kształcie

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

Mój problem jest nie wiem jak skonstruować analizator składniowy, który pasowałby do tekstu swobodnego, ale nie pasował do identyfikatorów. Czy jest to przypadek, w którym muszę wykonać wycofanie?

Czy można to zrobić, a jeśli tak, to w jaki sposób?

Odpowiedz

3

Myślę, że notFollowedBy jest tym, czego szukasz. To powinno załatwić:

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

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

Tarmil opublikował proste rozwiązanie.

Oto kolejny wariant, który nie potrzebuje nowej linii na początku i które sprawdza się następujący identyfikator tylko na końcu linii:

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

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

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

Jeśli chcesz zoptymalizować drugi parser używane z stringsSepBy syntezatora, można zastąpić go z poniższej wersji:

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

Cześć, czy mógłbyś skomentować na to pytanie: https://bitbucket.org/fparsec/main/issue/29/portable-version-of- fparsec – Den

Powiązane problemy