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 _) <- read1 (bytes sk)
239 | let ps := addCol (o2 `minus` o1) p
241 | write1 sk.error_ (Just $
B (Custom x) $
BS 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 | inc : Nat -> F1 q Nat
273 | inc k = read1 sk.pos >>= \n => writeAs sk.pos (k+n) n
278 | read : (ByteString -> a) -> (len : Nat) -> F1 q a
280 | bs <- read1 sk.bytes_
282 | pure (f $
substring p len bs)
287 | remString : F1 q String
290 | bs <- read1 sk.bytes_
291 | pure (stringTillEOL $
drop p bs)
297 | h1 <- replace1 sk.h1 ""
298 | h2 <- replace1 sk.h2 ""
299 | h3 <- replace1 sk.h3 ""
300 | sds <- getList sk.sdvals
301 | replace1 sk.isEmpty False >>= \case
303 | mg <- read1 sk.mgraph
304 | grps <- replace1 sk.groups SM.empty
305 | lupdNodes mg.graph $
{label $= map (groupLbl grps)}
306 | g <- Array.Core.unsafeFreeze mg.graph
307 | push1 sk.stack_ (MkMolfile h1 h2 h3 (G _ $
IG g) sds)
308 | True => push1 sk.stack_ (MkMolfile h1 h2 h3 (G 0 empty) sds)
310 | sdheader : ByteString -> F1 q CST
311 | sdheader bs = writeAs sk.sdhead (readHeader bs) SDValue
313 | endSDValue : F1 q CST
315 | hd <- read1 sk.sdhead
317 | push1 sk.sdvals (SD hd $
fromMaybe "" $
refineSDValue v)
322 | setIso : CST -> Isotope -> Step1 q CSz CSTCK
323 | setIso x i = \(_ # t) => let _ # t := modAtom {elem := i} t in x # t
331 | sdata : Steps q CSz CSTCK
333 | [ newline ("$$$$" >> newline) (end >> pure H1)
334 | , cexpr "$$$$" (end >> pure CDone)
335 | , convline ( '>' >> star dot >> newline) sdheader
340 | sdvalue : Steps q CSz CSTCK
342 | [ newline newline endSDValue
343 | , convline (dots >> newline) (pushStr Stack.SDValue . stringTillEOL)