簡體   English   中英

使用Attoparsec在Haskell中讀取POT文件

[英]Reading POT files in Haskell using Attoparsec

我有一組我想要閱讀的POT文件,以便在Haskell中對翻譯進行后處理。 由於POT文件非常大,我想使用attoparsec來獲得良好的性能。

我嘗試使用hgettext ,但我的任務不是閱讀翻譯我的程序而只是解析POT文件。 基本上,我想獲得(comment, msgid, msgstr)元組的列表

假設要讀取的POT文件存儲在mypot.pot ,您可以使用此代碼直接在runghc運行。 我已經使用一些Khan Academy PO文件成功測試了這個,但它目前只適用於簡單文件(沒有復數等),但它很容易擴展:

{-# LANGUAGE OverloadedStrings #-}

import Prelude hiding (takeWhile)
import Data.Attoparsec.ByteString
import Data.Attoparsec.ByteString.Char8 hiding (takeWhile, skipWhile)
import qualified Data.Text.Encoding as TE
import Data.Text(Text)
import Data.Word
import Data.ByteString (unsnoc, ByteString)
import qualified Data.ByteString.Char8 as B
import Control.Applicative
import Control.Monad
import Data.Maybe
import Data.Either
import qualified Data.Text as T

data PORecord = PORecord {
        poComment :: Text,
        poMsgid :: Text,
        poMsgstr :: Text
    } deriving (Show, Eq)

takeTillEOL :: Parser ByteString
takeTillEOL = takeWhile (not . isEndOfLine)

parseMsgidMsgstrLine :: ByteString -> Parser Text
parseMsgidMsgstrLine key = do
  void (string key) <?> "Line key"
  skipSpace
  char '"' <?> "Opening Qutotation mark"
  val <- takeTillEOL
  endOfLine <?> "EOL"
  return $ TE.decodeUtf8 $ fromMaybe "" $ (fst <$> unsnoc val)

msgidLine = parseMsgidMsgstrLine "msgid"
msgstrLine = parseMsgidMsgstrLine "msgstr"

escapedTextLine :: Parser Text
escapedTextLine = char '"' *> (TE.decodeUtf8 <$> takeTillEOL) <* endOfLine
--escapedTextLine = do
--    char '"'
--    val <- takeTillEOL
--    return $ (traceShow val ())

nameP :: String -> Parser a -> Parser a
nameP str p = p <?> str

commentLine :: Parser Text
commentLine = nameP "comment line" $ do
    char '#' <?> "Line start hash"
    -- Skip space but not newline
    void $ many (char ' ')
    txt <- TE.decodeUtf8 <$> takeTillEOL
    endOfLine <?> "EOF"
    return txt

emptyLine :: Parser ()
emptyLine = skipSpace <* endOfLine

poRecord :: Parser PORecord
poRecord = do
    comments <- many1 commentLine <?> "Comments"
    msgidPrimary <- msgidLine <?> "msgid"
    extraMsgid <- many escapedTextLine <?> "Extra msgid"
    msgstrPrimary <- msgstrLine <?> "msgstr"
    extraMsgstr <- many escapedTextLine <?> "Extra msgstr"
    endOfLine
    let comment = T.intercalate "\n" comments
    let msgid = T.intercalate "\n" $ msgidPrimary : extraMsgid
    let msgstr = T.intercalate "\n" $ msgstrPrimary : extraMsgstr
    return $ PORecord comment msgid msgstr

poFile :: Parser [PORecord]
poFile =
    --let options = choice [emptyLine *> pure Nothing, ]
    many1 poRecord <?> "PO results"

main :: IO ()
main = do
    f <- B.readFile "mypot.pot"
    print $ parseOnly poFile f

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM