2012-10-11 62 views
0

我似乎無法成功解析標準輸入流與FParsec。我減少了我的情況,以這種非常簡單的代碼:FParsec - 如何解析標準輸入流

match (runParserOnStream (pstring "test" .>> FParsec.CharParsers.newline)() "stdin" (Console.OpenStandardInput()) Console.InputEncoding) with 
    | Success(result, _, _) -> printfn "Success: %A" result 
    | Failure(errorMsg, perr, _) -> printfn "Failure: %s" errorMsg 

但是當我運行該程序,輸入字符串測試,然後按Enter鍵,它掛在那裏,我似乎無法找出原因..

會是什麼解決方案?

+0

我想你永遠不會到達輸入流的末尾。 – Daniel

+0

是的,這也是我的猜測,但是應該有辦法告訴FParsec,一旦正確的表單被解析並且沒有歧義,它就會停止,否則就意味着沒有辦法做REPL一個FParsec解析器。 –

+0

我的猜測是它不解析,直到它的緩衝區已滿。 – Daniel

回答

6

出於性能原因和簡單起見,FParsec讀取輸入流逐塊(或開始解析之前讀取完整的流成一個字符串)。見例如這個答案的一些更多的細節:Chunked Parsing with FParsec

如果你想解析來自REPLI FParsec的輸入,你可以實現一個簡單的掃描器,等待輸入流中的終止符(例如,一個「;;」後跟一個換行符,就像在FSI控制檯中一樣),然後,當它遇到這樣一個終止符時,將輸入複製到終結符到一個字符串中,然後交給FParsec解析器進行評估。

+0

嘿斯蒂芬,這是我自己做的,因爲我不想花費太多時間在它上面拖動毛髮。謝謝 ! –

2

由於FParsec的源代碼可用,因此很容易就可以逐步瀏覽並看到它讀取輸入流,直到緩衝區已滿或流信號結束爲止。

或者,可以一次讀取的行:

let rec parseConsoleInput() = 
    let parser = pstring "text" .>> eof 
    Console.Write("> ") 
    match Console.ReadLine() with 
    | null | "" ->() 
    | input -> 
    match run parser input with 
    | Success(result, _, _) -> printfn "Success: %A" result 
    | Failure(msg, _, _) -> printfn "Failure: %s" msg 
    parseConsoleInput() 
+0

在由A - >「test」定義的語法中,唯一有效的輸入是「test」,因此Fparsec *可能在分析所述字符串後停止。如果流中有剩餘字符,則根據語法輸入不正確。 –

+0

此外,什麼是可分析塊是由語法定義的,而不是以任何其他方式定義。運行F#repl爲我的意思的例子。 –

+1

在F#REPL中,您必須用「;;」來終止輸入。如果你想用FParsec解析這樣一個REPL的輸入,你可以簡單地掃描輸入「;;」,將由「;;」分隔的塊複製到字符串中,然後用FParsec分別解析這些字符串。 –