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

如果您使用字符串解析器,它会尝试消耗尽可能多的输入。这包括文件中的逗号。因此,您构建了一个解析器,它可以读取除逗号之外的所有内容。

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'允许我们解析零或多行相同格式的行。

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)用来打印它。

您有函数 show ,它可以将您的数据类型转换为 aString因为您deriving Show在定义的末尾添加了 如果您想使用自己的String表示形式自己实例化类型类(而不是您的convert函数),例如:

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