作为一项学习练习,我正在使用parsec在测试文件中查找值。我通常会在这种特殊情况下使用regexp,但是想看看parsec是否也有意义。不幸的是,我遇到了一些问题。
数据文件由重复的部分组成,其外观类似于以下内容。 'SHEF'是六个值之一,并且在页面之间有所变化,我想在构建数据类型时使用它。
Part A SHEF Nov/14/2011 (10:52)
-------------------
Portfolio Valuation
-------------------
FOREIGN COMMON STOCK 6,087,152.65
FOREIGN COMMON STOCK - USA 7,803,858.84
RIGHTS 0.00
我正在构建每个资产类别中金额的数据类型:
type Sector = String
type Amount = Double
type FundCode = String
data SectorAmount = SectorAmount (Sector,Amount) deriving (Show, Eq)
data FundSectors = FundSectors {
fund :: FundCode
, sectorAmounts :: [SectorAmount]
} deriving (Show, Eq)
我的代码成功编译,如下所示。它解析文件并正确检索每个资产类中的值,但我永远无法在fundValue解析器中正确设置状态。我已经使用输入字符串测试了fundValue解析器并且它成功解析了它,但由于某种原因,行函数没有像我想象的那样工作。我希望它在文件中查找以“Part A”开头的行,找到代码并将其存储在状态中,以便以后在标记解析器成功解析一行时使用。
使用fail
会导致问题吗?
allocationParser :: String -> Either ParseError [FundSectors]
allocationParser input = do
runParser allocationFile "" "" input
allocationFile :: GenParser Char FundCode [FundSectors]
allocationFile = do
secAmt <- many line
return secAmt
line :: GenParser Char FundCode FundSectors
line = try (do fund <- try fundValue
eol
fail "")
<|> do result <- try tag
eol
f <- getState
return $ FundSectors {fund=f, sectorAmounts = [result]}
fundValue :: GenParser Char FundCode FundCode
fundValue = do manyTill anyChar . try $ lookAhead (string "Part A ")
string "Part A "
fCode <- try fundCode
setState fCode
v <- many (noneOf "\n\r")
eol
return fCode
fundCode :: GenParser Char FundCode String
fundCode = try (string "SHSF")
<|> try (string "SHIF")
<|> try (string "SHFF")
<|> try (string "SHEF")
<|> try (string "SHGE")
<|> try (string "SHSE")
<|> fail "Couldn't match fundCode"
tag :: GenParser Char FundCode SectorAmount
tag = do manyTill anyChar . try $ lookAhead tagName
name <- tagName
v <- many (noneOf "\n\r")
let value = read ([x | x <- v, x /= ',']) :: Double -- remove commas from currency
return $ SectorAmount (name,value)
eol :: GenParser Char FundCode String
eol = try (string "\n\r")
<|> try (string "\r\n")
<|> string "\n"
<|> string "\r"
<|> fail "Couldn't find EOL"
提前致谢。
答案 0 :(得分:1)
是的,“try fundValue”块中的失败撤消了setState。 您需要稍微重新设计解析器,但您似乎很接近。