/// <summary> /// Read a bracket atom from the buffer. A bracket atom optionally defines /// isotope, chirality, hydrogen count, formal charge and the atom class. /// <para> /// bracket_atom ::= '[' isotope? symbol chiral? hcount? charge? class? ']' /// </para> /// </summary> /// <param name="buffer">a character buffer</param> /// <returns>a bracket atom</returns> /// <exception cref="InvalidSmilesException">if the bracket atom did not match the grammar, invalid symbol, missing closing bracket or invalid chiral specification.</exception> public IAtom ReadBracketAtom(CharBuffer buffer) { int start = buffer.Position; bool arbitraryLabel = false; if (!buffer.HasRemaining()) { throw new InvalidSmilesException("Unclosed bracket atom, SMILES may be truncated", buffer); } var isotope = buffer.GetNumber(); var aromatic = buffer.NextChar >= 'a' && buffer.NextChar <= 'z'; var element = Element.Read(buffer); if (element == Element.Unknown) { hasAstrix = true; } if (strict && element == null) { throw new InvalidSmilesException("unrecognised element symbol, SMILES may be truncated: ", buffer); } if (element != null && aromatic) { g.AddFlags(Graph.HAS_AROM); } // element isn't aromatic as per the OpenSMILES specification if (strict && aromatic && !element.IsAromatic(Element.AromaticSpecification.OpenSmiles)) { throw new InvalidSmilesException("abnormal aromatic element", buffer); } if (element == null) { arbitraryLabel = true; } configuration = Configuration.Read(buffer); var hCount = ReadHydrogens(buffer); var charge = ReadCharge(buffer); var atomClass = ReadClass(buffer); if (!arbitraryLabel && !buffer.GetIf(']')) { if (strict) { throw InvalidSmilesException.InvalidBracketAtom(buffer); } else { arbitraryLabel = true; } } if (arbitraryLabel) { var end = buffer.Position; int depth = 1; while (buffer.HasRemaining()) { char c = buffer.Get(); if (c == '[') { depth++; } else if (c == ']') { depth--; if (depth == 0) { break; } } end++; } if (depth != 0) { throw new InvalidSmilesException("unparsable label in bracket atom", buffer, buffer.Position - 1); } var label = buffer.Substr(start, end); hasAstrix = true; return(new AtomImpl.BracketAtom(label)); } return(new AtomImpl.BracketAtom(isotope, element, hCount, charge, atomClass, aromatic)); }