{- | Emping 0.6 (provisional) Module CsvParse converts a table in Open Office Calc .csv format into a list of lists of Haskell Strings.The first row in the table must consist of the attribute names. It is recommended that all attributes have unique names, but blanks and doubles are allowed. Each attribute will be identified by its column number. The rows after the first must be attribute values. Values in different columns may have the same names or be blank. Values in the same column with the same names are considered to be equal. Emping will generate a list of values for each column. Tue 19 May 2009 05:50:37 PM CEST -} module CsvParse ( getTable , blankId ) where import Text.ParserCombinators.Parsec {- | a text field starts with \" and ends with \" any other character is allowed a numerical field consists of digits only an empty field is zero or more spaces separated by comma's, returns \"NA\" -} -- | blankId is the String returned from parsing a blank field -- currently this is: \"NA\", which stands for 'not applicable' blankId :: String blankId = "NA" comma:: Parser Char comma = char ',' -- textField returns any String between double quotes (the OO Calc format) txtField :: Parser String txtField = do char '\"' txt <- many (noneOf "\"") char '\"' return txt -- numField returns a string of digits as a string -- this is the OO Calc format for numbers numField :: Parser String numField = many1 digit -- noField parses a blank field noField :: Parser String noField = do { many (char ' '); return blankId } -- getField parses a text field, a numeric field, or a blank field getField :: Parser String getField = do {txtField <|> numField <|> noField } -- csvLine parses a row csvLine :: Parser [String] csvLine = do fields <- (sepBy getField comma) newline return fields -- csvTable parses the table csvTable :: Parser [[String]] csvTable = many csvLine -- | getTable reads the table from a file path -- it returns a list of rows, where each row is a list of strings getTable :: String -> IO [[String]] getTable fname = do pares <- parseFromFile csvTable fname let res = case pares of Right x -> x Left err -> error ("parse error at: " ++ (show err)) return res ------------------------------------------------------------------------- -- test the table in csv format for parse errors {- test = do putStrLn "Enter CSV file:" name <- getLine res <- parseFromFile csvTable name case res of Left err -> error ("parse error at: " ++ (show err)) Right xs -> print xs -}