1 package Text::Tradition::Morphology;
5 use JSON qw/ from_json /;
8 use Text::Tradition::Collation::Reading::Lexeme;
10 use vars qw/ $VERSION /;
15 Text::Tradition::Morphology - add-on to associate lemma and part-of-speech
16 information to Text::Tradition::Collation::Reading objects
20 has 'grammar_invalid' => (
26 has 'is_nonsense' => (
32 has 'normal_form' => (
35 predicate => '_has_normal_form',
36 clearer => '_clear_normal_form',
39 # Holds the lexemes for the reading.
40 has 'reading_lexemes' => (
42 isa => 'ArrayRef[Text::Tradition::Collation::Reading::Lexeme]',
45 lexemes => 'elements',
46 has_lexemes => 'count',
47 clear_lexemes => 'clear',
50 default => sub { [] },
55 # Make normal_form default to text, transparently.
56 around 'normal_form' => sub {
60 if( $arg && $arg eq $self->text ) {
61 $self->_clear_normal_form;
63 } elsif( !$arg && !$self->_has_normal_form ) {
72 Methods for the morphological information (if any) attached to readings.
73 A reading may be made up of multiple lexemes; the concatenated lexeme
74 strings ought to match the reading's normalized form.
76 See L<Text::Tradition::Collation::Reading::Lexeme> for more information
77 on Lexeme objects and their attributes.
81 Returns a true value if the reading has any attached lexemes.
85 Returns the Lexeme objects (if any) attached to the reading.
89 Wipes any associated Lexeme objects out of the reading.
91 =head2 add_lexeme( $lexobj )
93 Adds the Lexeme in $lexobj to the list of lexemes.
97 If the language of the reading is set, this method will use the appropriate
98 Language model to determine the lexemes that belong to this reading. See
99 L<Text::Tradition::lemmatize> if you wish to lemmatize an entire tradition.
105 unless( $self->has_language ) {
106 warn "Please set a language to lemmatize a tradition";
109 my $mod = "Text::Tradition::Language::" . $self->language;
111 $mod->can( 'reading_lookup' )->( $self );
115 # For graph serialization. Return a JSON representation of the associated
117 sub _serialize_lexemes {
119 my $json = JSON->new->allow_blessed(1)->convert_blessed(1);
120 return $json->encode( [ $self->lexemes ] );
123 # Given a JSON representation of the lexemes, instantiate them and add
124 # them to the reading.
125 sub _deserialize_lexemes {
126 my( $self, $json ) = @_;
127 my $data = from_json( $json );
128 return unless @$data;
131 foreach my $lexhash ( @$data ) {
132 push( @lexemes, Text::Tradition::Collation::Reading::Lexeme->new(
133 'JSON' => $lexhash ) );
135 $self->clear_lexemes;
136 $self->add_lexeme( @lexemes );
141 return 0 unless $self->has_lexemes;
142 return !grep { !$_->is_disambiguated } $self->lexemes;
147 # While we are here, get rid of any extra wordforms from a disambiguated
149 if( $self->disambiguated ) {
150 foreach my $lex ( $self->lexemes ) {
151 $lex->clear_matching_forms();
152 $lex->add_matching_form( $lex->form );
157 around 'is_identical' => sub {
161 # If the base class returns true, do an extra check to make sure the
162 # lexemes also match.
163 my $answer = $self->$orig( $other );
165 if( $self->disambiguated && $other->disambiguated ) {
166 my $rform = join( '//', map { $_->form->to_string } $self->lexemes );
167 my $uform = join( '//', map { $_->form->to_string } $other->lexemes );
168 $answer = undef unless $rform eq $uform;
169 } elsif( $self->disambiguated xor $other->disambiguated ) {
176 around 'is_combinable' => sub {
179 # If the reading is marked with invalid grammar or as a nonsense reading,
180 # it is no longer combinable.
181 return undef if $self->grammar_invalid || $self->is_nonsense;
182 return $self->$orig();
185 after '_combine' => sub {
190 join( $joinstr, $self->normal_form, $other->normal_form ) );
191 # Combine the lexemes present in the readings
192 if( $self->has_lexemes && $other->has_lexemes ) {
193 $self->add_lexeme( $other->lexemes );
201 This package is free software and is provided "as is" without express
202 or implied warranty. You can redistribute it and/or modify it under
203 the same terms as Perl itself.
207 Tara L Andrews E<lt>aurum@cpan.orgE<gt>