Пример #1
0
        /**
         * Will parse the BibTex-Data found when reading from reader.
         *
         * The reader will be consumed.
         *
         * Multiple calls to parse() return the same results
         *
         * @return ParserResult
         * @throws IOException
         */
        public ParserResult Parse()
        {
            // If we already parsed this, just return it.
            if (_pr != null)
            return _pr;

            _db = new BibtexDatabase(); // Bibtex related contents.
            _meta = new Dictionary<string, string>(); // Metadata in comments for Bibkeeper.
            entryTypes = new Dictionary<string, BibtexEntryType>(); // To store custem entry types parsed.
            _pr = new ParserResult(_db, _meta, entryTypes);

            // First see if we can find the version number of the JabRef version that
            // wrote the file:
            string versionNum = ReadJabRefVersionNumber();
            if (versionNum != null) {
            _pr.JabrefVersion = versionNum;
            SetMajorMinorVersions();
            }
            else {
            // No version number found. However, we have only
            }

            SkipWhitespace();

            try {
            while (!_eof) {
                bool found = ConsumeUncritically('@');
                if (!found)
                    break;
                SkipWhitespace();
                string entryType = ParseTextToken();
                BibtexEntryType tp = BibtexEntryType.getType(entryType);
                bool isEntry = (tp != null);
                // Util.pr(tp.getName());
                if (!isEntry) {
                    // The entry type name was not recognized. This can mean
                    // that it is a string, preamble, or comment. If so,
                    // parse and set accordingly. If not, assume it is an entry
                    // with an unknown type.
                    if (entryType.ToLower().Equals("preamble")) {
                        _db.setPreamble(ParsePreamble());
                    } else if (entryType.ToLower().Equals("string")) {
                        BibtexString bs = ParseString();
                        try {
                            _db.addString(bs);
                        } catch (KeyCollisionException) {
                            _pr.AddWarning(Globals.lang("Duplicate string name") + ": "
                                + bs.getName());
                            // ex.printStackTrace();
                        }
                    } else if (entryType.ToLower().Equals("comment")) {
                        StringBuilder commentBuf = ParseBracketedTextExactly();
                        /**
                         *
                         * Metadata are used to store Bibkeeper-specific
                         * information in .bib files.
                         *
                         * Metadata are stored in bibtex files in the format
                         *
                         * @comment{jabref-meta: type:data0;data1;data2;...}
                         *
                         * Each comment that starts with the META_FLAG is stored
                         * in the meta Dictionary, with type as key. Unluckily, the
                         * old META_FLAG bibkeeper-meta: was used in JabRef 1.0
                         * and 1.1, so we need to support it as well. At least
                         * for a while. We'll always save with the new one.
                         */
                        // TODO: unicode escape sequences
                        string comment = commentBuf.ToString().Replace("[\\x0d\\x0a]", "");
                        if (comment.Substring(0,
                            Math.Min(comment.Length, Globals.META_FLAG.Length)).Equals(
                            Globals.META_FLAG)
                            || comment.Substring(0,
                                Math.Min(comment.Length, Globals.META_FLAG_OLD.Length))
                                .Equals(Globals.META_FLAG_OLD)) {

                            string rest;
                            if (comment.Substring(0, Globals.META_FLAG.Length).Equals(
                                Globals.META_FLAG))
                                rest = comment.Substring(Globals.META_FLAG.Length);
                            else
                                rest = comment.Substring(Globals.META_FLAG_OLD.Length);

                            int pos = rest.IndexOf(':');

                            if (pos > 0)
                                _meta.Add(rest.Substring(0, pos), rest.Substring(pos + 1));
                            // We remove all line breaks in the metadata - these
                            // will have been inserted
                            // to prevent too long lines when the file was
                            // saved, and are not part of the data.
                        }

                        /**
                         * A custom entry type can also be stored in a
                         *
                         * @comment:
                         */
                        if (comment.Substring(0,
                            Math.Min(comment.Length, Globals.ENTRYTYPE_FLAG.Length)).Equals(
                            Globals.ENTRYTYPE_FLAG)) {

                            CustomEntryType typ = CustomEntryType.parseEntryType(comment);
                            entryTypes.Add(typ.getName().ToLower(), typ);

                        }
                    } else {
                        // The entry type was not recognized. This may mean that
                        // it is a custom entry type whose definition will
                        // appear
                        // at the bottom of the file. So we use an
                        // UnknownEntryType
                        // to remember the type name by.
                        tp = new UnknownEntryType(entryType.ToLower());
                        // System.out.println("unknown type: "+entryType);
                        isEntry = true;
                    }
                }

                if (isEntry) // True if not comment, preamble or string.
                {
                    /**
                     * Morten Alver 13 Aug 2006: Trying to make the parser more
                     * robust. If an exception is thrown when parsing an entry,
                     * drop the entry and try to resume parsing. Add a warning
                     * for the user.
                     *
                     * An alternative solution is to try rescuing the entry for
                     * which parsing failed, by returning the entry with the
                     * exception and adding it before parsing is continued.
                     */
                    try {
                        BibtexEntry be = ParseEntry(tp);

                        bool duplicateKey = _db.insertEntry(be);
                        if (duplicateKey) // JZTODO lyrics
                            _pr.AddDuplicateKey(be.getCiteKey());
                            /*_pr.AddWarning(Globals.lang("duplicate BibTeX key") + ": "
                                + be.getCiteKey() + " ("
                                + Globals.lang("grouping may not work for this entry") + ")");                        */
                        else if (be.getCiteKey() == null || be.getCiteKey().Equals("")) {
                            _pr.AddWarning(Globals.lang("empty BibTeX key") + ": "
                                + be.getAuthorTitleYear(40) + " ("
                                + Globals.lang("grouping may not work for this entry") + ")");
                        }
                    } catch (IOException ex) {
                        _pr.AddWarning(Globals.lang("Error occured when parsing entry") + ": '"
                            + ex.Message + "'. " + Globals.lang("Skipped entry."));

                    }
                }

                SkipWhitespace();
            }

            // Before returning the database, update entries with unknown type
            // based on parsed type definitions, if possible.
            CheckEntryTypes(_pr);

            return _pr;
            } catch (KeyCollisionException kce) {
            // kce.printStackTrace();
            throw new IOException("Duplicate ID in bibtex file: " + kce.ToString());
            }
        }
Пример #2
0
        public void CheckEntryTypes(ParserResult _pr)
        {
            foreach (BibtexEntry be in _db.getEntries()){
            if (be.getType() is UnknownEntryType) {
                // Look up the unknown type name in our map of parsed types:

                object o = entryTypes[(be.getType().getName().ToLower())];
                if (o != null) {
                    BibtexEntryType type = (BibtexEntryType) o;
                    be.setType(type);
                } else {
                    // System.out.println("Unknown entry type:
                    // "+be.getType().getName());
                    _pr
                        .AddWarning(Globals.lang("unknown entry type") + ": "
                            + be.getType().getName() + ". " + Globals.lang("Type set to 'other'")
                            + ".");
                    be.setType(BibtexEntryType.OTHER.Instance);
                }
            }
            }
        }