summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/bibtexperllibs/BibTeX
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2015-10-25 22:57:55 +0000
committerKarl Berry <karl@freefriends.org>2015-10-25 22:57:55 +0000
commit4a9225ab54c95efafd2534812e2f53697fd0f6d9 (patch)
tree0ba9a25e89367efb21e41640876facce6b60d08c /Master/texmf-dist/scripts/bibtexperllibs/BibTeX
parent4a0798e9378fdb2de85f56e1ef1d46653f86cc69 (diff)
bibtexperllibs (25oct15)
git-svn-id: svn://tug.org/texlive/trunk@38711 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/scripts/bibtexperllibs/BibTeX')
-rw-r--r--Master/texmf-dist/scripts/bibtexperllibs/BibTeX/Parser.pm308
-rw-r--r--Master/texmf-dist/scripts/bibtexperllibs/BibTeX/Parser/Author.pm267
-rw-r--r--Master/texmf-dist/scripts/bibtexperllibs/BibTeX/Parser/Entry.pm360
3 files changed, 935 insertions, 0 deletions
diff --git a/Master/texmf-dist/scripts/bibtexperllibs/BibTeX/Parser.pm b/Master/texmf-dist/scripts/bibtexperllibs/BibTeX/Parser.pm
new file mode 100644
index 00000000000..8f0ab3a4c49
--- /dev/null
+++ b/Master/texmf-dist/scripts/bibtexperllibs/BibTeX/Parser.pm
@@ -0,0 +1,308 @@
+package BibTeX::Parser;
+{
+ $BibTeX::Parser::VERSION = '0.65';
+}
+# ABSTRACT: A pure perl BibTeX parser
+use warnings;
+use strict;
+
+use BibTeX::Parser::Entry;
+
+
+my $re_namechar = qr/[a-zA-Z0-9\!\$\&\*\+\-\.\/\:\;\<\>\?\[\]\^\_\`\|]/o;
+my $re_name = qr/$re_namechar+/o;
+
+
+sub new {
+ my ( $class, $fh ) = @_;
+
+ return bless {
+ fh => $fh,
+ strings => {
+ jan => "January",
+ feb => "February",
+ mar => "March",
+ apr => "April",
+ may => "May",
+ jun => "June",
+ jul => "July",
+ aug => "August",
+ sep => "September",
+ oct => "October",
+ nov => "November",
+ dec => "December",
+
+ },
+ line => -1,
+ buffer => "",
+ }, $class;
+}
+
+sub _slurp_close_bracket;
+
+sub _parse_next {
+ my $self = shift;
+
+ while (1) { # loop until regular entry is finished
+ return 0 if $self->{fh}->eof;
+ local $_ = $self->{buffer};
+
+ until (/@/m) {
+ my $line = $self->{fh}->getline;
+ return 0 unless defined $line;
+ $_ .= $line;
+ }
+
+ my $current_entry = new BibTeX::Parser::Entry;
+ if (/@($re_name)/cgo) {
+ my $type = uc $1;
+ $current_entry->type( $type );
+ my $start_pos = pos($_) - length($type) - 1;
+
+ # read rest of entry (matches braces)
+ my $bracelevel = 0;
+ $bracelevel += tr/\{/\{/; #count braces
+ $bracelevel -= tr/\}/\}/;
+ while ( $bracelevel != 0 ) {
+ my $position = pos($_);
+ my $line = $self->{fh}->getline;
+ last unless defined $line;
+ $bracelevel =
+ $bracelevel + ( $line =~ tr/\{/\{/ ) - ( $line =~ tr/\}/\}/ );
+ $_ .= $line;
+ pos($_) = $position;
+ }
+
+ # Remember raw bibtex code
+ my $raw = substr($_, $start_pos);
+ $raw =~ s/^\s+//;
+ $raw =~ s/\s+$//;
+ $current_entry->raw_bibtex($raw);
+
+ my $pos = pos $_;
+ tr/\n/ /;
+ pos($_) = $pos;
+
+ if ( $type eq "STRING" ) {
+ if (/\G{\s*($re_name)\s*=\s*/cgo) {
+ my $key = $1;
+ my $value = _parse_string( $self->{strings} );
+ if ( defined $self->{strings}->{$key} ) {
+ warn("Redefining string $key!");
+ }
+ $self->{strings}->{$key} = $value;
+ /\G[\s\n]*\}/cg;
+ } else {
+ $current_entry->error("Malformed string!");
+ return $current_entry;
+ }
+ } elsif ( $type eq "COMMENT" or $type eq "PREAMBLE" ) {
+ /\G\{./cgo;
+ _slurp_close_bracket;
+ } else { # normal entry
+ $current_entry->parse_ok(1);
+
+ # parse key
+ if (/\G\s*\{(?:\s*($re_name)\s*,[\s\n]*|\s+\r?\s*)/cgo) {
+ $current_entry->key($1);
+
+ # fields
+ while (/\G[\s\n]*($re_name)[\s\n]*=[\s\n]*/cgo) {
+ $current_entry->field(
+ $1 => _parse_string( $self->{strings} ) );
+ my $idx = index( $_, ',', pos($_) );
+ pos($_) = $idx + 1 if $idx > 0;
+ }
+
+ return $current_entry;
+
+ } else {
+
+ $current_entry->error("Malformed entry (key contains illegal characters) at " . substr($_, pos($_) || 0, 20) . ", ignoring");
+ _slurp_close_bracket;
+ return $current_entry;
+ }
+ }
+
+ $self->{buffer} = substr $_, pos($_);
+
+ } else {
+ $current_entry->error("Did not find type at " . substr($_, pos($_) || 0, 20));
+ return $current_entry;
+ }
+
+ }
+}
+
+
+sub next {
+ my $self = shift;
+
+ return $self->_parse_next;
+}
+
+# slurp everything till the next closing brace. Handels
+# nested brackets
+sub _slurp_close_bracket {
+ my $bracelevel = 0;
+ BRACE: {
+ /\G[^\}]*\{/cg && do { $bracelevel++; redo BRACE };
+ /\G[^\{]*\}/cg
+ && do {
+ if ( $bracelevel > 0 ) {
+ $bracelevel--;
+ redo BRACE;
+ } else {
+ return;
+ }
+ }
+ }
+}
+
+# parse bibtex string in $_ and return. A BibTeX string is either enclosed
+# in double quotes '"' or matching braces '{}'. The braced form may contain
+# nested braces.
+sub _parse_string {
+ my $strings_ref = shift;
+
+ my $value = "";
+
+ PART: {
+ if (/\G(\d+)/cg) {
+ $value .= $1;
+ } elsif (/\G($re_name)/cgo) {
+ warn("Using undefined string $1") unless defined $strings_ref->{$1};
+ $value .= $strings_ref->{$1} || "";
+ } elsif (/\G"(([^"\\]*(\\.)*[^\\"]*)*)"/cgs)
+ { # quoted string with embeded escapes
+ $value .= $1;
+ } else {
+ my $part = _extract_bracketed( $_ );
+ $value .= substr $part, 1, length($part) - 2; # strip quotes
+ }
+
+ if (/\G\s*#\s*/cg) { # string concatenation by #
+ redo PART;
+ }
+ }
+ $value =~ s/[\s\n]+/ /g;
+ return $value;
+}
+
+sub _extract_bracketed
+{
+ for($_[0]) # alias to $_
+ {
+ /\G\s+/cg;
+ my $start = pos($_);
+ my $depth = 0;
+ while(1)
+ {
+ /\G\\./cg && next;
+ /\G\{/cg && (++$depth, next);
+ /\G\}/cg && (--$depth > 0 ? next : last);
+ /\G([^\\\{\}]+)/cg && next;
+ last; # end of string
+ }
+ return substr($_, $start, pos($_)-$start);
+ }
+}
+
+1; # End of BibTeX::Parser
+
+
+__END__
+=pod
+
+=head1 NAME
+
+BibTeX::Parser - A pure perl BibTeX parser
+
+=head1 VERSION
+
+version 0.65
+
+=head1 SYNOPSIS
+
+Parses BibTeX files.
+
+ use BibTeX::Parser;
+ use IO::File;
+
+ my $fh = IO::File->new("filename");
+
+ # Create parser object ...
+ my $parser = BibTeX::Parser->new($fh);
+
+ # ... and iterate over entries
+ while (my $entry = $parser->next ) {
+ if ($entry->parse_ok) {
+ my $type = $entry->type;
+ my $title = $entry->field("title");
+
+ my @authors = $entry->author;
+ # or:
+ my @editors = $entry->editor;
+
+ foreach my $author (@authors) {
+ print $author->first . " "
+ . $author->von . " "
+ . $author->last . ", "
+ . $author->jr;
+ }
+ } else {
+ warn "Error parsing file: " . $entry->error;
+ }
+ }
+
+=for stopwords jr von
+
+=head1 NAME
+
+BibTeX::Parser - A pure perl BibTeX parser
+
+=head1 VERSION
+
+version 0.65
+
+=head1 FUNCTIONS
+
+=head2 new
+
+Creates new parser object.
+
+Parameters:
+
+ * fh: A filehandle
+
+=head2 next
+
+Returns the next parsed entry or undef.
+
+=head2 SEE ALSO
+
+=over 4
+
+=item
+
+L<BibTeX::Parser::Entry>
+
+=item
+
+L<BibTeX::Parser::Author>
+
+=back
+
+=head1 AUTHOR
+
+Gerhard Gossen <gerhard.gossen@googlemail.com>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2013 by Gerhard Gossen.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
+
diff --git a/Master/texmf-dist/scripts/bibtexperllibs/BibTeX/Parser/Author.pm b/Master/texmf-dist/scripts/bibtexperllibs/BibTeX/Parser/Author.pm
new file mode 100644
index 00000000000..c358d245116
--- /dev/null
+++ b/Master/texmf-dist/scripts/bibtexperllibs/BibTeX/Parser/Author.pm
@@ -0,0 +1,267 @@
+package BibTeX::Parser::Author;
+{
+ $BibTeX::Parser::Author::VERSION = '0.65';
+}
+
+use warnings;
+use strict;
+
+use overload
+ '""' => \&to_string;
+
+
+
+sub new {
+ my $class = shift;
+
+ if (@_) {
+ my $self = [ $class->split(@_) ];
+ return bless $self, $class;
+ } else {
+ return bless [], $class;
+ }
+}
+
+sub _get_or_set_field {
+ my ($self, $field, $value) = @_;
+ if (defined $value) {
+ $self->[$field] = $value;
+ } else {
+ return $self->[$field];
+ }
+}
+
+
+sub first {
+ shift->_get_or_set_field(0, @_);
+}
+
+
+sub von {
+ shift->_get_or_set_field(1, @_);
+}
+
+
+sub last {
+ shift->_get_or_set_field(2, @_);
+}
+
+
+sub jr {
+ shift->_get_or_set_field(3, @_);
+}
+
+
+sub split {
+ my ($self_or_class, $name) = @_;
+
+ # remove whitespace at start and end of string
+ $name =~ s/^\s*(.*)\s*$/$1/s;
+
+ if ( $name =~ /^\{\s*(.*)\s*\}$/ ) {
+ return (undef, undef, $1, undef);
+ }
+
+ if ( $name =~ /\{/ ) {
+ my @tokens;
+ my $cur_token = '';
+ while ( scalar( $name =~ /\G \s* ( [^,\{]*? ) ( \s* , \s* | \{ | \s* $ ) /xgc ) ) {
+ $cur_token .= $1 if $1;
+ if ( $2 =~ /\{/ ) {
+ if ( scalar( $name =~ /\G([^\}]*)\}/gc ) ) {
+ $cur_token .= "{$1}";
+ } else {
+ die "Unmatched brace in name '$name'";
+ }
+ } else {
+ $cur_token =~ s/\s*$//;
+ push @tokens, $cur_token if $cur_token;
+ $cur_token = '';
+ }
+ }
+ push @tokens, $cur_token if $cur_token;
+ return _get_single_author_from_tokens( @tokens );
+ } else {
+ my @tokens = split /\s*,\s*/, $name;
+
+ return _get_single_author_from_tokens( @tokens );
+ }
+}
+
+sub _split_name_parts {
+ my $name = shift;
+
+ if ( $name !~ /\{/ ) {
+ return split /\s+/, $name;
+ } else {
+ my @parts;
+ my $cur_token = '';
+ while ( scalar( $name =~ /\G ( [^\s\{]* ) ( \s+ | \{ | \s* $ ) /xgc ) ) {
+ $cur_token .= $1;
+ if ( $2 =~ /\{/ ) {
+ if ( scalar( $name =~ /\G([^\}]*)\}/gc ) ) {
+ $cur_token .= "{$1}";
+ } else {
+ die "Unmatched brace in name '$name'";
+ }
+ } else {
+ if ( $cur_token =~ /^{(.*)}$/ ) {
+ $cur_token = $1;
+ }
+ push @parts, $cur_token;
+ $cur_token = '';
+ }
+ }
+ return @parts;
+ }
+
+}
+
+
+sub _get_single_author_from_tokens {
+ my (@tokens) = @_;
+ if (@tokens == 0) {
+ return (undef, undef, undef, undef);
+ } elsif (@tokens == 1) { # name without comma
+ if ( $tokens[0] =~ /(^|\s)[[:lower:]]/) { # name has von part or has only lowercase names
+ my @name_parts = _split_name_parts $tokens[0];
+
+ my $first;
+ while (@name_parts && ucfirst($name_parts[0]) eq $name_parts[0] ) {
+ $first .= $first ? ' ' . shift @name_parts : shift @name_parts;
+ }
+
+ my $von;
+ # von part are lowercase words
+ while ( @name_parts && lc($name_parts[0]) eq $name_parts[0] ) {
+ $von .= $von ? ' ' . shift @name_parts : shift @name_parts;
+ }
+
+ if (@name_parts) {
+ return ($first, $von, join(" ", @name_parts), undef);
+ } else {
+ return (undef, undef, $tokens[0], undef);
+ }
+ } else {
+ if ( $tokens[0] !~ /\{/ && $tokens[0] =~ /^((.*)\s+)?\b(\S+)$/) {
+ return ($2, undef, $3, undef);
+ } else {
+ my @name_parts = _split_name_parts $tokens[0];
+ return ($name_parts[0], undef, $name_parts[1], undef);
+ }
+ }
+
+ } elsif (@tokens == 2) {
+ my @von_last_parts = _split_name_parts $tokens[0];
+ my $von;
+ # von part are lowercase words
+ while ( @von_last_parts && lc($von_last_parts[0]) eq $von_last_parts[0] ) {
+ $von .= $von ? ' ' . shift @von_last_parts : shift @von_last_parts;
+ }
+ return ($tokens[1], $von, join(" ", @von_last_parts), undef);
+ } else {
+ my @von_last_parts = _split_name_parts $tokens[0];
+ my $von;
+ # von part are lowercase words
+ while ( @von_last_parts && lc($von_last_parts[0]) eq $von_last_parts[0] ) {
+ $von .= $von ? ' ' . shift @von_last_parts : shift @von_last_parts;
+ }
+ return ($tokens[2], $von, join(" ", @von_last_parts), $tokens[1]);
+ }
+
+}
+
+
+sub to_string {
+ my $self = shift;
+
+ if ($self->jr) {
+ return $self->von . " " . $self->last . ", " . $self->jr . ", " . $self->first;
+ } else {
+ return ($self->von ? $self->von . " " : '') . $self->last . ($self->first ? ", " . $self->first : '');
+ }
+}
+
+1; # End of BibTeX::Entry
+
+__END__
+=pod
+
+=head1 NAME
+
+BibTeX::Parser::Author
+
+=head1 VERSION
+
+version 0.65
+
+=head1 SYNOPSIS
+
+This class ist a wrapper for a single BibTeX author. It is usually created
+by a BibTeX::Parser.
+
+ use BibTeX::Parser::Author;
+
+ my $entry = BibTeX::Parser::Author->new($full_name);
+
+ my $firstname = $author->first;
+ my $von = $author->von;
+ my $last = $author->last;
+ my $jr = $author->jr;
+
+ # or ...
+
+ my ($first, $von, $last, $jr) = BibTeX::Author->split($fullname);
+
+=head1 NAME
+
+BibTeX::Author - Contains a single author for a BibTeX document.
+
+=head1 VERSION
+
+version 0.65
+
+=head1 FUNCTIONS
+
+=head2 new
+
+Create new author object. Expects full name as parameter.
+
+=head2 first
+
+Set or get first name(s).
+
+=head2 von
+
+Set or get 'von' part of name.
+
+=head2 last
+
+Set or get last name(s).
+
+=head2 jr
+
+Set or get 'jr' part of name.
+
+=head2 split
+
+Split name into (firstname, von part, last name, jr part). Returns array
+with four strings, some of them possibly empty.
+
+=head2 to_string
+
+Return string representation of the name.
+
+=head1 AUTHOR
+
+Gerhard Gossen <gerhard.gossen@googlemail.com>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2013 by Gerhard Gossen.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
+
diff --git a/Master/texmf-dist/scripts/bibtexperllibs/BibTeX/Parser/Entry.pm b/Master/texmf-dist/scripts/bibtexperllibs/BibTeX/Parser/Entry.pm
new file mode 100644
index 00000000000..6fb54a3972a
--- /dev/null
+++ b/Master/texmf-dist/scripts/bibtexperllibs/BibTeX/Parser/Entry.pm
@@ -0,0 +1,360 @@
+package BibTeX::Parser::Entry;
+{
+ $BibTeX::Parser::Entry::VERSION = '0.65';
+}
+
+use warnings;
+use strict;
+
+use BibTeX::Parser::Author;
+
+
+
+sub new {
+ my ($class, $type, $key, $parse_ok, $fieldsref) = @_;
+
+ my %fields = defined $fieldsref ? %$fieldsref : ();
+ if (defined $type) {
+ $fields{_type} = uc($type);
+ }
+ $fields{_key} = $key;
+ $fields{_parse_ok} = $parse_ok;
+ $fields{_raw} = '';
+ return bless \%fields, $class;
+}
+
+
+
+sub parse_ok {
+ my $self = shift;
+ if (@_) {
+ $self->{_parse_ok} = shift;
+ }
+ $self->{_parse_ok};
+}
+
+
+sub error {
+ my $self = shift;
+ if (@_) {
+ $self->{_error} = shift;
+ $self->parse_ok(0);
+ }
+ return $self->parse_ok ? undef : $self->{_error};
+}
+
+
+sub type {
+ if (scalar @_ == 1) {
+ # get
+ my $self = shift;
+ return $self->{_type};
+ } else {
+ # set
+ my ($self, $newval) = @_;
+ $self->{_type} = uc($newval);
+ }
+}
+
+
+sub key {
+ if (scalar @_ == 1) {
+ # get
+ my $self = shift;
+ return $self->{_key};
+ } else {
+ # set
+ my ($self, $newval) = @_;
+ $self->{_key} = $newval;
+ }
+
+}
+
+
+sub field {
+ if (scalar @_ == 2) {
+ # get
+ my ($self, $field) = @_;
+ return $self->{ lc( $field ) };
+ } else {
+ my ($self, $key, $value) = @_;
+ $self->{ lc( $key ) } = $value; #_sanitize_field($value);
+ }
+
+}
+
+use LaTeX::ToUnicode qw( convert );
+
+
+sub cleaned_field {
+ my ( $self, $field, @options ) = @_;
+ if ( $field =~ /author|editor/i ) {
+ return $self->field( $field );
+ } else {
+ return convert( $self->field( lc $field ), @options );
+ }
+}
+
+
+sub cleaned_author {
+ my $self = shift;
+ $self->_handle_cleaned_author_editor( [ $self->author ], @_ );
+}
+
+
+sub cleaned_editor {
+ my $self = shift;
+ $self->_handle_cleaned_author_editor( [ $self->editor ], @_ );
+}
+
+sub _handle_cleaned_author_editor {
+ my ( $self, $authors, @options ) = @_;
+ map {
+ my $author = $_;
+ my $new_author = BibTeX::Parser::Author->new;
+ map {
+ $new_author->$_( convert( $author->$_, @options ) )
+ } grep { defined $author->$_ } qw( first von last jr );
+ $new_author;
+ } @$authors;
+}
+
+no LaTeX::ToUnicode;
+
+sub _handle_author_editor {
+ my $type = shift;
+ my $self = shift;
+ if (@_) {
+ if (@_ == 1) { #single string
+ # my @names = split /\s+and\s+/i, $_[0];
+ my @names = _split_author_field( $_[0] );
+ $self->{"_$type"} = [map {new BibTeX::Parser::Author $_} @names];
+ $self->field($type, join " and ", @{$self->{"_$type"}});
+ } else {
+ $self->{"_$type"} = [];
+ foreach my $param (@_) {
+ if (ref $param eq "BibTeX::Author") {
+ push @{$self->{"_$type"}}, $param;
+ } else {
+ push @{$self->{"_$type"}}, new BibTeX::Parser::Author $param;
+ }
+
+ $self->field($type, join " and ", @{$self->{"_$type"}});
+ }
+ }
+ } else {
+ unless ( defined $self->{"_$type"} ) {
+ #my @names = split /\s+and\s+/i, $self->{$type} || "";
+ my @names = _split_author_field( $self->{$type} || "" );
+ $self->{"_$type"} = [map {new BibTeX::Parser::Author $_} @names];
+ }
+ return @{$self->{"_$type"}};
+ }
+}
+
+# _split_author_field($field)
+#
+# Split an author field into different author names.
+# Handles quoted names ({name}).
+sub _split_author_field {
+ my $field = shift;
+
+ return () if !defined $field || $field eq '';
+
+ my @names;
+
+ my $buffer;
+ while (!defined pos $field || pos $field < length $field) {
+ if ( $field =~ /\G ( .*? ) ( \{ | \s+ and \s+ )/xcgi ) {
+ my $match = $1;
+ if ( $2 =~ /and/i ) {
+ $buffer .= $match;
+ push @names, $buffer;
+ $buffer = "";
+ } elsif ( $2 =~ /\{/ ) {
+ $buffer .= $match . "{";
+ if ( $field =~ /\G (.* \})/cgx ) {
+ $buffer .= $1;
+ } else {
+ die "Missing closing brace at " . substr( $field, pos $field, 10 );
+ }
+ } else {
+ $buffer .= $match;
+ }
+ } else {
+ #print "# $field " . (pos ($field) || 0) . "\n";
+ $buffer .= substr $field, (pos $field || 0);
+ last;
+ }
+ }
+ push @names, $buffer if $buffer;
+ return @names;
+}
+
+
+sub author {
+ _handle_author_editor('author', @_);
+}
+
+
+sub editor {
+ _handle_author_editor('editor', @_);
+}
+
+
+sub fieldlist {
+ my $self = shift;
+
+ return grep {!/^_/} keys %$self;
+}
+
+
+sub has {
+ my ($self, $field) = @_;
+
+ return defined $self->{$field};
+}
+
+sub _sanitize_field {
+ my $value = shift;
+ for ($value) {
+ tr/\{\}//d;
+ s/\\(?!=[ \\])//g;
+ s/\\\\/\\/g;
+ }
+ return $value;
+}
+
+
+
+sub raw_bibtex {
+ my $self = shift;
+ if (@_) {
+ $self->{_raw} = shift;
+ }
+ return $self->{_raw};
+}
+
+1; # End of BibTeX::Entry
+
+__END__
+=pod
+
+=head1 NAME
+
+BibTeX::Parser::Entry
+
+=head1 VERSION
+
+version 0.65
+
+=head1 SYNOPSIS
+
+This class ist a wrapper for a single BibTeX entry. It is usually created
+by a BibTeX::Parser.
+
+ use BibTeX::Parser::Entry;
+
+ my $entry = BibTeX::Parser::Entry->new($type, $key, $parse_ok, \%fields);
+
+ if ($entry->parse_ok) {
+ my $type = $entry->type;
+ my $key = $enty->key;
+ print $entry->field("title");
+ my @authors = $entry->author;
+ my @editors = $entry->editor;
+
+ ...
+ }
+
+=head1 NAME
+
+BibTeX::Entry - Contains a single entry of a BibTeX document.
+
+=head1 VERSION
+
+version 0.65
+
+=head1 FUNCTIONS
+
+=head2 new
+
+Create new entry.
+
+=head2 parse_ok
+
+If the entry was correctly parsed, this method returns a true value, false otherwise.
+
+=head2 error
+
+Return the error message, if the entry could not be parsed or undef otherwise.
+
+=head2 type
+
+Get or set the type of the entry, eg. 'ARTICLE' or 'BOOK'. Return value is
+always uppercase.
+
+=head2 key
+
+Get or set the reference key of the entry.
+
+=head2 field($name [, $value])
+
+Get or set the contents of a field. The first parameter is the name of the
+field, the second (optional) value is the new value.
+
+=head2 cleaned_field($name)
+
+Retrieve the contents of a field in a format that is cleaned of TeX markup.
+
+=head2 cleaned_author
+
+Get an array of L<BibTeX::Parser::Author> objects for the authors of this
+entry. Each name has been cleaned of accents and braces.
+
+=head2 cleaned_editor
+
+Get an array of L<BibTeX::Parser::Author> objects for the editors of this
+entry. Each name has been cleaned of accents and braces.
+
+=head2 author([@authors])
+
+Get or set the authors. Returns an array of L<BibTeX::Author|BibTeX::Author>
+objects. The parameters can either be L<BibTeX::Author|BibTeX::Author> objects
+or strings.
+
+Note: You can also change the authors with $entry->field('author', $authors_string)
+
+=head2 editor([@editors])
+
+Get or set the editors. Returns an array of L<BibTeX::Author|BibTeX::Author>
+objects. The parameters can either be L<BibTeX::Author|BibTeX::Author> objects
+or strings.
+
+Note: You can also change the authors with $entry->field('editor', $editors_string)
+
+=head2 fieldlist()
+
+Returns a list of all the fields used in this entry.
+
+=head2 has($fieldname)
+
+Returns a true value if this entry has a value for $fieldname.
+
+=head2 raw_bibtex
+
+Return raw BibTeX entry (if available).
+
+=head1 AUTHOR
+
+Gerhard Gossen <gerhard.gossen@googlemail.com>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2013 by Gerhard Gossen.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
+