-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path49parsec.hs
64 lines (51 loc) · 1.86 KB
/
49parsec.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import Text.ParserCombinators.Parsec
import Control.Monad
-- from http://book.realworldhaskell.org/read/using-parsec.html
import Text.ParserCombinators.Parsec
{- A CSV file contains 0 or more lines, each of which is terminated
by the end-of-line character (eol). -}
csvFile :: GenParser Char st [[String]]
csvFile =
do result <- many line
eof
return result
-- Each line contains 1 or more cells, separated by a comma
line :: GenParser Char st [String]
line =
do result <- cells
eol -- end of line
return result
-- Build up a list of cells. Try to parse the first cell, then figure out
-- what ends the cell.
cells :: GenParser Char st [String]
cells =
do first <- cellContent
next <- remainingCells
return (first : next)
-- The cell either ends with a comma, indicating that 1 or more cells follow,
-- or it doesn't, indicating that we're at the end of the cells for this line
remainingCells :: GenParser Char st [String]
remainingCells =
(char ',' >> cells) -- Found comma? More cells coming
<|> (return []) -- No comma? Return [], no more cells
-- Each cell contains 0 or more characters, which must not be a comma or
-- EOL
cellContent :: GenParser Char st String
cellContent =
many (noneOf ",\n")
-- The end of line character is \n
eol :: GenParser Char st Char
eol = char '\n'
parseCSV :: String -> Either ParseError [[String]]
parseCSV input = parse csvFile "(unknown)" input
-- quite beautiful
{-
Example usage,
*Main Control.Monad Text.ParserCombinators.Parsec> parseCSV "aditya,is,bad\n"
Right [["aditya","is","bad"]]
*Main Control.Monad Text.ParserCombinators.Parsec>
*Main Control.Monad Text.ParserCombinators.Parsec> parseCSV "\n"
Right [[""]]
*Main Control.Monad Text.ParserCombinators.Parsec> parseCSV ",,,,\n"
Right [["","","","",""]]
-}