Guest User

Untitled

a guest
Nov 18th, 2018
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.84 KB | None | 0 0
  1. module CSV
  2. ( CSV
  3. , Record
  4. , Field
  5. , csv
  6. , parseCSV
  7. , parseCSVFromFile
  8. , parseCSVTest
  9. , printCSV
  10. )
  11. where
  12.  
  13. import Text.Parsec
  14. import Text.Parsec.String
  15. import Text.Parsec.Error ( ParseError )
  16. import Data.List ( intersperse )
  17.  
  18. -- | A CSV file is a series of records. According to the RFC, the
  19. -- records all have to have the same length. As an extension, I
  20. -- allow variable length records.
  21. type CSV = [Record]
  22.  
  23. -- | A record is a series of fields
  24. type Record = [Field]
  25.  
  26. -- | A field is a string
  27. type Field = String
  28.  
  29. -- | A Parsec parser for parsing CSV files
  30. csv :: Parser CSV
  31. csv = do
  32. x <- record `sepEndBy` many1 (oneOf "\n\r")
  33. eof
  34. return x
  35.  
  36. record :: Parser Record
  37. record = (quotedField <|> field) `sepBy` char ','
  38.  
  39. field :: Parser Field
  40. field = many (noneOf ",\n\r\"")
  41.  
  42. quotedField :: Parser Field
  43. quotedField = between (char '"') (char '"')
  44. $ many (noneOf "\"" <|> try (string "\"\"" >> return '"'))
  45.  
  46. -- | Given a file name (used only for error messages) and a string to
  47. -- parse, run the parser.
  48. parseCSV :: FilePath -> String -> Either ParseError CSV
  49. parseCSV = parse csv
  50.  
  51. -- | Given a file name, read from that file and run the parser
  52. parseCSVFromFile :: FilePath -> IO (Either ParseError CSV)
  53. parseCSVFromFile = parseFromFile csv
  54.  
  55. -- | Given a string, run the parser, and print the result on stdout.
  56. parseCSVTest :: String -> IO ()
  57. parseCSVTest = parseTest csv
  58.  
  59. -- | Given an object of type CSV, generate a CSV formatted
  60. -- string. Always uses escaped fields.
  61. printCSV :: CSV -> String
  62. printCSV records = unlines (printRecord `map` records)
  63. where
  64. printRecord = concat . intersperse "," . map printField
  65. printField f = "\"" ++ concatMap escape f ++ "\""
  66. escape '"' = "\"\""
  67. escape x = [x]
  68. unlines = concat . intersperse "\n"
Add Comment
Please, Sign In to add comment