Haskell 使用parsec解析文件
我试图解析文件[1],但下面的代码无法正常工作Haskell 使用parsec解析文件,haskell,parsec,Haskell,Parsec,我试图解析文件[1],但下面的代码无法正常工作 import Control.Applicative hiding ( many , ( <|> ) ) import Text.Parsec import Text.Parsec.String (Parser) import qualified Text.Parsec.Token as T import Text.Parsec.Language (emptyDef) --Scheme Code;ISIN Div Payout/
import Control.Applicative hiding ( many , ( <|> ) )
import Text.Parsec
import Text.Parsec.String (Parser)
import qualified Text.Parsec.Token as T
import Text.Parsec.Language (emptyDef)
--Scheme Code;ISIN Div Payout/ ISIN Growth;ISIN Div Reinvestment;Scheme Name;Net Asset Value;Repurchase Price;Sale Price;Date
--120523;INF846K01ET8;INF846K01EU6;Axis Triple Advantage Fund - Direct Plan - Dividend Option;13.3660;13.2323;13.3660;19-Jun-2015
data MFund = MFund Integer String String String Double Double Double String deriving (Show) --String String String deriving (Show)
lexer :: T.TokenParser st
lexer = T.makeTokenParser emptyDef
natural :: Parser Integer
natural = T.natural lexer
float :: Parser Double
float = T.float lexer
eol :: Parser String
eol = try (string "\r\n")
<|> try (string "\n")
<|> try (string "\r")
parseFund :: Parsec String () MFund
parseFund = MFund <$> natural
<*> (char ';' *> (many1 alphaNum <|> string "-"))
<*> (char ';' *> (many1 alphaNum <|> string "-"))
<*> (char ';' *> manyTill anyChar (char ';'))
<*> float
<*> (char ';' *> float)
<*> (char ';' *> float)
<*> (char ';' *> many1 (alphaNum <|> char '-'))
parseBlockFund :: Parsec String () [MFund]
parseBlockFund = manyTill anyChar eol *> space *> eol *> endBy parseFund eol
parseMutual :: Parsec String () [MFund]
parseMutual = concat <$> (manyTill anyChar eol *> space *> eol *>
sepBy parseBlockFund (space *> eol))
{- each scheme is seperated by space and end of line-}
parseSchemeBlock :: Parsec String () [MFund]
parseSchemeBlock = concat <$> (sepBy parseMutual (space *> eol))
parseFile :: Parsec String () [MFund]
parseFile =
string "Scheme Code;ISIN Div Payout/ ISIN Growth;ISIN Div Reinvestment;Scheme Name;Net Asset Value;Repurchase Price;Sale Price;Date" *>
eol *> space *> eol *> parseSchemeBlock <* eof
main :: IO ()
main = do
input <- readFile "data.txt"
print input
case parse parseFile "" input of
Left err -> print err
Right val -> print val
导入控制。应用程序隐藏(许多,())
导入文本.Parsec
导入Text.Parsec.String(解析器)
将限定的Text.Parsec.Token作为T导入
导入Text.Parsec.Language(emptyDef)
--方案代码;ISIN部门支出/ISIN增长;ISIN部门再投资;方案名称;资产净值;回购价格;销售价格;日期
--120523;INF846K01ET8;INF846K01EU6;安讯士三重优势基金-直接计划-分红期权;13.3660;13.2323;13.3660;2015年6月19日
数据MFund=MFund整数字符串派生(显示)--字符串派生(显示)
lexer::T.TokenParser st
lexer=T.makeTokenParser emptyDef
自然::解析器整数
自然的,自然的
浮点::分析器双精度
float=T.float lexer
eol::解析器字符串
eol=try(字符串“\r\n”)
try(字符串“\n”)
try(字符串“\r”)
parseFund::Parsec String()MFund
parseFund=MFund natural
(字符“;”*>(多个字母数字字符串“-”)
(字符“;”*>(多个字母数字字符串“-”)
(char';'*>manyTill anyChar(char';'))
浮动
(字符“;”*>浮点)
(字符“;”*>浮点)
(字符“;”*>many1(alphaNum字符“-”)
parseBlockFund::Parsec字符串()[MFund]
parseBlockFund=manyTill anyChar eol*>space*>eol*>endBy parseFund eol
parseMutual::Parsec字符串()[MFund]
parseMutual=concat(manyTill anyChar eol*>space*>eol*>
Sebby parseBlockFund(空间*>eol))
{-每个方案由空格和行尾分隔-}
parseSchemeBlock::Parsec字符串()[MFund]
parseSchemeBlock=concat(sebby parseMutual(空格*>eol))
parseFile::Parsec字符串()[MFund]
解析文件=
字符串“方案代码;ISIN Div支出/ISIN增长;ISIN Div再投资;方案名称;资产净值;回购价格;销售价格;日期”*>
eol*>space*>eol*>parseSchemeBlock打印值
我开始从parseFile函数解析文件,该函数使用第一行、行尾、空格和行尾。现在,我解析每个由空格和行尾分隔的scheme块。在每个scheme块中,我们有许多共同块,它们也由空格和行尾分隔,因此我首先使用字符串,直到行尾,然后是空格和行尾,然后调用parseBlockFund
我怀疑的问题是,当我调用parseMutual函数时,当它到达scheme块的末尾时,它会占用parseSchemeBlock函数应该占用的空间和行尾。我尝试了try函数,但它不起作用,所以我不确定我的想法是否正确。谁能告诉我这个密码有什么问题吗
当我删除eof时,一件有趣的事情是,这段代码能够解析至少一个scheme块[2]
[1]
[2] 很难跟踪应该在何处使用空白,因为代码在许多地方都分散在
空间和eol
中。使用这样一种简单的基于行的格式,您确实希望一次处理整行。我会尝试编写一个line::Parser a->Parser a
combinator,它解析a
,然后热切地咀嚼空格和换行符。(但要小心,a
本身不会使用换行符。)