@@ -215,8 +215,8 @@ private static boolean isSgroupDelim(char c) {
215215
216216 private static boolean processDataSgroups (CharIter iter , CxSmilesState state ) {
217217
218- if (state .dataSgroups == null )
219- state .dataSgroups = new ArrayList <>(4 );
218+ if (state .mysgroups == null )
219+ state .mysgroups = new ArrayList <>(4 );
220220
221221 final List <Integer > atomset = new ArrayList <>();
222222 if (!processIntList (iter , COMMA_SEPARATOR , atomset ))
@@ -237,7 +237,7 @@ private static boolean processDataSgroups(CharIter iter, CxSmilesState state) {
237237 final String value = unescape (iter .substr (beg , iter .pos ));
238238
239239 if (!iter .nextIf (':' )) {
240- state .dataSgroups .add (new CxSmilesState .DataSgroup (atomset , field , value , "" , "" , "" ));
240+ state .mysgroups .add (new CxSmilesState .CxDataSgroup (atomset , field , value , "" , "" , "" ));
241241 return true ;
242242 }
243243
@@ -247,7 +247,7 @@ private static boolean processDataSgroups(CharIter iter, CxSmilesState state) {
247247 final String operator = unescape (iter .substr (beg , iter .pos ));
248248
249249 if (!iter .nextIf (':' )) {
250- state .dataSgroups .add (new CxSmilesState .DataSgroup (atomset , field , value , operator , "" , "" ));
250+ state .mysgroups .add (new CxSmilesState .CxDataSgroup (atomset , field , value , operator , "" , "" ));
251251 return true ;
252252 }
253253
@@ -257,7 +257,7 @@ private static boolean processDataSgroups(CharIter iter, CxSmilesState state) {
257257 final String unit = unescape (iter .substr (beg , iter .pos ));
258258
259259 if (!iter .nextIf (':' )) {
260- state .dataSgroups .add (new CxSmilesState .DataSgroup (atomset , field , value , operator , unit , "" ));
260+ state .mysgroups .add (new CxSmilesState .CxDataSgroup (atomset , field , value , operator , unit , "" ));
261261 return true ;
262262 }
263263
@@ -266,7 +266,7 @@ private static boolean processDataSgroups(CharIter iter, CxSmilesState state) {
266266 iter .next ();
267267 final String tag = unescape (iter .substr (beg , iter .pos ));
268268
269- state .dataSgroups .add (new CxSmilesState .DataSgroup (atomset , field , value , operator , unit , tag ));
269+ state .mysgroups .add (new CxSmilesState .CxDataSgroup (atomset , field , value , operator , unit , tag ));
270270
271271 return true ;
272272 }
@@ -279,8 +279,8 @@ private static boolean processDataSgroups(CharIter iter, CxSmilesState state) {
279279 * @return parse was a success (or not)
280280 */
281281 private static boolean processPolymerSgroups (CharIter iter , CxSmilesState state ) {
282- if (state .sgroups == null )
283- state .sgroups = new ArrayList <>();
282+ if (state .mysgroups == null )
283+ state .mysgroups = new ArrayList <>();
284284 int beg = iter .pos ;
285285 while (iter .hasNext () && !isSgroupDelim (iter .curr ()))
286286 iter .next ();
@@ -308,18 +308,20 @@ private static boolean processPolymerSgroups(CharIter iter, CxSmilesState state)
308308 subscript = keyword ;
309309
310310 // "In the superscript only connectivity and flip information is allowed.", default
311- // appears to be "eu" either/unspecified
311+ // appears to be "eu" either/unspecified for SRU
312312 if (!iter .nextIf (':' ))
313313 return false ;
314314 beg = iter .pos ;
315315 while (iter .hasNext () && !isSgroupDelim (iter .curr ()))
316316 iter .next ();
317317 supscript = unescape (iter .substr (beg , iter .pos ));
318- if (supscript .isEmpty ())
318+ if (supscript .isEmpty () &&
319+ !keyword .equals ("c" )&&!keyword .equals ("mix" )&&
320+ !keyword .equals ("f" )&&!keyword .equals ("mod" ))
319321 supscript = "eu" ;
320322
321323 if (iter .nextIf (',' ) || iter .curr () == '|' ) {
322- state .sgroups .add (new CxSmilesState .PolymerSgroup (keyword , atomset , subscript , supscript ));
324+ state .mysgroups .add (new CxSmilesState .CxPolymerSgroup (keyword , atomset , subscript , supscript ));
323325 return true ;
324326 }
325327 // not supported: crossing bond info (difficult to work out from doc) and bracket orientation
@@ -493,6 +495,12 @@ else if (iter.nextIf("tu:")) {
493495 else if (iter .nextIf ("gD:" )) {
494496 if (!processDataSgroups (iter , state ))
495497 return -1 ;
498+ if (iter .nextIf (',' ))
499+ break ;
500+ }
501+ else if (iter .nextIf ("gH:" )) {
502+ if (!processSgroupsHierarchy (iter , state ))
503+ return -1 ;
496504 }
497505 else {
498506 return -1 ;
@@ -543,6 +551,42 @@ else if (iter.nextIf("gD:")) {
543551 return -1 ;
544552 }
545553
554+
555+ private static boolean processSgroupsHierarchy (CharIter iter , CxSmilesState state ) {
556+ int nsgroups = 0 ;
557+ if (state .mysgroups != null )
558+ nsgroups += state .mysgroups .size ();
559+ if (nsgroups == 0 )
560+ return false ; // may not be written yet
561+ for (;;) {
562+ int parent = processUnsignedInt (iter );
563+ if (parent < 0 )
564+ return false ;
565+ if (!iter .nextIf (':' ))
566+ return false ;
567+ List <Integer > children = new ArrayList <>();
568+ processIntList (iter , '.' , children );
569+ if (parent < state .mysgroups .size ()) {
570+ for (Integer child : children ) {
571+ if (child < nsgroups ) {
572+ state .mysgroups .get (parent ).children
573+ .add (state .mysgroups .get (child ));
574+ } else
575+ return false ; // missing Sgroup
576+ }
577+ } else {
578+ return false ; // missing Sgroup
579+ }
580+ if (iter .curr () == '|' )
581+ return true ;
582+ if (!iter .nextIf (',' ))
583+ return false ;
584+ if (!isDigit (iter .curr ()))
585+ return true ;
586+ }
587+ }
588+
589+
546590 private static boolean isDigit (char c ) {
547591 return c >= '0' && c <= '9' ;
548592 }
0 commit comments