0 | module Text.Molfile.Parser.KeyVal
2 | import Derive.Prelude
5 | import Text.ILex.State.Derive
6 | import Text.ILex.State.Regular
7 | import Text.Molfile.Parser.Util
8 | import Text.Molfile.Types
11 | %language ElabReflection
14 | data KV : Nat -> Type where
17 | L : List (KV 0) -> KV (S n)
18 | P : String -> KV 1 -> KV 2
20 | %runElab deriveIndexed "KV" [Show]
37 | toString : KV n -> Maybe String
38 | toString (S s) = Just s
39 | toString _ = Nothing
42 | toNat : KV n -> Maybe Nat
43 | toNat (I i) = if i >= 0 then Just (cast i) else Nothing
47 | toNats : KV n -> Maybe (List Nat)
48 | toNats (L xs) = traverse toNat xs
52 | lookupVal : String -> List KeyVal -> Maybe (KV 1)
53 | lookupVal s [] = Nothing
54 | lookupVal s (P k v :: xs) = if s == k then Just v else lookupVal s xs
55 | lookupVal s (_ :: xs) = lookupVal s xs
61 | %runElab deriveParserState "KSz" "KST"
62 | ["KIni","Entry","KVal","InStr","LStart","LVal","LEnd","KErr","KDone"]
64 | data Part : Type where
65 | VS : SnocList KeyVal -> Part
66 | VK : SnocList KeyVal -> String -> Part
67 | VO : SnocList KeyVal -> Nat -> SnocList (KV 0) -> Part
68 | VL : SnocList KeyVal -> String -> Nat -> SnocList (KV 0) -> Part
72 | ST = State MolErr Part KSz
78 | parameters {auto sk : ST q}
79 | part : KV 0 -> Part -> F1 q KST
80 | part p (VS sx) = putStackAs (VS $
sx:<w1 p) Entry
81 | part p (VK sx s) = putStackAs (VS $
sx:<P s (w0 p)) Entry
82 | part p (VO sx k sp) =
84 | 0 => putStackAs (VS $
sx:<(L $
sp<>>[p])) LEnd
85 | x => putStackAs (VO sx x (sp:<p)) LVal
86 | part p (VL sx s k sp) =
88 | 0 => putStackAs (VS $
sx:<P s (L $
sp<>>[p])) LEnd
89 | x => putStackAs (VL sx s x (sp:<p)) LVal
91 | key : String -> Part -> F1 q KST
92 | key s (VS sx) = putStackAs (VK sx s) KVal
96 | onPrim : KV 0 -> F1 q KST
97 | onPrim v = getStack >>= part v
100 | onKey : ByteString -> F1 q KST
101 | onKey v = getStack >>= key (toUpper $
toString $
dropEnd 1 v)
103 | startList : ByteString -> F1 q KST
105 | let n := cast {to = Nat} $
decimal bs
106 | in getStack >>= \case
107 | VS sx => putStackAs (VO sx n [<]) LVal
108 | VK sx s => putStackAs (VL sx s n [<]) LVal
118 | mv30 = like "M V30"
122 | keyValRest : RExp True
123 | keyValRest = dots >> star ('-' >> newline >> mv30 >> dots) >> newline
127 | spaced : HasBytes s => Steps q r s -> DFA q r s
128 | spaced ss = dfa $
ignore (plus ' ') :: ss
131 | size = posdigit >> star digit
140 | unquoted : RExp True
141 | unquoted = start >> star uqc
143 | uqc, start : RExp True
144 | uqc = dot && not ' ' && not ')' && not '='
145 | start = uqc && not '"' && not '('
147 | splitted : Steps q KSz ST -> DFA q KSz ST
150 | [ ignore ('-' >> newline >> mv30)
151 | , step' newline KDone
154 | val : Steps q KSz ST -> DFA q KSz ST
157 | [ bytes integer (onPrim . I . decimal)
158 | , string unquoted (onPrim . S)
162 | toplevel : DFA q KSz ST
165 | [ bytes (plus alphaNum >> '=') onKey
172 | [ string (plus $
dot && not '"' && not '-') (pushStr InStr)
173 | , step "\"\"" (pushStr InStr "\"")
174 | , step '-' (pushStr InStr "-")
175 | , step' ('-' >> newline >> mv30 >> ' ') InStr
176 | , step' ('-' >> newline >> mv30) InStr
177 | , closeStr '"' (onPrim . S)
184 | kvTrans : Lex1 q KSz ST
187 | [ E KIni $
dfa [step' mv30 KeyVal.Entry]
188 | , E Entry $
toplevel
189 | , E KVal $
toplevel
191 | , E LStart $
splitted [bytes size startList]
192 | , E LEnd $
splitted [close ')' (pure Entry)]
196 | kvErr : Arr32 KSz (ST q -> F1 q (BBErr MolErr))
198 | arr32 KSz (unexpected [])
199 | [ E InStr $
unclosedIfEOI "\"" []
200 | , E LStart $
unclosedIfEOI "(" []
201 | , E LVal $
unclosedIfEOI "(" []
202 | , E LEnd $
unclosedIfEOI "(" [")"]
205 | kvEOI : KST -> ST q -> F1 q (Either (BBErr MolErr) (List KeyVal))
207 | case sk == KDone || sk == Entry of
208 | False => arrFail ST kvErr sk s t
209 | True => case getStack t of
210 | VS vs # t => Right (vs <>> []) # t
211 | _ # t => Right [] # t
213 | kv : P1 q (BBErr MolErr) (List KeyVal)
214 | kv = P KIni (init (VS [<])) kvTrans noChunk kvErr kvEOI
218 | keyVals : ByteString -> Either (BBErr MolErr) (List KeyVal)
219 | keyVals = runBytes kv
221 | test : String -> IO ()
224 | (putStrLn . interpolate)
225 | (traverse_ printLn)
226 | (parseString kv Virtual s)
231 | M V30 FOO=12 BAR="quux" BAZ="this is a -
232 | M V30 test" AND=(7 1 2 3 4 5 -
233 | M V30 six "se=ven") im="not yet done"
239 | M V30 1 SUP 0 LABEL=a0 ATOMS=(1 1)\n