3

学習演習として、parsecを使用してテストファイル内の値を検索しています。私は通常、この特定のケースに正規表現を使用しますが、parsecも意味があるかどうかを確認したいと思います。残念ながら、私はいくつかの問題に直面しています。

データファイルは、次のような繰り返しセクションで構成されています。「SHEF」は6つの値の1つであり、ページごとに変化します。データ型の作成に使用したいと思います。

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パーサーをテストしましたが、正常に解析されましたが、何らかの理由で、ライン関数が思ったとおりに機能していません。「パート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"

前もって感謝します。

4

1 に答える 1

1

はい、「tryfundValue」ブロックで失敗するとsetStateが元に戻されます。パーサーを少し再設計する必要がありますが、近いようです。

于 2011-11-30T22:39:14.727 に答える