2016-01-21 54 views
2

我有一個簡單的解析器scriptParser,它使用用戶狀態(類型和內容在這裏不重要)。它返回無論是對錯誤信息或Statement列表(再次,並不重要,這是怎麼定義的)一個Stringparsec,解析後訪問最後一個用戶狀態

parseScript :: String -> Either String [Statement] 
parseScript input 
    = let parsed = runParser scriptParser initialUserState "" input 
    in case parsed of 
      Left e -> Left (parseError input e) 
      Right ss -> Right ss 

parseError簡單地格式化基於einput錯誤消息(它顯示的代碼片斷圍繞錯誤位置)。

我的問題是,如果我想根據最後一個可用的用戶狀態自定義錯誤信息呢?顯然用戶狀態在runParser結束後不見了。 runParserT後允許訪問用戶狀態嗎?

+0

我擔心這個問題在語義上是不合格的。如果我的解析器是'(put 3 >> fail「)<|>(put 4 >> fail」「)',哪個狀態是」last「?更一般地說,如果出現錯誤,導致分支失敗的許多州中的哪一個應被視爲「最後可用」的一個,爲什麼? –

+0

謝謝@DanielWagner。通過「最後」,我指的是失敗前的那個人,無論這可能發生在哪裏。也許我是誤解,但是因爲內部Parsec狀態是回溯,所以我認爲這是有道理的。 – cornuz

+0

我期望在正常情況下,因爲回溯會出現*很多*失敗,每個失敗都有可能不同的「最終」狀態。目前尚不清楚這些失敗中的任何一個是否「特殊」足以保證其狀態被稱爲最終狀態。報告所有最終狀態可能在語義上是明智的,但在成功解析的情況下可能是嚴重的內存泄漏。 –

回答

4

據我所知,Parsec拋出錯誤的內置用戶狀態,所以無法恢復它。

或者,您可以將用戶狀態轉移到ParsecT s u m a中的m monad,因此您可能有ParsecT String() (State s) a

那樣,runParserT返回類型State s (Either ParseError a),您可以從中恢復最後一個狀態。

而且,由於ParsecT String() (State s) aMonadState sinstance,您可以使用get和其他MonadState功能沒有問題。

+0

對。內部狀態的一大優勢是它是回溯,我曾希望保持這種狀態。 – cornuz

+0

我也許可以通過使用這兩種狀態來實現這一點。像我現在所做的那樣使用內部狀態,但在每次更新後將其鏡像到全局狀態。醜陋,非常醜陋。但也許唯一的選擇,如果我想要一個回溯狀態,並從解析器外部訪問它? – cornuz

+0

我不確定這是否可行。即使您在更新時進行鏡像,您也不會在回溯時反映回退。 –

相關問題