使用MegaParsecparse函式,我可以運行決議器,并ParseErrorBundle在它失敗時得到一個。
我知道我可以ParseErrorBundle使用errorBundlePretty.
我也知道,我能得到一個串列ParseError的從ParseErrorBundle使用bundleErrors。而且我可以用parseErrorPretty或來列印這些parseErrorTextPretty。
我希望能夠運行決議器,如果它失敗,則獲取 的串列(SourcePos, Text),以便我知道各個錯誤訊息和每個錯誤的位置。我想不出一種優雅的方式來做到這一點。雖然我可以在理論上嬰兒床從相當大量的源代碼errorBundlePretty,我覺得像折疊錯誤,并用reachOffset推進PosState不能去這個最簡單的方法?
uj5u.com熱心網友回復:
請注意,如果您使用megaparsec >= 7.0.0,我認為您應該attachSourcePos用于遍歷。它回傳NonEmpty的(ParseError, SourcePos)對。我認為它看起來像:
import qualified Text.Megaparsec as MP
import qualified Data.Text as T
import Data.List.NonEmpty (NonEmpty (..))
import Data.Void
annotateErrorBundle :: MP.ParseErrorBundle T.Text Void -> NonEmpty (MP.SourcePos, T.Text)
annotateErrorBundle bundle
= fmap (\(err, pos) -> (pos, T.pack . MP.parseErrorTextPretty $ err)) . fst $
MP.attachSourcePos MP.errorOffset
(MP.bundleErrors bundle)
(MP.bundlePosState bundle)
請注意,與您建議的答案不同,通過錯誤包的遍歷正確地attachSourcePos執行緒化PosState,而不是在每次reachOffset呼叫后丟棄更新的狀態。因此,我相信對于大量錯誤,它會更有效率。(它還使用reachOffsetNoLine代替reachOffsetwhich 對于某些流型別可能更有效。
如果您使用的是megaparsec < 7.0.0,您可能想嘗試attachSourcePos從更高版本中調整源代碼。
uj5u.com熱心網友回復:
我能夠讓這個作業如下:
import qualified Text.Megaparsec as MP
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.Text as T
annotateErrorBundle :: MP.ParseErrorBundle Text Void -> NonEmpty (MP.SourcePos, Text)
annotateErrorBundle bundle = (\e -> (errorSrcPos e, T.pack $ MP.parseErrorTextPretty e)) <$> MP.bundleErrors bundle
where
initialPosState = MP.bundlePosState bundle
errors = MP.bundleErrors bundle
errorSrcPos e = MP.pstateSourcePos . snd $ MP.reachOffset (MP.errorOffset e) initialPosState
我懷疑這可能不是非常有效,因為我reachOffset每個錯誤都呼叫一次。然而,在實踐中,錯誤串列可能并沒有那么大,所以我并不太擔心。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/370710.html
