jord-1.0.0.0: gen/Models.hs
module Models
( Model(..)
, parser
, generator
) where
import Control.Applicative ((<|>))
import Data.List (intercalate)
import Text.ParserCombinators.ReadP (ReadP, choice, skipSpaces, string)
import qualified Generator as G
import qualified Parsers as P
data Model =
Model
{ mtype :: ModelType
, mid :: String
, comment :: [String]
, surface :: String
, longitudeRange :: String
, epoch :: Maybe Double
}
data ModelType
= Spherical
| Ellipsoidal
deriving (Eq)
parser :: ReadP Model
parser = do
c <- P.comment
t <- type'
skipSpaces
n <- P.name
P.eol
s <- surface'
P.eol
lr <- longitudeRange'
ep <- maybeEpoch t
P.eol
return (Model t n c s lr ep)
type' :: ReadP ModelType
type' = do
s <- string "spherical " <|> string "ellipsoidal "
case s of
"spherical " -> return Spherical
"ellipsoidal " -> return Ellipsoidal
_ -> error "unsupported model type"
surface' :: ReadP String
surface' = do
skipSpaces
_ <- string "surface: "
P.name
longitudeRange' :: ReadP String
longitudeRange' = do
skipSpaces
_ <- string "longitudeRange: "
choice [string "L180", string "L360"]
maybeEpoch :: ModelType -> ReadP (Maybe Double)
maybeEpoch Spherical = return Nothing
maybeEpoch _ = P.epoch
generator :: String -> G.Generator Model
generator ellipsoids =
G.Generator [ellipsoids, "Data.Geo.Jord.Ellipsoid", "Data.Geo.Jord.Model"] genModel (const "")
genModel :: Model -> String
genModel m = unlines' ([d, model, eq, show'] ++ instanceType m)
where
d = G.documentation (comment m) ++ "data " ++ mid m ++ " = " ++ "\n" ++ " " ++ mid m
model = instanceModel m
eq = instanceEq m
show' = instanceShow m
instanceModel :: Model -> String
instanceModel m =
"instance Model " ++
mid m ++
" where\n" ++
" modelId _ = ModelId \"" ++
mid m ++
"\"\n" ++ " surface _ = " ++ s ++ "\n" ++ " longitudeRange _ = " ++ longitudeRange m
where
s =
if mtype m == Spherical
then "toSphere e" ++ surface m
else "e" ++ surface m
instanceEq :: Model -> String
instanceEq m = "instance Eq " ++ mid m ++ " where\n _ == _ = True"
instanceShow :: Model -> String
instanceShow m = "instance Show " ++ mid m ++ " where\n show m = show (modelId m)"
instanceType :: Model -> [String]
instanceType m
| mtype m == Spherical = instanceSpherical n
| mtype m == Ellipsoidal = instanceEllipsoidal n (epoch m)
| otherwise = error "unsupported type"
where
n = mid m
instanceSpherical :: String -> [String]
instanceSpherical n = ["instance Spherical " ++ n]
instanceEllipsoidal :: String -> Maybe Double -> [String]
instanceEllipsoidal n Nothing = ["instance Ellipsoidal " ++ n]
instanceEllipsoidal n (Just yd) =
[ "instance Ellipsoidal " ++ n
, "instance EllipsoidalT0 " ++ n ++ " where\n" ++ " epoch _ = Epoch " ++ show yd
]
unlines' :: [String] -> String
unlines' = intercalate "\n\n"