0 | module Text.Molfile.Parser.KeyVal
2 | import Derive.Prelude
5 | import Text.ILex.Derive
6 | import Text.Molfile.Parser.Util
7 | import Text.Molfile.Types
10 | %language ElabReflection
13 | data KV : Nat -> Type where
16 | L : List (KV 0) -> KV (S n)
17 | P : String -> KV 1 -> KV 2
19 | %runElab deriveIndexed "KV" [Show]
36 | toString : KV n -> Maybe String
37 | toString (S s) = Just s
38 | toString _ = Nothing
41 | toNat : KV n -> Maybe Nat
42 | toNat (I i) = if i >= 0 then Just (cast i) else Nothing
46 | toNats : KV n -> Maybe (List Nat)
47 | toNats (L xs) = traverse toNat xs
51 | lookupVal : String -> List KeyVal -> Maybe (KV 1)
52 | lookupVal s [] = Nothing
53 | lookupVal s (P k v :: xs) = if s == k then Just v else lookupVal s xs
54 | lookupVal s (_ :: xs) = lookupVal s xs
60 | %runElab deriveParserState "KSz" "KST"
61 | ["KIni","Entry","KVal","InStr","LStart","LVal","LEnd","KErr","KDone"]
63 | data Part : Type where
64 | VS : SnocList KeyVal -> Part
65 | VK : SnocList KeyVal -> String -> Part
66 | VO : SnocList KeyVal -> Nat -> SnocList (KV 0) -> Part
67 | VL : SnocList KeyVal -> String -> Nat -> SnocList (KV 0) -> Part
71 | SK = Stack MolErr Part KSz
77 | parameters {auto sk : SK q}
78 | part : KV 0 -> Part -> F1 q KST
79 | part p (VS sx) = putStackAs (VS $
sx:<w1 p) Entry
80 | part p (VK sx s) = putStackAs (VS $
sx:<P s (w0 p)) Entry
81 | part p (VO sx k sp) =
83 | 0 => putStackAs (VS $
sx:<(L $
sp<>>[p])) LEnd
84 | x => putStackAs (VO sx x (sp:<p)) LVal
85 | part p (VL sx s k sp) =
87 | 0 => putStackAs (VS $
sx:<P s (L $
sp<>>[p])) LEnd
88 | x => putStackAs (VL sx s x (sp:<p)) LVal
90 | key : String -> Part -> F1 q KST
91 | key s (VS sx) = putStackAs (VK sx s) KVal
95 | onPrim : KV 0 -> F1 q KST
96 | onPrim v = getStack >>= part v
99 | onKey : ByteString -> F1 q KST
100 | onKey v = getStack >>= key (toUpper $
toString $
dropEnd 1 v)
102 | startList : ByteString -> F1 q KST
104 | let n := cast {to = Nat} $
decimal bs
105 | in getStack >>= \case
106 | VS sx => putStackAs (VO sx n [<]) LVal
107 | VK sx s => putStackAs (VL sx s n [<]) LVal
117 | mv30 = like "M V30"
121 | keyValRest : RExp True
122 | keyValRest = dots >> star ('-' >> newline >> mv30 >> dots) >> newline
126 | spaced : HasBytes s => HasPosition s => Index r -> Steps q r s -> DFA q r s
127 | spaced x ss = dfa $
conv' (plus ' ') x :: ss
130 | size = posdigit >> star digit
139 | unquoted : RExp True
140 | unquoted = start >> star uqc
142 | uqc, start : RExp True
143 | uqc = dot && not ' ' && not ')' && not '='
144 | start = uqc && not '"' && not '('
146 | splitted : KST -> Steps q KSz SK -> DFA q KSz SK
149 | [ linecol' 1 6 ('-' >> newline >> mv30) x
150 | , newline' newline KDone
153 | val : KST -> Steps q KSz SK -> DFA q KSz SK
156 | [ conv integer (onPrim . I . decimal)
157 | , read unquoted (onPrim . S)
161 | toplevel : KST -> DFA q KSz SK
164 | [ conv (plus alphaNum >> '=') onKey
165 | , copen' '(' LStart
171 | [ read (plus $
dot && not '"' && not '-') (pushStr InStr)
172 | , cexpr "\"\"" (pushStr InStr "\"")
173 | , cexpr '-' (pushStr InStr "-")
174 | , linecol' 1 7 ('-' >> newline >> mv30 >> ' ') InStr
175 | , linecol' 1 6 ('-' >> newline >> mv30) InStr
176 | , ccloseStr '"' (onPrim . S)
183 | kvTrans : Lex1 q KSz SK
186 | [ E KIni $
dfa [cexpr' mv30 KeyVal.Entry]
187 | , E Entry $
toplevel Entry
188 | , E KVal $
toplevel KVal
189 | , E LVal $
val LVal []
190 | , E LStart $
splitted LStart [conv size startList]
191 | , E LEnd $
splitted LEnd [cclose ')' (pure Entry)]
195 | kvErr : Arr32 KSz (SK q -> F1 q (BoundedErr MolErr))
197 | arr32 KSz (unexpected [])
198 | [ E InStr $
unclosedIfEOI "\"" []
199 | , E LStart $
unclosedIfEOI "(" []
200 | , E LVal $
unclosedIfEOI "(" []
201 | , E LEnd $
unclosedIfEOI "(" [")"]
204 | kvEOI : KST -> SK q -> F1 q (Either (BoundedErr MolErr) (List KeyVal))
206 | case sk == KDone || sk == Entry of
207 | False => arrFail SK kvErr sk s t
208 | True => case getStack t of
209 | VS vs # t => Right (vs <>> []) # t
210 | _ # t => Right [] # t
212 | kv : P1 q (BoundedErr MolErr) (List KeyVal)
213 | kv = P KIni (init (VS [<])) kvTrans noChunk kvErr kvEOI
217 | keyVals : ByteString -> Either (BoundedErr MolErr) (List KeyVal)
218 | keyVals = runBytes kv
220 | test : String -> IO ()
223 | (putStrLn . interpolate)
224 | (traverse_ printLn)
225 | (parseString kv Virtual s)
230 | M V30 FOO=12 BAR="quux" BAZ="this is a -
231 | M V30 test" AND=(7 1 2 3 4 5 -
232 | M V30 six "se=ven") im="not yet done"
238 | M V30 1 SUP 0 LABEL=a0 ATOMS=(1 1)\n