module Data.DescriLo(loadDescriptionFile, loadDescriptionString, checkAttribute, Description(Description, name, values)) where
import System.IO
data Description =
Description {
name :: String,
values :: [(String,String)]
}
instance Show Description where
show Description {name=n, values=vs} =
"[" ++ n ++ "]\n" ++ foldl (++) "" (map (\(x,y) -> "\t" ++ x ++ " = " ++ y ++ "\n") vs)
data Element a = Variable a a | Definition a | Nil deriving Show
trimL (' ':r) = trimL r
trimL ('\t':r) = trimL r
trimL str = str
trimR [] = []
trimR (' ':[]) = []
trimR ('\t':[]) = []
trimR (h:r) =
let trimmed = trimR r in
case trimmed of
[] -> [h]
' ':[] -> [h]
'\t':[] -> [h]
a -> h:a
trim s = trimR $ trimL s
loadDescriptionFile fname defName = do
fl <- readFile fname
return $ loadDescriptionString fl defName
loadDescriptionString string defaultName =
let lns = lines string in
loadDescriptions lns Description{name = defaultName, values = []}
loadDescriptions lns cat = loadDescriptions' lns cat False
loadDescriptions' [] cat hasVars = if hasVars then [cat] else []
loadDescriptions' (h:rest) cat hasVars =
let ln = loadLine h in
case ln of
Variable left right ->
let loaded = loadDescriptions' rest cat True in
case loaded of
[] -> [cat{values = [(left,right)]}]
(rcat:rrest) -> rcat{values = (left,right):values rcat}:rrest
Definition newName -> (if hasVars then (cat :) else id) $ loadDescriptions' rest Description{name = newName, values = []} False
Nil -> loadDescriptions' rest cat hasVars
loadLine ln =
case ln of
' ':rest -> loadLine rest
'\t':rest -> loadLine rest
'#':_ -> Nil
'\n':_ -> Nil
'[':rest -> Definition $ loadDescription rest
_ -> loadVariable ln
loadDescription ln =
case ln of
[] -> ""
']':[] -> ""
h:rest -> h:loadDescription rest
loadVariable ln =
let (left,right) = loadVariableLeft ln in
case (trim left, trim right) of
([],_) -> Nil
(_,[]) -> Nil
(a,b) -> Variable a b
loadVariableLeft [] = ([],[])
loadVariableLeft (h:rest) =
let (left,right) = loadVariableLeft rest in
case h of
'=' -> ([], rest)
_ -> (h:left,loadVariableRight right)
loadVariableRight [] = []
loadVariableRight ('#':r) = []
loadVariableRight (h:r) = h:loadVariableRight r
checkAttribute lval compareF Description{values = (h:r)} = checkAttribute' lval compareF (h:r)
checkAttribute' _ _ [] = False
checkAttribute' lval compareF ((l,r):rest) =
if l == lval then compareF r else checkAttribute' lval compareF rest