0 | module Text.Molfile.Parser.V3000
3 | import Data.SortedMap
5 | import Text.Molfile.Parser.KeyVal
6 | import Text.Molfile.Parser.Stack
7 | import Text.Molfile.Parser.Util
8 | import Text.Molfile.Writer.Util
9 | import Text.Molfile.Writer.V3000
19 | beginV3 : (s : String) -> (0 p : NonEmpty (unpack s)) => RExp True
21 | mv30 >> spaces >> like "BEGIN" >> spaces >> like x >> dots >> newline
27 | v3000 = star sdigit >> like "V3000" >> newline >> beginV3 "CTAB"
31 | endV3 : (s : String) -> (0 p : NonEmpty (unpack s)) => RExp True
32 | endV3 x = mv30 >> spaces >> "END" >> spaces >> like x >> spaces >> newline
35 | countsExpr : RExp True
36 | countsExpr = mv30 >> like "COUNTS" >> spaces
39 | bondExprV3 : RExp True
40 | bondExprV3 = mv30 >> repeat 4 (spaces >> plus digit)
44 | coordinatesV3 : RExp True
46 | let pre := ('-' >> repeatRange 1 4 digit) <|> repeatRange 1 5 digit
47 | rem := '.' >> repeatRange 1 4 digit
48 | coord := pre >> opt rem
49 | in coord >> plus ' ' >> coord >> plus ' ' >> coord
51 | supLines : RExp True
52 | supLines = mv30 >> spaces >> decimal >> spaces >> like "SUP" >> keyValRest
58 | parameters {auto sk : CSTCK q}
63 | newV3 : ByteString -> F1 q CST
65 | case cast {to = Nat} (decimal bs) of
66 | 0 => writeAs sk.isEmpty True EmptyV3
69 | writeAs sk.mgraph g BCount
73 | bondsV3 : ByteString -> F1 q CST
74 | bondsV3 bs = writeAs sk.count (cast $
decimal bs) CountEnd
79 | indexV3 : ByteString -> F1 q CST
81 | let ix := cast {to = Nat} (decimal bs)
82 | g <- read1 sk.mgraph
84 | m <- read1 g.indices
85 | case SortedMap.lookup ix m of
86 | Nothing => writeAs g.indices (insert ix x m) Sym3
87 | Just _ => failHere {s = CSTCK} (Custom $
MNode ix) CErr
91 | mg <- read1 sk.mgraph
93 | let x2 := finToNat $
FS x
95 | Just0 prf => writeAs mg.atom (natToFinLT x2) Atom3
96 | Nothing0 => pure AtomEnd
98 | massV3 : ByteString -> F1 q CST
100 | let x := decimal $
drop 5 bs
101 | in case refineMassNr (cast x) of
102 | Nothing => failHere (Custom $
MMass x) CErr
103 | Just x => modAtom {elem $= setMass x} >> pure Prop3
106 | beginBondV3 : F1 q CST
107 | beginBondV3 = countdown sk.count BondBegin RestV3
110 | checkBondV3 : F1 q CST
111 | checkBondV3 = T1.do
112 | mg <- read1 sk.mgraph
113 | Just e <- read1 mg.bond | Nothing => pure BondEnd
114 | linsEdge mg.graph e
115 | countdown sk.count Bnd3 BondEnd
120 | coordsV3 : ByteString -> F1 q CST
122 | let (x,r) := break (SPACE ==) (trimLeft bs)
123 | (y,z) := break (SPACE ==) (trimLeft r)
124 | in modAtom {position := [coord x,coord y,coord z]} >> pure AAMap
127 | bondV3 : ByteString -> F1 q CST
129 | [_,_,_,tp,a1,a2] <- pure (splitNonEmpty SPACE bs) | _ => checkBondV3
130 | mg <- read1 sk.mgraph
131 | ixs <- read1 mg.indices
132 | let Right x := lkpNode ixs a1 | Left x => failErr x
133 | Right e := lkpEdge ixs x a2 | Left x => failErr x
134 | Right o := bondOrder tp | Left x => failErr x
135 | lbl := MkBond (x < e.node2) o NoBondStereo
136 | writeAs mg.bond (Just $
{label := lbl} e) BndProp3
139 | sup : ByteString -> F1 q CST
140 | sup bs = case keyVals bs of
141 | Left x => getPosition >>= \p => failWith (fromPosition x p) CErr
142 | Right (I n::S _::I _::t) => case lookupVal "LABEL" t >>= toString of
143 | Just lbl => case lookupVal "ATOMS" t >>= toNats of
145 | mg <- read1 sk.mgraph
146 | addGroup (cast n) mg lbl as
147 | Nothing => failHere (Custom MAbbr) CErr
148 | Nothing => failHere (Custom MAbbr) CErr
149 | Right p => failHere (Custom MAbbr) CErr
151 | addGroup : Nat -> MGraph q -> String -> List Nat -> F1 q CST
152 | addGroup v g l [] = pure SGroup
153 | addGroup v g l (x :: xs) = T1.do
154 | is <- read1 g.indices
155 | let Just n := lookup x is | _ => failHere {sk} (Custom $
MNode x) CErr
156 | lupdNode g.graph n {label := Just $
G v l}
159 | bondStereoV3 : BondStereo -> Step1 q CSz CSTCK
160 | bondStereoV3 s (_ # t) = let _ # t := modBond {stereo := s} t in BndProp3 # t
162 | chargeV3 : Charge -> Step1 q CSz CSTCK
163 | chargeV3 c (_ # t) = let _ # t := modAtom {charge := c} t in Prop3 # t
165 | radicalV3 : Radical -> Step1 q CSz CSTCK
166 | radicalV3 c (_ # t) = let _ # t := modAtom {radical := c} t in Prop3 # t
173 | mv30prefix : Nat -> RExp b -> CST -> (RExp True, Step q CSz CSTCK)
174 | mv30prefix n x = linecol' n 6 (orT $
x >> mv30)
177 | emptyEnd : List (RExp True, Step q CSz CSTCK)
179 | let pre := zeroes >> endV3 "CTAB" >> m_end
180 | in [newlines' 3 pre CDone, newlines' 3 (pre >> newline) EndMol]
192 | prop3 : List (RExp True, Step q CSz CSTCK)
194 | vals (("CHG="++) . interpolate) chargeV3 values
195 | ++ vals (("RAD="++) . dispRadical) radicalV3 values
196 | ++ [ conv (like "MASS=" >> plus digit) massV3
197 | , cexpr' (like "CFG=" >> oneof ['0','1','2','3']) Prop3
198 | , conv' (like "VAL=" >> integer) Prop3
199 | , conv' (like "HCOUNT=" >> integer) Prop3
200 | , cexpr' (like "STBOX=" >> bindigit) Prop3
201 | , cexpr' (like "INVERT=" >> oneof ['0','1','2']) Prop3
202 | , cexpr' (like "EXACHG=" >> bindigit) Prop3
203 | , conv' (like "SUBST=" >> integer) Prop3
204 | , cexpr' (like "UNSAT=" >> bindigit) Prop3
205 | , conv' (like "RBCNT=" >> integer) Prop3
206 | , conv' (like "ATTACHPT=" >> integer) Prop3
207 | , mv30prefix 1 ('-' >> newline) Prop3
208 | , newline newline atomV3
212 | bondProp3 : List (RExp True, Step q CSz CSTCK)
214 | vals (("CFG="++) . dispStereoV3) bondStereoV3 values
215 | ++ [ cexpr' (like "TOPO=" >> oneof ['0','1','2']) BndProp3
216 | , conv' (like "RXCTR=" >> integer) BndProp3
217 | , cexpr' (like "STBOX=" >> bindigit) BndProp3
218 | , mv30prefix 1 ('-' >> newline) BndProp3
219 | , newline newline checkBondV3
225 | rest3 : List (RExp True, Step q CSz CSTCK)
227 | [ conv' m_end CDone
228 | , newline' (m_end >> newline) EndMol
229 | , newline' (beginV3 "Sgroup") SGroup
230 | , newline' (mv30 >> dots >> newline) RestV3
234 | sgroup : List (RExp True, Step q CSz CSTCK)
236 | [ newline' (endV3 "Sgroup") RestV3
237 | , multiline supLines sup
238 | , newline' (mv30 >> dots >> newline) SGroup