0

の.csvを変換しようとしています

femin,femin,1,f,woman,women,
aqu,aqu,1,f,water,waters,
..

.plの​​ようなファイルに

noun(femin,femin,1,f,trans(woman,women)).
noun(aqu,aqu,1,f,trans(water,waters)).
..

ここに私の現在のソースコードがあります:

-- get from "femin, femin, 1, f, woman, women" to noun(femin, femin, 1, f ,trans(woman,women)). 
import qualified Data.Attoparsec as P


data NounClause = NounClause
    {
        nom :: String,
        gen :: String,
        declension :: String,
        gender :: String,
        sgtrans :: String,
        pltrans :: String
    } deriving Show 

parseNounClause :: P.Parser NounClause

parseNounClause = do 
    nom <- String
    char ","
    gen <- String
    char ","
    declension <- String
    char ","
    gender <- String
    char ","
    sgtrans <- String
    char ","
    pltrans <- String
    return $ NounClause nom gen declension gender sgtrans pltrans

ただし、これは機能していないようです。これはなぜですか?

また、このパーサーを各行に適用するにはどうすればよいですか? 解析されたデータを取得して文字列を返す関数もここにあります。

c = ","
convert :: NounClause -> String
convert NounClause = "noun(" ++ nom ++ c ++ gen ++ c ++ declension ++ c ++ gender ++ "trans(" ++ sgtrans ++ c ++ pltrans ++ "))."

このプロジェクトで私を助けてくれた人にとても感謝しています。彼らの貢献は私にとって最も価値があります。

4

1 に答える 1

2

String パーサーを使用すると、できるだけ多くの入力を消費しようとします。これには、ファイル内のコンマが含まれます。したがって、コンマを除くすべてを読み取るパーサーを作成します。

import qualified Data.Attoparsec.Text as P
import Data.Text(unpack)

entry = fmap unpack (P.takeWhile (/=','))

unpack は、型の解析された情報をText文字列に変換するために使用されます。

次に、コンマを読み取る追加のパーサーが必要です。

separator = P.char ','

次に、これを組み合わせて解析しますNounClause

parseNounClause :: P.Parser NounClause
parseNounClause = do 
    nom <- entry
    separator -- don't need the comma so no need to keep it.
    gen <- entry
    separator
    declension <- entry
    separator
    gender <- entry 
    separator
    sgtrans <- entry
    separator
    pltrans <- entry
    separator
    return $ NounClause nom gen declension gender sgtrans pltrans

したがって、複数行を読みたいとします。これはコンマと同じですが、改行記号が追加されています。エントリと改行記号を交互に解析します。n 行を補正するために、n-1 個の改行記号のみを補正するために、最初の行を区別します。コンビネータを使用すると、同じ形式のmany'0 行以上の行を解析できます。

multiLines = do x <- parseNounClause
                xs <- many' (do P.endOfLine
                                clause <- parseNounClause
                                return clause
                           )
                return (x:xs)

したがって、これを解析する必要があります。これは、次のメイン関数によって行われます。Fileinfoをタイプとして読み取るために、別のインポートが必要ですText

import qualified Data.Text.IO as T(readFile)

main :: IO ()
main = do fileContents <- T.readFile "input.txt"
          let result = P.parseOnly multiLines fileContents
          case result of (Left s)   -> putStrLn s
                         (Right rs) -> sequence_ (map (putStrLn . show) rs)

解析結果は、エラー メッセージまたはNounClauseリスト内のすべての s のいずれかを取得します。sequence_ (map (putStrLn .show)印刷して使っています。

独自の表現を使用する場合は、定義の最後にStringを追加したため、データ型を a に変換できる関数 show があり、次のように (関数ではなく) 自分で型クラスをインスタンス化します。deriving ShowStringconvert

instance Show NounClause where
    show n = ...
于 2013-10-06T13:43:21.790 に答える