Beispiel #1
0
        /// <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));
        }