2013-05-13 53 views
4

我有以下程序運行。它將一行文本分成兩部分,第一部分是一個標識符,第二部分是該行的其餘部分。我的標識符(factID)的解析器將任何字符串作爲標識符,這不是(非常)我想要的。我想要的是一個解析器,只有遇到兩個連續的大寫字母時纔會成功。因此,例如「AA」應該成功,而「A」,「A1」或「AAA」不應該成功。如何用fparsec測試2個字符?

我無法弄清楚的是如何構造一個查找固定長度標記的解析器。我想可能CharParsers.next2CharsSatisfy可能是我正在尋找的功能,但我無法弄清楚如何正確使用它。

open FParsec 

let test p str = 
    match run p str with 
    | Success(result, _, _) -> printfn "Success: %A" result 
    | Failure(errorMsg, _, _) -> printfn "Failure: %s" errorMsg 

let ws = spaces 
let str_ws s = pstring s .>> ws 

type StringConstant = StringConstant of string * string 

let factID = 
    let isIdentifierFirstChar c = isLetter c 
    let isIdentifierChar c = isLetter c 

    many1Satisfy2L isIdentifierFirstChar isIdentifierChar "factID" 

let factText = 
    let isG c = isLetter c || isDigit c || c = ' ' || c = '.' 
    manySatisfy isG 


let factParse = pipe3 factID (str_ws " ") factText 
         (fun id _ str -> StringConstant(id, str)) 


[<EntryPoint>] 
let main argv = 
    test factParse "AA This is some text."  // This should pass 
    test factParse "A1 This is some text."  // This should fail 
    test factParse "AAA This is some text."  // This passes but I want it to fail 
    0 // return an integer exit code 
+0

它應該接受任何兩個大寫字符,例如,「AB」,或者只有兩個相同字符的? – Daniel 2013-05-13 16:13:29

+0

任何兩個大寫字母;所以「AA」,「AB」,「ZQ」等都可以。 – JonnyBoats 2013-05-13 16:17:53

+1

'next2CharsSatisfy f1 f2'就像'followedBy(滿足f1 >>。滿足f2)'一樣使用,即它只向前看,但不消耗輸入。如Daniel所建議的,如果你想消費兩個字母,你可以結合兩個單獨的char分析器或使用'manyMinMaxSatisfy'變體之一。如有疑問,請使用帶有L後綴的帶標籤的變體,以便獲得更好的錯誤消息。 – 2013-05-13 16:31:16

回答

4

我認爲這會做

let pFactID = manyMinMaxSatisfy 2 2 Char.IsUpper 
+0

我使用的實際代碼是: let factID = manyMinMaxSatisfy 2 2 CharParsers.isUpper – JonnyBoats 2013-05-13 20:30:06