--Cookbook.Project.Scribe
module Cookbook.Project.Scribe.Scribe(
Frame(..),Column,Row,Table,Database,
isRow,isColumn,isFrame,isTable,
makeName,
parseFrame,parseColumn,parseRow,parseTable,
readColumn,readRow,readTable,readDatabase,
getTable,getRow,getColumn,getFrame,
qGetRow,qGetColumn,qGetFrame) where
import qualified Cookbook.Essential.Common as Cm
import qualified Cookbook.Essential.Continuous as Ct
import qualified Cookbook.Ingredients.Lists.Modify as Md
import qualified Cookbook.Ingredients.Lists.Access as Ac
import qualified Cookbook.Ingredients.Tupples.Look as Lk
import qualified Cookbook.Ingredients.Functional.Break as Br
import qualified Cookbook.Recipes.Sanitize as St
--Data
data Frame = Frame {keyval :: String, entry :: String} | Promise {keyval :: String, link :: String} deriving (Eq,Show)
type Column = (String,[Frame])
type Row = (String,[Column])
type Table = (String,[Row])
type Database = [Table]
isRow x = and [x `Ac.contains` "row", length x > 4]
isColumn x = and [x `Ac.contains` "column", length x > 4]
isFrame x = and $ map ((flip elem) x) "<>"
isTable x = and [x `Ac.contains` "table",length x > 4]
makeName :: String -> String -> String
makeName a b = St.blacklist (Ct.after a b) "{ "
--Parsing
parseFrame :: String -> Frame
parseFrame x | not $ isFrame x = error (x ++ " was passed to parseFrame, but does not conform to standard.")
parseFrame x
| ('-','-') `Ac.surrounds` inner = Promise {keyval = Md.between inner ('-','-'), link = Ct.after x '>'}
| otherwise = Frame {keyval = inner, entry = Ct.after x '>'}
where inner = Md.between x ('<','>')
parseColumn :: (String,[String]) -> Column
parseColumn (a,b) = (makeName a "column ",map parseFrame b)
parseRow :: (String,[(String,[String])]) -> Row
parseRow (a,b) = (makeName a "row ",map parseColumn b)
parseTable :: (String,[(String,[(String,[String])])]) -> Table
parseTable (a,b) = (makeName a "table ",map parseRow b)
--Reading
readColumn :: [String] -> (String,[String])
readColumn [] = error "Column either does not exist or does not conform to standards."
readColumn (x:xs) | not $ isColumn x = readColumn xs
readColumn (x:xs) = (x,Md.linesBetween (x:xs) ("{","}"))
readRow :: [String] -> (String,[(String,[String])])
readRow [] = error "Row either does not exist or does not conform to standards."
readRow (x:xs) | not $ isRow x = readRow xs
readRow (x:xs) = (x, map readColumn splitup)
where splitup = Br.splitBool (\c -> not $ c `Ac.contains` "}") rowScope
rowScope = Md.linesBetween (x:xs) ("{","}}")
readTable :: [String] -> (String,[(String,[(String,[String])])])
readTable [] = error "Table either does not exist or does not conform to standards."
readTable (x:xs) | not $ isTable x = readTable xs
readTable (x:xs) = (x,map readRow splitup)
where splitup = Br.splitBool (\c -> not $ c `Ac.contains` "}}") tableScope;
tableScope = Md.linesBetween (x:xs) ("{","}}}")
readDatabase :: [String] -> Database
readDatabase (x:xs)
| isTable x = parseTable (readTable (x:xs)) : readDatabase (Ct.after xs "}}}")
| otherwise = readDatabase xs
--Accessors
getTable :: String -> Database -> Table
getTable a b = (a,(head $ Lk.lookList b a))
getRow :: (String,String) -> Database -> Row
getRow (a,b) c = (b,head $ Lk.lookList (snd (getTable a c)) b)
getColumn :: (String,String,String) -> Database -> Column
getColumn (a,b,c) d = (c,head $ Lk.lookList (snd (getRow (a,b) d)) c)
getFrame :: (String,String,String,String) -> Database -> Frame
getFrame (a,b,c,d) e = let frames = (snd $ getColumn (a,b,c) e) in head $ Lk.lookList (zip (map keyval frames) frames) d
qGetRow :: String -> Database -> Row
qGetRow x z= getRow (a,b) z
where (a,b) = let (f:g:[]) = Md.splitOn x '.' in (f,g)
qGetColumn :: String -> Database -> Column
qGetColumn x z = getColumn (a,b,c) z
where (a,b,c) = let (f:g:h:[]) = Md.splitOn x '.' in (f,g,h)
qGetFrame :: String -> Database -> Frame
qGetFrame x z = getFrame (a,b,c,d) z
where (a,b,c,d) = let (f:g:h:j:[]) = Md.splitOn x '.' in (f,g,h,j)