0 | module Text.Molfile.Parser.Util
2 | import Data.ByteString
3 | import Data.SortedMap as SM
4 | import Data.Array.Mutable
7 | import Text.Molfile.Parser.Stack
21 | isos = MkI H (Just 2) :: MkI H (Just 3) :: map (`MkI` Nothing) values
26 | stringTillEOL : ByteString -> String
27 | stringTillEOL = toString . dropWhileEnd isNL
30 | toCoord : Integer -> Coordinate
31 | toCoord = fromMaybe 0 . refineCoordinate
34 | coord : ByteString -> Coordinate
35 | coord (BS n bv) = go n
37 | postdot : Integer -> Nat -> (k : Nat) -> (x : Ix k n) => Integer
39 | postdot n (S x) 0 = postdot (n*10) x 0
40 | postdot n (S x) (S k) = postdot (n*10 + decimaldigit (bv `ix` k)) x k
42 | predot : Integer -> (k : Nat) -> (x : Ix k n) => Integer
43 | predot n (S k) = case bv `ix` k of
45 | b => predot (n*10 + decimaldigit b) k
46 | predot n 0 = n * 10_000
48 | go : (k : Nat) -> (x : Ix k n) => Coordinate
49 | go (S k) = case bv `ix` k of
51 | 45 => toCoord (negate $
predot 0 k)
52 | b => toCoord (predot (decimaldigit b) k)
57 | ErrPair = (ByteString,MolErr)
59 | public export %inline
65 | {auto cst : Cast Integer a}
70 | refineInt f err bs =
71 | let va := cast {to = a} (integer $
trim bs)
72 | Just vb := f va | Nothing => Left (bs, err va)
76 | blockcharge : ByteString -> Either ErrPair Charge
78 | case decimalSep SPACE bs of
86 | n => Left (bs,MCharge n)
89 | charge : ByteString -> Either ErrPair Charge
90 | charge = refineInt refineCharge (MCharge . cast)
93 | massNr : ByteString -> Either ErrPair MassNr
94 | massNr = refineInt refineMassNr (MMass . cast)
97 | radical : ByteString -> Either ErrPair Radical
99 | case decimalSep SPACE bs of
103 | 0 => Right NoRadical
104 | n => Left (bs, MRadical n)
107 | sgroupType : ByteString -> SGroupType
109 | case toString $
trim bs of
114 | bondOrder : ByteString -> Either ErrPair BondOrder
116 | case decimalSep SPACE bs of
120 | n => Left (bs, MBondOrder n)
123 | bondStereo : ByteString -> Either ErrPair BondStereo
125 | case decimalSep SPACE bs of
126 | 0 => Right NoBondStereo
131 | n => Left (bs, MBondStereo n)
134 | nat : ByteString -> Nat
135 | nat = cast . decimalSep SPACE
138 | node : {k : _} -> ByteString -> Either ErrPair (Fin k)
140 | case tryNatToFin (pred $
nat bs) of
142 | Nothing => Left (bs, MNode $
nat bs)
145 | uedge : {k : _} -> Fin k -> ByteString -> Either ErrPair (Edge k ())
147 | case tryNatToFin (pred $
nat bs) >>= \y => mkEdge x y () of
149 | Nothing => Left (bs, MNode $
nat bs)
152 | setMass : MassNr -> Isotope -> Isotope
153 | setMass v = {mass := Just v}
156 | groupLbl : SortedMap Nat String -> AtomGroup -> AtomGroup
157 | groupLbl m g@(G n l) = maybe g (G n) (lookup n m)
159 | parameters (ixs : SortedMap Nat (Fin k))
161 | lkpNode : ByteString -> Either ErrPair (Fin k)
163 | case lookup (nat bs) ixs of
165 | Nothing => Left (bs, MNode $
nat bs)
168 | lkpEdge : Fin k -> ByteString -> Either ErrPair (Edge k ())
170 | case lookup (nat bs) ixs >>= \y => mkEdge x y () of
172 | Nothing => Left (bs, MNode $
nat bs)
184 | fill : Nat -> String -> List String
185 | fill n s = go [<] (n `minus` length s) 0
187 | go : SnocList String -> Nat -> Nat -> List String
188 | go ss 0 j = ss <>> [s ++ replicate j ' ']
190 | go (ss:< (replicate (S k) ' ' ++ s ++ replicate j ' ')) k (S j)
197 | newline : RExp True
198 | newline = '\n' <|> "\r\n"
203 | sdigit = ' ' <|> digit
212 | zeroes = star (' ' <|> '0') >> newline
215 | spaces : RExp False
220 | m_end = "M END" >> spaces
226 | parameters {auto sk : CSTCK q}
235 | fail : ErrPair -> F1' q
236 | fail (BS l $
BV _ o2 _, x) = T1.do
237 | BS _ (BV _ o1 _) <- getBytes
239 | let ps := incLen (o2 `minus` o1) p
241 | write1 sk.error_ (Just $
B (Custom x) $
BB ps pe)
245 | failErr : ErrPair -> F1 q CST
246 | failErr p = fail p >> pure CErr
249 | h1,h2,h3 : ByteString -> F1 q CST
250 | h1 bs = writeAs sk.h1 (cast bs) H2
251 | h2 bs = writeAs sk.h2 (cast bs) H3
252 | h3 bs = writeAs sk.h3 (cast bs) Counts
256 | modAtom : (MolAtom -> MolAtom) -> F1' q
258 | mg <- read1 sk.mgraph
260 | modify mg.graph x {label $= f}
264 | modBond : (MolBond -> MolBond) -> F1' q
266 | mg <- read1 sk.mgraph
267 | mod1 mg.bond (map $
map f)
272 | read : (ByteString -> a) -> (len : Nat) -> F1 q a
276 | pure (f $
substring p len bs)
281 | remString : F1 q String
285 | pure (stringTillEOL $
drop p bs)
291 | h1 <- replace1 sk.h1 ""
292 | h2 <- replace1 sk.h2 ""
293 | h3 <- replace1 sk.h3 ""
294 | sds <- getList sk.sdvals
295 | replace1 sk.isEmpty False >>= \case
297 | mg <- read1 sk.mgraph
298 | grps <- replace1 sk.groups SM.empty
299 | lupdNodes mg.graph $
{label $= map (groupLbl grps)}
300 | g <- Array.Core.unsafeFreeze mg.graph
301 | push1 sk.stack_ (MkMolfile h1 h2 h3 (G _ $
IG g) sds)
302 | True => push1 sk.stack_ (MkMolfile h1 h2 h3 (G 0 empty) sds)
304 | sdheader : ByteString -> F1 q CST
305 | sdheader bs = writeAs sk.sdhead (readHeader bs) SDValue
307 | endSDValue : F1 q CST
309 | hd <- read1 sk.sdhead
311 | push1 sk.sdvals (SD hd $
fromMaybe "" $
refineSDValue v)
316 | setIso : CST -> Isotope -> Step1 q CSz CSTCK
317 | setIso x i = \_,t => let _ # t := modAtom {elem := i} t in x # t
325 | sdata : Steps q CSz CSTCK
327 | [ step ("$$$$" >> newline) (end >> pure H1)
328 | , step "$$$$" (end >> pure CDone)
329 | , bytes ( '>' >> star dot >> newline) sdheader
334 | sdvalue : Steps q CSz CSTCK
336 | [ step newline endSDValue
337 | , bytes (dots >> newline) (pushStr Stack.SDValue . stringTillEOL)