9 | import Data.SortedMap
13 | import Language.TOML.Lexer
14 | import Language.TOML.Parser
15 | import public Language.TOML.Value
16 | import Language.TOML.ConcreteSyntax as C
21 | data SectionIdent = SGlobal
25 | toPair : Item -> Maybe (CKey,CValue)
26 | toPair (IKeyValue key val) = Just (key,val)
27 | toPair (ITableHeader _) = Nothing
28 | toPair (ITableArray _) = Nothing
30 | takeWhileJust : (a -> Maybe b) -> List a -> (List b, List a)
31 | takeWhileJust f [] = ([],[])
32 | takeWhileJust f (x :: xs) = case f x of
33 | Nothing => ([],x :: xs)
34 | Just vb => let (bs,as) = takeWhileJust f xs in (vb :: bs, as)
38 | sections : List C.Item -> List (SectionIdent, List (CKey, CValue))
39 | sections xs = loop SGlobal xs
41 | loop : SectionIdent -> List C.Item -> List (SectionIdent, List (CKey, CValue))
43 | loop sec ((ITableHeader header) :: xs) = loop (STable header) xs
44 | loop sec ((ITableArray header) :: xs) = loop (STableArray header) xs
46 | let (kvs, rest) = takeWhileJust toPair xs
47 | in (sec, kvs) :: loop sec rest
51 | data Error = ErrDottedIsNotATable Key Value
53 | | ParseError (List String)
59 | show (ErrDottedIsNotATable x y) = "Dotted key part `" ++ show x ++ "`is not a table"
60 | show LexerError = "Lexer error"
61 | show (ParseError x) = "Parse error: " ++ show x
62 | show Unimplemented = "Unimplemented feature"
65 | keyAtomStr : CKeyAtom -> Key
66 | keyAtomStr (CKBare x) = x
67 | keyAtomStr (CKQuoted x) = x
70 | keyParts : CKey -> List1 Key
71 | keyParts (CKAtom x) = keyAtomStr x ::: []
72 | keyParts (CKDotted x) = map keyAtomStr x
76 | x == y = keyAtomStr x == keyAtomStr y
80 | x == y = keyParts x == keyParts y
83 | tableSetWithParts : (t : Table) -> (path : List1 Key) -> (val : Value) -> Either Error Table
84 | tableSetWithParts t (head ::: []) val = pure $
insert head val t
85 | tableSetWithParts t (head ::: (x :: xs)) val = do
86 | inner <- case lookup head t of
87 | Nothing => pure empty
88 | Just (VTable t) => pure t
89 | Just v => Left $
ErrDottedIsNotATable head v
91 | inner' <- tableSetWithParts inner (x ::: xs) val
92 | pure $
insert head (VTable inner') t
98 | cvalToVal : CValue -> Either Error Value
99 | cvalToVal (CVString x) = pure $
VString x
100 | cvalToVal (CVInteger x) = pure $
VInteger x
101 | cvalToVal (CVFloat x) = pure $
VFloat x
102 | cvalToVal (CVBoolean x) = pure $
VBoolean x
103 | cvalToVal (CVArray xs) = map VArray $
for xs cvalToVal
104 | cvalToVal (CVInlineTable xs) = map VTable $
tableFromKVs xs
107 | tableFromKVs : List (CKey, CValue) -> Either Error Table
108 | tableFromKVs xs = loop empty xs
110 | loop : Table -> List (CKey, CValue) -> Either Error Table
111 | loop t [] = Right t
112 | loop t ((k, v) :: xs) = do
114 | let parts = keyParts k
115 | t' <- tableSetWithParts t parts v'
119 | extendFile : (file : Table) -> (sects : List (SectionIdent, List (CKey, CValue))) -> Either Error Table
120 | extendFile file [] = pure file
121 | extendFile file ((SGlobal, kvs) :: rest) = do
122 | tab <- tableFromKVs kvs
123 | extendFile (mergeLeft tab file) rest
124 | extendFile file (((STable key), kvs) :: rest) = do
125 | tab <- tableFromKVs kvs
126 | let kParts = keyParts key
127 | file' <- tableSetWithParts file kParts (VTable tab)
128 | extendFile file' rest
130 | extendFile file rest@(((STableArray key), kvs) :: _) = do
131 | let (array, rest') = partition
132 | (\(sect, _) => case sect of
133 | (STableArray key') => key == key'
136 | array' <- traverse (map VTable . tableFromKVs) (map snd array)
137 | file' <- tableSetWithParts file (keyParts key) (VArray array')
138 | extendFile file' rest'
141 | parseTOML : (src : String) -> Either Error Table
143 | let Just toks = lexTOML src
144 | | Nothing => Left LexerError
146 | items <- bimap ParseError id (parseItems toks)
148 | let sects = sections items
150 | extendFile empty sects