diff --git a/a-deeper-dive-into-relational-algebra-by-way-of-adjunctions.cabal b/a-deeper-dive-into-relational-algebra-by-way-of-adjunctions.cabal index 22c0673..89d5f23 100644 --- a/a-deeper-dive-into-relational-algebra-by-way-of-adjunctions.cabal +++ b/a-deeper-dive-into-relational-algebra-by-way-of-adjunctions.cabal @@ -27,7 +27,9 @@ library Data.PointedSet, Data.Key, Database.Bag, - Database.IndexedTable + Database.IndexedTable, + Text.Parser.Customers, + Text.Parser.Invoices -- Modules included in this library but not exported. other-modules: @@ -39,7 +41,8 @@ library FlexibleInstances build-depends: base >=4.16.4.0, - array >= 0.5.4.0 + array >= 0.5.4.0, + parsec >= 0.3.1.15 hs-source-dirs: src default-language: Haskell2010 @@ -70,10 +73,13 @@ test-suite spec Data.PointedSetSpec, Data.KeySpec, Database.BagSpec, - Database.IndexedTableSpec + Database.IndexedTableSpec, + Text.Parser.CustomersSpec, + Text.Parser.InvoicesSpec build-depends: base >=4.16.4.0, hspec ^>=2.10, a-deeper-dive-into-relational-algebra-by-way-of-adjunctions, - array >= 0.5.4.0 + array >= 0.5.4.0, + parsec >= 0.3.1.15 build-tool-depends: hspec-discover:hspec-discover == 2.* diff --git a/src/Text/Parser/Customers.hs b/src/Text/Parser/Customers.hs new file mode 100644 index 0000000..b053460 --- /dev/null +++ b/src/Text/Parser/Customers.hs @@ -0,0 +1,39 @@ +module Text.Parser.Customers where + +import Text.ParserCombinators.Parsec +import Data.Bag + +type Identifier = Int +type Name = String +data Customer = C { cid :: Identifier, name :: Name } deriving (Show, Eq) + +csvFile :: GenParser Char st (Bag Customer) +csvFile = do + result <- many record + eof + return (Bag result) + +record :: GenParser Char st Customer +record = do + id <- cidCell + separator + name <- nameCell + eol + return (C id name) + +cidCell :: GenParser Char st Identifier +cidCell = do + id <- many digit + return (read id) + +nameCell :: GenParser Char st Name +nameCell = many (noneOf ",\n") + +separator :: GenParser Char st Char +separator = char ',' + +eol :: GenParser Char st Char +eol = char '\n' + +parseCSV :: String -> Either ParseError (Bag Customer) +parseCSV input = parse csvFile "(unknown)" input diff --git a/src/Text/Parser/Invoices.hs b/src/Text/Parser/Invoices.hs new file mode 100644 index 0000000..4c6d061 --- /dev/null +++ b/src/Text/Parser/Invoices.hs @@ -0,0 +1,56 @@ +module Text.Parser.Invoices where + +import Text.ParserCombinators.Parsec +import Data.Bag + +type Identifier = Int +type Date = Int +type Amount = Int + +data Invoice = I + { iid :: Identifier + , cust :: Identifier + , due :: Date + , amount :: Amount} deriving (Show, Eq) + +csvFile :: GenParser Char st (Bag Invoice) +csvFile = do + result <- many invoiceRecord + eof + return (Bag result) + +invoiceRecord :: GenParser Char st Invoice +invoiceRecord = do + iidCell <- identifier + separator + custIdCell <- identifier + separator + dueCell <- date + separator + amountCell <- price + eol + return (I iidCell custIdCell dueCell amountCell) + +identifier :: GenParser Char st Identifier +identifier = do + id <- many digit + return (read id) + +price :: GenParser Char st Amount +price = do + id <- many digit + return (read id) + +date :: GenParser Char st Date +date = do + id <- many digit + return (read id) + +separator :: GenParser Char st Char +separator = char ',' + +eol :: GenParser Char st Char +eol = char '\n' + +parseCSV :: String -> Either ParseError (Bag Invoice) +parseCSV input = parse csvFile "(unknown)" input diff --git a/test/Text/Parser/CustomersSpec.hs b/test/Text/Parser/CustomersSpec.hs new file mode 100644 index 0000000..2f6daa8 --- /dev/null +++ b/test/Text/Parser/CustomersSpec.hs @@ -0,0 +1,16 @@ +module Text.Parser.CustomersSpec where + +import Test.Hspec +import Text.Parser.Customers +import Data.Bag as Bag +import Text.ParserCombinators.Parsec +import Data.Either + +expectedOutput = Bag [C 1 "John", C 2 "Kayla"] + +spec :: Spec +spec = do + describe "parseCSV" $ do + it "can correctly parse the example" $ do + testFile <- readFile "test/Text/Parser/customertest.csv" + fromRight Bag.empty (parseCSV testFile) `shouldBe` expectedOutput diff --git a/test/Text/Parser/InvoicesSpec.hs b/test/Text/Parser/InvoicesSpec.hs new file mode 100644 index 0000000..77177de --- /dev/null +++ b/test/Text/Parser/InvoicesSpec.hs @@ -0,0 +1,16 @@ +module Text.Parser.InvoicesSpec where + +import Test.Hspec +import Text.Parser.Invoices +import Data.Bag as Bag +import Text.ParserCombinators.Parsec +import Data.Either + +expectedOutput = Bag [I 10 1 20160101 10, I 11 1 20160102 83, I 12 2 20160103 15] + +spec :: Spec +spec = do + describe "parseCSV" $ do + it "can correctly parse the example" $ do + testFile <- readFile "test/Text/Parser/invoicestest.csv" + fromRight Bag.empty (parseCSV testFile) `shouldBe` expectedOutput diff --git a/test/Text/Parser/customertest.csv b/test/Text/Parser/customertest.csv new file mode 100644 index 0000000..047afb3 --- /dev/null +++ b/test/Text/Parser/customertest.csv @@ -0,0 +1,2 @@ +1,John +2,Kayla diff --git a/test/Text/Parser/invoicestest.csv b/test/Text/Parser/invoicestest.csv new file mode 100644 index 0000000..45e3d57 --- /dev/null +++ b/test/Text/Parser/invoicestest.csv @@ -0,0 +1,3 @@ +10,1,20160101,10 +11,1,20160102,83 +12,2,20160103,15