private RDFTerm readObject(bool acceptLiteral)
        {
            int ch = input.read();

            if (ch < 0)
            {
                throw new ParserException();
            }
            else if (ch == '<')
            {
                return(RDFTerm.fromIRI(readIriReference()));
            }
            else if (acceptLiteral && (ch == '\"')) // start of quote literal
            {
                string str = readStringLiteral(ch);
                return(finishStringLiteral(str));
            }
            else if (ch == '_') // Blank Node Label
            {
                if (input.read() != ':')
                {
                    throw new ParserException();
                }
                string  label = readBlankNodeLabel();
                RDFTerm term  = bnodeLabels[label];
                if (term == null)
                {
                    term = RDFTerm.fromBlankNode(label);
                    bnodeLabels.Add(label, term);
                }
                return(term);
            }
            else
            {
                throw new ParserException();
            }
        }
        /*
         *  Replaces certain blank nodes with blank nodes whose
         *  names meet the N-Triples requirements
         * @param triples A set of RDF triples
         * @param bnodeLabels A mapping of blank node names
         * already allocated.  This method will modify this
         * _object as needed to allocate new blank nodes.
         */
        //
        internal static void replaceBlankNodes(ISet <RDFTriple> triples,
                                               IDictionary <string, RDFTerm> bnodeLabels)
        {
            if (bnodeLabels.Count == 0)
            {
                return;
            }
            IDictionary <string, RDFTerm> newBlankNodes  = new PeterO.Support.LenientDictionary <string, RDFTerm>();
            IList <RDFTriple[]>           changedTriples = new List <RDFTriple[]>();

            int[] nodeindex = new int[] { 0 };
            foreach (var triple in triples)
            {
                bool    changed = false;
                RDFTerm subj    = triple.getSubject();
                if (subj.getKind() == RDFTerm.BLANK)
                {
                    string oldname = subj.getValue();
                    string newname = suggestBlankNodeName(oldname, nodeindex, bnodeLabels);
                    if (!newname.Equals(oldname))
                    {
                        RDFTerm newNode = newBlankNodes[oldname];
                        if (newNode == null)
                        {
                            newNode = RDFTerm.fromBlankNode(newname);
                            bnodeLabels.Add(newname, newNode);
                            newBlankNodes.Add(oldname, newNode);
                        }
                        subj    = newNode;
                        changed = true;
                    }
                }
                RDFTerm obj = triple.getObject();
                if (obj.getKind() == RDFTerm.BLANK)
                {
                    string oldname = obj.getValue();
                    string newname = suggestBlankNodeName(oldname, nodeindex, bnodeLabels);
                    if (!newname.Equals(oldname))
                    {
                        RDFTerm newNode = newBlankNodes[oldname];
                        if (newNode == null)
                        {
                            newNode = RDFTerm.fromBlankNode(newname);
                            bnodeLabels.Add(newname, newNode);
                            newBlankNodes.Add(oldname, newNode);
                        }
                        obj     = newNode;
                        changed = true;
                    }
                }
                if (changed)
                {
                    RDFTriple[] newTriple = new RDFTriple[] { triple,
                                                              new RDFTriple(subj, triple.getPredicate(), obj) };
                    changedTriples.Add(newTriple);
                }
            }
            foreach (var triple in changedTriples)
            {
                triples.Remove(triple[0]);
                triples.Add(triple[1]);
            }
        }