| 1 | 1 |
module Main where
|
| 2 | 2 |
|
| 3 |
import Control.Monad (when)
|
| 3 | 4 |
import Data.Char (isSpace, isAlphaNum)
|
| 5 |
import Data.Monoid ((<>))
|
| 4 | 6 |
import Data.Text (Text)
|
| 5 | 7 |
import qualified Data.Text as T
|
| 6 | 8 |
import qualified Data.Text.IO as T
|
|
| 11 | 13 |
} deriving (Eq, Show)
|
| 12 | 14 |
|
| 13 | 15 |
data Field = Field
|
| 14 | |
{ fName :: Text
|
| 15 | |
, fType :: Text
|
| 16 | |
, fNull :: Bool
|
| 16 |
{ fName :: Text
|
| 17 |
, fType :: Text
|
| 18 |
, fNull :: Bool
|
| 19 |
, fUniq :: Bool
|
| 20 |
, fDefault :: Maybe Text
|
| 17 | 21 |
} deriving (Eq, Show)
|
| 18 | 22 |
|
| 19 | 23 |
uncomment :: Text -> Text
|
|
| 22 | 26 |
isValid :: Text -> Bool
|
| 23 | 27 |
isValid = T.all (\ x -> isAlphaNum x || x == '_')
|
| 24 | 28 |
|
| 29 |
isSpecial :: Char -> Bool
|
| 30 |
isSpecial c = c == '?' || c == '!'
|
| 31 |
|
| 32 |
parseField :: Text -> Field
|
| 33 |
parseField ln =
|
| 34 |
let (name, tt) = T.break (== ':') (T.strip ln)
|
| 35 |
(typ, def) = T.break (== '=') (T.strip tt)
|
| 36 |
in Field
|
| 37 |
{ fName = T.strip name
|
| 38 |
, fType = T.strip (T.drop 1 (T.filter (not . isSpecial) typ))
|
| 39 |
, fNull = T.any (== '?') typ
|
| 40 |
, fUniq = T.any (== '!') typ
|
| 41 |
, fDefault =
|
| 42 |
case def of
|
| 43 |
"" -> Nothing
|
| 44 |
rs -> Just (T.strip (T.drop 1 rs))
|
| 45 |
}
|
| 46 |
|
| 25 | 47 |
parse :: Text -> Either String [Decl]
|
| 26 | 48 |
parse = go [] . map uncomment . T.lines
|
| 27 | 49 |
where go ds [] = return ds
|
| 28 | 50 |
go ds (l:ls)
|
| 29 | 51 |
| T.length (T.takeWhile isSpace l) > 0 =
|
| 30 | |
let (n, t) = T.break (== ':') (T.strip l)
|
| 31 | |
f = Field { fName = T.strip n
|
| 32 | |
, fType = T.strip (T.drop 1 (T.filter (/= '?') t))
|
| 33 | |
, fNull = T.any (== '?') t
|
| 34 | |
}
|
| 52 |
let f = parseField l
|
| 35 | 53 |
in case ds of
|
| 36 | 54 |
(d:ds') -> go (d { dFields = f : dFields d } : ds') ls
|
| 37 | 55 |
[] -> Left "indented line outside of table decl"
|
|
| 80 | 98 |
where printField Field { fName = f
|
| 81 | 99 |
, fType = t
|
| 82 | 100 |
, fNull = l
|
| 101 |
, fUniq = u
|
| 102 |
, fDefault = d
|
| 83 | 103 |
} = do
|
| 84 | 104 |
T.putStr " , "
|
| 85 | 105 |
T.putStr f
|
| 86 | 106 |
T.putStr " "
|
| 87 | 107 |
T.putStr (typeName t)
|
| 88 | |
if not l
|
| 89 | |
then T.putStrLn " NOT NULL"
|
| 90 | |
else T.putStrLn ""
|
| 108 |
when (not l) $
|
| 109 |
T.putStr " NOT NULL"
|
| 110 |
when u $
|
| 111 |
T.putStr " UNIQUE"
|
| 112 |
case d of
|
| 113 |
Nothing -> return ()
|
| 114 |
Just dv -> T.putStr (" DEFAULT " <> dv)
|
| 115 |
T.putStrLn ""
|
| 91 | 116 |
printForeign Field { fName = f, fType = t }
|
| 92 | 117 |
| t `elem` builtins = return ()
|
| 93 | 118 |
| otherwise = do
|
|
| 105 | 130 |
cs <- T.getContents
|
| 106 | 131 |
case parse cs of
|
| 107 | 132 |
Left err -> putStrLn err
|
| 108 | |
Right ds -> case check ds of
|
| 109 | |
Left err -> putStrLn err
|
| 110 | |
Right () -> mapM_ pprint (rev ds)
|
| 133 |
Right ds -> do
|
| 134 |
case check ds of
|
| 135 |
Left err -> putStrLn err
|
| 136 |
Right () -> mapM_ pprint (rev ds)
|