File Coverage

blib/lib/Treex/Core/Node/T.pm
Criterion Covered Total %
statement 110 270 40.7
branch 23 64 35.9
condition 13 51 25.4
subroutine 19 85 22.3
pod 21 72 29.1
total 186 542 34.3


line stmt bran cond sub pod time code
1             package Treex::Core::Node::T;
2             $Treex::Core::Node::T::VERSION = '2.20210102';
3 24     24   202 use namespace::autoclean;
  24         73  
  24         289  
4              
5 24     24   2338 use Moose;
  24         64  
  24         193  
6 24     24   174633 use Treex::Core::Common;
  24         68  
  24         292  
7             extends 'Treex::Core::Node';
8             with 'Treex::Core::Node::Ordered';
9             with 'Treex::Core::Node::InClause';
10             with 'Treex::Core::Node::EffectiveRelations';
11             with 'Treex::Core::Node::Interset' => { interset_attribute => 'dset' };
12              
13             # t-layer attributes
14             has [
15             qw( nodetype t_lemma functor subfunctor formeme tfa
16             is_dsp_root sentmod is_parenthesis is_passive is_generated
17             is_relclause_head is_name_of_person voice
18             t_lemma_origin formeme_origin is_infin
19             )
20             ] => ( is => 'rw' );
21              
22             sub get_pml_type_name {
23 83     83 1 172 my ($self) = @_;
24 83 100       234 return $self->is_root() ? 't-root.type' : 't-node.type';
25             }
26              
27             # the node is a root of a coordination/apposition construction
28             # analogy of PML_T::IsCoord
29             sub is_coap_root {
30 47     47 1 87 my ($self) = @_;
31 47 50       107 log_fatal("Incorrect number of arguments") if @_ != 1;
32 47   100     1418 return ( $self->functor || '' ) =~ /^(CONJ|CONFR|DISJ|GRAD|ADVS|CSQ|REAS|CONTRA|APPS|OPER)$/;
33             }
34              
35             #----------- helpers for reference lists ------------
36              
37             sub _get_node_list {
38 3     3   8 my ( $self, $list, $arg_ref ) = @_;
39 3         10 $list = $self->get_attr($list);
40 3         9 my $doc = $self->get_document();
41 3 100       11 my @nodes = $list ? ( map { $doc->get_node_by_id($_) } @{$list} ) : ();
  2         9  
  2         6  
42 3 50       13 return $arg_ref ? $self->_process_switches( $arg_ref, @nodes ) : @nodes;
43             }
44              
45             sub _set_node_list {
46 0     0   0 my $self = shift;
47 0         0 my $list = shift;
48 0         0 $self->set_attr( $list, [ map { $_->get_attr('id') } @_ ] );
  0         0  
49 0         0 return;
50             }
51              
52             sub _add_to_node_list {
53 1     1   4 my $self = shift;
54 1         3 my $list = shift;
55              
56             # get the current elements of the list
57 1         6 my $cur_ref = $self->get_attr($list);
58 1 50       5 my @cur = $cur_ref ? @{$cur_ref} : ();
  0         0  
59              
60             # grep only those that aren't already in the list
61             my @new = grep {
62 1         5 my $id = $_;
63 0     0   0 !any { $_ eq $id } @cur
64 1         3 } map { $_->get_attr('id') } @_;
  1         16  
  1         5  
65              
66             # set the new list value
67 1         8 $self->set_attr( $list, [ @cur, @new ] );
68 1         6 return;
69             }
70              
71             sub _remove_from_node_list {
72 0     0   0 my $self = shift;
73 0         0 my $list = shift;
74 0         0 my @prev = $self->_get_node_list($list);
75 0         0 my @remain;
76              
77 0         0 foreach my $node (@prev) {
78 0 0       0 if ( !grep { $_ == $node } @_ ) {
  0         0  
79 0         0 push @remain, $node;
80             }
81             }
82 0         0 $self->_set_node_list( $list, @remain );
83 0         0 return;
84             }
85              
86             # TODO: with backrefs this method is no more needed
87             # remove unindexed IDs from a list attribute
88             sub _update_list {
89              
90 0     0   0 my ( $self, $list ) = @_;
91 0         0 my $doc = $self->get_document();
92              
93 0         0 my $ref = $self->get_attr($list);
94 0         0 my (@nodes, @invalid);
95              
96 0 0       0 return if (!$ref);
97              
98 0         0 foreach my $id (@{$ref}){
  0         0  
99 0 0       0 if ($doc->id_is_indexed($id)){
100 0         0 push @nodes, $id;
101             }
102             else {
103 0         0 push @invalid, $id;
104             }
105             }
106              
107 0 0       0 $self->set_attr( $list, @nodes > 0 ? [@nodes] : undef );
108 0         0 return;
109             }
110              
111             #----------- a-layer (analytical) nodes -------------
112              
113             sub get_lex_anode {
114 5     5 1 378 my ($self) = @_;
115 5         22 my $lex_rf = $self->get_attr('a/lex.rf');
116 5         24 my $document = $self->get_document();
117 5 100       32 return $document->get_node_by_id($lex_rf) if $lex_rf;
118 1         4 return;
119             }
120              
121             sub set_lex_anode {
122 4     4 1 34 my ( $self, $lex_anode ) = @_;
123 4 50       21 my $new_id = defined $lex_anode ? $lex_anode->get_attr('id') : undef;
124 4         19 $self->set_attr( 'a/lex.rf', $new_id );
125 4         15 return;
126             }
127              
128             sub get_aux_anodes {
129 0     0 1 0 my ( $self, $arg_ref ) = @_;
130              
131             log_fatal('Switches preceding_only and following_only cannot be used with get_aux_anodes (t-nodes vs. a-nodes).')
132 0 0 0     0 if $arg_ref and ( $arg_ref->{preceding_only} or $arg_ref->{following_only} );
      0        
133              
134 0         0 return $self->_get_node_list( 'a/aux.rf', $arg_ref );
135             }
136              
137             sub set_aux_anodes {
138 0     0 1 0 my $self = shift;
139 0         0 return $self->_set_node_list( 'a/aux.rf', @_ );
140             }
141              
142             sub add_aux_anodes {
143 0     0 1 0 my $self = shift;
144 0         0 return $self->_add_to_node_list( 'a/aux.rf', @_ );
145             }
146              
147             sub remove_aux_anodes {
148 0     0 1 0 my $self = shift;
149 0         0 return $self->_remove_from_node_list( 'a/aux.rf', @_ );
150             }
151              
152             sub get_anodes {
153 0     0 1 0 my ( $self, $arg_ref ) = @_;
154 0         0 my $lex_anode = $self->get_lex_anode();
155 0 0       0 my @nodes = ( ( defined $lex_anode ? ($lex_anode) : () ), $self->get_aux_anodes() );
156 0 0       0 return @nodes if !$arg_ref;
157             log_fatal('Switches preceding_only and following_only cannot be used with get_anodes (t-nodes vs. a-nodes).')
158 0 0 0     0 if $arg_ref->{preceding_only} || $arg_ref->{following_only};
159 0         0 return $self->_process_switches( $arg_ref, @nodes );
160             }
161              
162             #------------ coreference and bridging nodes -------------------
163              
164             sub get_appos_expansion {
165 5     5 1 14 my ($self, $arg_ref ) = @_;
166 5 50 33     16 if ($self->is_coap_root && $self->functor eq "APPS") {
167 0 0       0 return ($self->get_coap_members({direct_only => 1}), $arg_ref->{with_appos_root} ? $self : ());
168             }
169             else {
170 5         20 my $par = $self->get_parent;
171 5 0 33     33 if (defined $par && !$par->is_root && $par->is_coap_root && $par->functor eq "APPS" && $self->is_member ) {
      33        
      33        
      0        
172 0 0       0 return ($par->get_coap_members({direct_only => 1}), $arg_ref->{with_appos_root} ? $par : ());
173             }
174             }
175 5         42 return $self;
176             }
177              
178             # types are not allowed for the time being
179             sub _unfold_appos {
180 3     3   10 my ( $self, $type ) = @_;
181              
182 3         16 my @appos_nodes_not_self = grep {$_ != $self} $self->get_appos_expansion({with_appos_root => 1});
  3         12  
183              
184 3         11 my @member_antes = ();
185             # type = { text, gram, all }
186 3 100       11 if ($type eq "gram") {
    50          
187 2         6 @member_antes = map {$_->get_coref_gram_nodes({appos_aware => 0})} @appos_nodes_not_self;
  0         0  
188             }
189             elsif ($type eq "text") {
190 1         3 @member_antes = map {$_->get_coref_text_nodes({appos_aware => 0})} @appos_nodes_not_self;
  0         0  
191             }
192             else {
193 0         0 @member_antes = map {$_->get_coref_nodes({appos_aware => 0})} @appos_nodes_not_self;
  0         0  
194             }
195 3         7 return @member_antes;
196             }
197              
198             sub _replace_appos_antes {
199 3     3   8 my (@antes) = @_;
200 3         6 my @new_antes = map {$_->get_appos_expansion({with_appos_root => 0})} @antes;
  2         8  
201 3         7 my %seen = ();
202 3         8 my @unique_antes = grep { !$seen{$_->id}++ } @new_antes;
  2         54  
203 3         9 return @unique_antes;
204             }
205              
206             sub _get_coref_nodes {
207 3     3   10 my ($self, $type, $arg_ref) = @_;
208              
209 3   50     17 my $appos_aware = $arg_ref->{appos_aware} // 1;
210 3   50     12 my $with_types = $arg_ref->{with_types} // 0;
211 3         12 delete $arg_ref->{$_} foreach (qw/appos_aware with_types/);
212              
213 3         7 my @antes = ();
214 3         4 my @types = ();
215              
216 3 100       10 if ($type ne 'text') {
217 2         8 my @gram_nodes = $self->_get_node_list('coref_gram.rf');
218 2         5 push @antes, @gram_nodes;
219 2         5 push @types, map {undef} @gram_nodes;
  1         14  
220             }
221 3 100       13 if ($type ne 'gram') {
222             # textual coreference in PDT2.0 and 2.5 style
223 1         6 my @text_nodes = $self->_get_node_list('coref_text.rf');
224 1         3 push @antes, @text_nodes;
225 1         4 push @types, map {undef} @text_nodes;
  1         3  
226             # textual coreference in PDT3.0 style
227 1   50     6 my $pdt30_text_coref_rf = $self->get_attr('coref_text') // [];
228 1         4 @text_nodes = map {$self->get_document->get_node_by_id( $_->{'target_node.rf'} )} @$pdt30_text_coref_rf;
  0         0  
229 1         3 my @text_types = map { $_->{'type'} } @$pdt30_text_coref_rf;
  0         0  
230 1         2 push @antes, @text_nodes;
231 1         4 push @types, @text_types;
232             }
233              
234             # for the time being, apposition-aware handling is disabled if types are demanded
235 3 50 33     16 if (!$with_types && $appos_aware) {
236 3         11 push @antes, $self->_unfold_appos($type);
237 3         18 @antes = _replace_appos_antes(@antes);
238             }
239              
240 3         17 my @filtered_antes = $self->_process_switches( $arg_ref, @antes );
241 3 50       28 return @filtered_antes if (!$with_types);
242              
243             # return both nodes and types (as list references - similar to alignments)
244 0         0 my %node_id_to_index = map {$antes[$_]->id => $_} 0 .. $#antes;
  0         0  
245             my @filtered_types = map {
246 0         0 my $idx = $node_id_to_index{$_->id};
  0         0  
247 0 0       0 defined $idx ? $types[$idx] : undef
248             } @filtered_antes;
249 0         0 return (\@filtered_antes, \@filtered_types);
250             }
251              
252              
253             sub get_coref_nodes {
254 0     0 1 0 my ( $self, $arg_ref ) = @_;
255 0         0 return $self->_get_coref_nodes('all', $arg_ref);
256             }
257              
258             sub get_coref_gram_nodes {
259 2     2 1 11 my ( $self, $arg_ref ) = @_;
260 2         10 return $self->_get_coref_nodes('gram', $arg_ref);
261             }
262              
263             sub get_coref_text_nodes {
264 1     1 1 4 my ( $self, $arg_ref ) = @_;
265 1         5 return $self->_get_coref_nodes('text', $arg_ref);
266             }
267              
268              
269             # it doesn't return a complete chain, just the members which are accessible
270             # from the current node
271             # TODO: with backrefs the whole chain is accessible now
272             sub get_coref_chain {
273 0     0 0 0 my ( $self, $arg_ref ) = @_;
274              
275 0         0 my %visited_nodes = ();
276 0         0 my @nodes;
277 0         0 my %sub_args = map {$_ => $arg_ref->{$_}} qw/appos_aware with_types/;
  0         0  
278 0         0 my @queue = $self->get_coref_nodes(\%sub_args);
279 0         0 while ( my $node = shift @queue ) {
280 0         0 $visited_nodes{$node} = 1;
281 0         0 push @nodes, $node;
282 0         0 my @antes = $node->get_coref_nodes(\%sub_args);
283 0         0 foreach my $ante (@antes) {
284 0 0       0 if ( !defined $visited_nodes{$ante} ) {
285 0         0 push @queue, $ante;
286             }
287             }
288             }
289              
290 0         0 return $self->_process_switches( $arg_ref, @nodes );
291             }
292              
293             sub select_node_if_apps {
294 2     2 0 4 my ($node) = @_;
295 2         9 my $par = $node->get_parent;
296 2 0 33     15 if (defined $par && !$par->is_root && $par->is_coap_root && $par->functor eq "APPS" && $node->is_member ) {
      33        
      33        
      0        
297 0         0 return $par;
298             }
299 2         16 return $node;
300             }
301              
302             sub _add_coref_nodes {
303 1     1   6 my ($self, $type, @antes) = @_;
304              
305             # if called on a member of an apposition, call it on the apposition root
306 1         6 my $anaph = select_node_if_apps($self);
307 1 50       5 if ($anaph != $self) {
308 0         0 return $anaph->_add_coref_nodes($type, @antes);
309             }
310              
311             # antes must be apposition roots if in apposition
312 1         4 @antes = map {select_node_if_apps($_)} @antes;
  1         3  
313              
314             # avoid link repeating and self-reference
315 1         4 my %seen;
316 1         3 @antes = grep {$_ != $self} grep {!$seen{$_->id}++} @antes;
  1         6  
  1         34  
317 1 50       6 return if (!@antes);
318              
319 1         8 $self->_add_to_node_list( "coref_$type.rf", @antes );
320             }
321              
322             sub add_coref_gram_nodes {
323 1     1 1 10 my $self = shift;
324 1         19 $self->_add_coref_nodes('gram', @_);
325             }
326              
327             sub add_coref_text_nodes {
328 0     0 0 0 my $self = shift;
329 0         0 $self->_add_coref_nodes('text', @_);
330             }
331              
332             sub remove_coref_nodes {
333 0     0 1 0 my $self = shift;
334 0         0 $self->_remove_from_node_list( 'coref_gram.rf', @_ );
335 0         0 $self->_remove_from_node_list( 'coref_text.rf', @_ );
336 0         0 return;
337             }
338              
339             # remove unindexed IDs from coreference lists
340             sub update_coref_nodes {
341 0     0 1 0 my $self = shift;
342              
343 0         0 $self->_update_list('coref_gram.rf');
344 0         0 $self->_update_list('coref_text.rf');
345 0         0 return;
346             }
347              
348             sub get_bridging_nodes {
349 0     0 1 0 my ($self, $arg_ref) = @_;
350 0   0     0 my $bridging = $self->get_attr('bridging') // [];
351 0         0 my $doc = $self->get_document;
352 0         0 my @nodes = map {$doc->get_node_by_id($_->{'target_node.rf'})} @$bridging;
  0         0  
353 0         0 my @types = map {$_->{'type'}} @$bridging;
  0         0  
354 0         0 return (\@nodes, \@types);
355             }
356              
357             sub add_bridging_node {
358 0     0 1 0 my ( $self, $node, $type ) = @_;
359 0         0 my $links_rf = $self->get_attr('bridging');
360 0   0     0 my %new_link = ( 'target_node.rf' => $node->id, 'type' => $type // ''); #/ so we have no undefs
361 0         0 push( @$links_rf, \%new_link );
362 0         0 $self->set_attr( 'bridging', $links_rf );
363 0         0 return;
364             }
365              
366             # ----------- complement nodes -------------
367              
368             sub get_compl_nodes {
369 0     0 0 0 my ( $self, $arg_ref ) = @_;
370 0         0 return $self->_get_node_list( 'compl.rf', $arg_ref );
371             }
372              
373             sub add_compl_nodes {
374 0     0 0 0 my $self = shift;
375 0         0 return $self->_add_to_node_list( 'compl.rf', @_ );
376             }
377              
378             sub remove_compl_nodes {
379 0     0 0 0 my $self = shift;
380 0         0 $self->_remove_from_node_list( 'compl.rf', @_ );
381 0         0 return;
382             }
383              
384             sub update_compl_nodes {
385 0     0 0 0 my $self = shift;
386 0         0 $self->_update_list('compl.rf');
387 0         0 return;
388             }
389              
390             #----------- n-layer (named entity) nodes -------------
391              
392             sub get_n_node {
393 2     2 1 10 my ($self) = @_;
394 2 50       8 my $lex_anode = $self->get_lex_anode() or return;
395 2         10 return $lex_anode->n_node();
396             }
397              
398             #----------- source t-layer (source-language in MT) nodes -------------
399              
400             sub src_tnode {
401 0     0 1   my ($self) = @_;
402 0 0         my $source_node_id = $self->get_attr('src_tnode.rf') or return;
403 0           return $self->get_document->get_node_by_id($source_node_id);
404             }
405              
406             sub set_src_tnode {
407 0     0 1   my ( $self, $source_node ) = @_;
408 0           $self->set_attr( 'src_tnode.rf', $source_node->id );
409 0           return;
410             }
411              
412             # ---- attributes that contain references
413              
414             override '_get_reference_attrs' => sub {
415              
416             my ($self) = @_;
417             return ('a/lex.rf', 'original_parent.rf', 'src_tnode.rf', 'a/aux.rf', 'compl.rf', 'coref_gram.rf', 'coref_text.rf');
418             };
419              
420             #----------- grammatemes -------------
421              
422             #TODO: make these real Moose attributes
423 0     0 0   sub gram_sempos { return $_[0]->get_attr('gram/sempos'); }
424 0     0 0   sub gram_gender { return $_[0]->get_attr('gram/gender'); }
425 0     0 0   sub gram_number { return $_[0]->get_attr('gram/number'); }
426 0     0 0   sub gram_degcmp { return $_[0]->get_attr('gram/degcmp'); }
427 0     0 0   sub gram_verbmod { return $_[0]->get_attr('gram/verbmod'); }
428 0     0 0   sub gram_deontmod { return $_[0]->get_attr('gram/deontmod'); }
429 0     0 0   sub gram_factmod { return $_[0]->get_attr('gram/factmod'); }
430 0     0 0   sub gram_tense { return $_[0]->get_attr('gram/tense'); }
431 0     0 0   sub gram_aspect { return $_[0]->get_attr('gram/aspect'); }
432 0     0 0   sub gram_resultative { return $_[0]->get_attr('gram/resultative'); }
433 0     0 0   sub gram_dispmod { return $_[0]->get_attr('gram/dispmod'); }
434 0     0 0   sub gram_iterativeness { return $_[0]->get_attr('gram/iterativeness'); }
435 0     0 0   sub gram_indeftype { return $_[0]->get_attr('gram/indeftype'); }
436 0     0 0   sub gram_person { return $_[0]->get_attr('gram/person'); }
437 0     0 0   sub gram_numertype { return $_[0]->get_attr('gram/numertype'); }
438 0     0 0   sub gram_politeness { return $_[0]->get_attr('gram/politeness'); }
439 0     0 0   sub gram_negation { return $_[0]->get_attr('gram/negation'); }
440 0     0 0   sub gram_definiteness { return $_[0]->get_attr('gram/definiteness'); }
441 0     0 0   sub gram_diathesis { return $_[0]->get_attr('gram/diathesis'); }
442 0     0 0   sub gram_diatgram { return $_[0]->get_attr('gram/diatgram'); }
443 0     0 0   sub gram_typgroup { return $_[0]->get_attr('gram/typgroup'); }
444              
445 0     0 0   sub set_gram_sempos { return $_[0]->set_attr( 'gram/sempos', $_[1] ); }
446 0     0 0   sub set_gram_gender { return $_[0]->set_attr( 'gram/gender', $_[1] ); }
447 0     0 0   sub set_gram_number { return $_[0]->set_attr( 'gram/number', $_[1] ); }
448 0     0 0   sub set_gram_degcmp { return $_[0]->set_attr( 'gram/degcmp', $_[1] ); }
449 0     0 0   sub set_gram_verbmod { return $_[0]->set_attr( 'gram/verbmod', $_[1] ); }
450 0     0 0   sub set_gram_deontmod { return $_[0]->set_attr( 'gram/deontmod', $_[1] ); }
451 0     0 0   sub set_gram_factmod { return $_[0]->set_attr( 'gram/factmod', $_[1] ); }
452 0     0 0   sub set_gram_tense { return $_[0]->set_attr( 'gram/tense', $_[1] ); }
453 0     0 0   sub set_gram_aspect { return $_[0]->set_attr( 'gram/aspect', $_[1] ); }
454 0     0 0   sub set_gram_resultative { return $_[0]->set_attr( 'gram/resultative', $_[1] ); }
455 0     0 0   sub set_gram_dispmod { return $_[0]->set_attr( 'gram/dispmod', $_[1] ); }
456 0     0 0   sub set_gram_iterativeness { return $_[0]->set_attr( 'gram/iterativeness', $_[1] ); }
457 0     0 0   sub set_gram_indeftype { return $_[0]->set_attr( 'gram/indeftype', $_[1] ); }
458 0     0 0   sub set_gram_person { return $_[0]->set_attr( 'gram/person', $_[1] ); }
459 0     0 0   sub set_gram_numertype { return $_[0]->set_attr( 'gram/numertype', $_[1] ); }
460 0     0 0   sub set_gram_politeness { return $_[0]->set_attr( 'gram/politeness', $_[1] ); }
461 0     0 0   sub set_gram_negation { return $_[0]->set_attr( 'gram/negation', $_[1] ); }
462 0     0 0   sub set_gram_definiteness { return $_[0]->set_attr( 'gram/definiteness', $_[1] ); }
463 0     0 0   sub set_gram_diathesis { return $_[0]->set_attr( 'gram/diathesis', $_[1] ); }
464 0     0 0   sub set_gram_diatgram { return $_[0]->set_attr( 'gram/diatgram', $_[1] ); }
465 0     0 0   sub set_gram_typgroup { return $_[0]->set_attr( 'gram/typgroup', $_[1] ); }
466              
467             #------------- valency frame reference -----
468              
469 0     0 0   sub val_frame_rf { return $_[0]->get_attr('val_frame.rf'); }
470 0     0 0   sub set_val_frame_rf { return $_[0]->set_attr('val_frame.rf', $_[1]); }
471              
472             1;
473              
474             __END__
475              
476             =encoding utf-8
477              
478             =head1 NAME
479              
480             Treex::Core::Node::T
481              
482             =head1 VERSION
483              
484             version 2.20210102
485              
486             =head1 DESCRIPTION
487              
488             t-layer (tectogrammatical) node
489              
490              
491             =head1 METHODS
492              
493             =head2 Access to a-layer (analytical nodes)
494              
495             =over
496              
497             =item $node->add_aux_anodes(@aux_anodes)
498              
499             Add auxiliary a-nodes (to C<a/aux.rf>)
500              
501             =item @anodes = $node->get_anodes()
502              
503             Return a-nodes (both auxiliary and lexical, ie. C<a/aux.rf> and C<a/lex.rf>)
504              
505             =item @aux_anodes = $node->get_aux_anodes()
506              
507             Return auxiliary a-nodes (from C<a/aux.rf>).
508              
509             =item $lex_anod = $node->get_lex_anode()
510              
511             Return the lexical a-nodes (from C<a/lex.rf>).
512              
513             =item $node->set_aux_anodes(@aux_anodes)
514              
515             Set the auxiliary a-nodes (to C<a/aux.rf>).
516              
517             =item set_lex_anode
518              
519             Set the lexical a-node (to C<a/lex.rf>).
520              
521             =item $node->remove_aux_anodes(@to_remove)
522              
523             Remove the specified a-nodes from C<a/aux.rf> (if they are contained in it).
524              
525             =item $node->get_coref_nodes()
526              
527             Return textual and grammatical coreference nodes (from C<coref_gram.rf> and C<coref_text.rf>).
528             If the document follows the PDT3.0 annotation style, the same steps as for C<$node->get_coref_text_nodes()> are applied.
529              
530             =item $node->get_coref_gram_nodes()
531              
532             Return grammatical coreference nodes (from C<coref_gram.rf>).
533              
534             =item $node->get_coref_text_nodes()
535              
536             Return textual coreference nodes (from C<coref_text.rf> if the document follows the PDT2.0 annotation style).
537             If the document follows the PDT3.0 annotation style, the list of nodes is extracted from C<coref_text/target_node.rf>.
538             If the C<with_types> parameter is set in C<arg_ref>, two list references are returned: the first one refers to a list of nodes
539             extracted from C<coref_text/target_node.rf>, the second one to a list of types from C<coref_text/type>.
540              
541             =item $node->add_coref_gram_nodes(@nodes)
542              
543             Add grammatical coreference nodes (to C<coref_gram.rf>).
544              
545             =item $node->add_coref_gram_nodes(@nodes)
546              
547             Add textual coreference nodes (to C<coref_text.rf>).
548              
549             =item $node->remove_coref_nodes()
550              
551             Remove the specified nodes from C<coref_gram.rf> or C<coref_text.rf> (if they are contained in one or both of them).
552              
553             =item $node->update_coref_nodes()
554              
555             Remove all invalid coreferences from C<coref_gram.rf> and C<coref_text.rf>.
556              
557             =item $node->get_bridging_nodes()
558              
559             Access the nodes referred from the current node by bridging anaphora (in C<bridging> attribute).
560             The method returns references to two lists of the equal length: the referred nodes and the types of bridging relations.
561              
562             =item $node->add_bridging_node($node, $type)
563              
564             Add bridging anaphora to C<$node> of type C<$type> (to C<bridging>).
565              
566             =item $node->get_appos_expansion($arg_ref?)
567              
568             If the node is part of an apposition (no matter whether as a root
569             or a member), return all the nodes that constitute the apposition.
570             Only the apposition root may be excluded from the selection if the
571             option C<with_appos_root> is off.
572             The method is used to abstract from the technical implementation
573             of appositions. So far, it is used by coreference accessors.
574              
575             OPTIONS
576              
577             =over
578              
579             =item with_appos_root
580              
581             Include the apposition root. Disabled by default.
582              
583             =back
584              
585             =back
586              
587             =head2 Access to source language t-layer (in MT)
588              
589             =over
590              
591             =item $src_tnode = $node->src_tnode()
592              
593             Return the source language (in MT) t-node (from C<src_tnode.rf>).
594              
595             =item set_src_tnode
596              
597             Set the source language (in MT) t-node (to C<src_tnode.rf>).
598              
599             =back
600              
601             =head2 Access to n-layer (named entity nodes)
602              
603             Note there is no C<set_n_node> method.
604             You must set the link from n-node to a a-node.
605              
606             =over
607              
608             =item $node->get_n_node()
609              
610             This is a shortcut for C<< $self->get_lex_anode()->n_node; >>
611             If this t-node is a part of a named entity,
612             this method returns the corresponding n-node (L<Treex::Core::Node::N>).
613             If this node is a part of more than one named entities,
614             only the most nested one is returned.
615             For example: "Bank of China"
616              
617             $n_node_for_china = $t_node_china->get_n_node();
618             print $n_node_for_china->get_attr('normalized_name'); # China
619             $n_node_for_bank_of_china = $n_node_for_china->get_parent();
620             print $n_node_for_bank_of_china->get_attr('normalized_name'); # Bank of China
621              
622              
623             =back
624              
625             =head2 Other methods
626              
627             =over
628              
629             =item is_coap_root
630              
631             Is this node a root (or head) of a coordination/apposition construction?
632             On t-layer this is decided based on C<functor =~ /^(CONJ|CONFR|DISJ|GRAD|ADVS|CSQ|REAS|CONTRA|APPS|OPER)/>.
633              
634             =back
635              
636              
637             =head1 AUTHOR
638              
639             Zdeněk Žabokrtský <zabokrtsky@ufal.mff.cuni.cz>
640              
641             Martin Popel <popel@ufal.mff.cuni.cz>
642              
643             Ondřej Dušek <odusek@ufal.mff.cuni.cz>
644              
645             Michal Novák <mnovak@ufal.mff.cuni.cz>
646              
647             =head1 COPYRIGHT AND LICENSE
648              
649             Copyright © 2011-2016 by Institute of Formal and Applied Linguistics, Charles University in Prague
650              
651             This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.