File Coverage

blib/lib/Treex/Core/Phrase/BaseNTerm.pm
Criterion Covered Total %
statement 67 190 35.2
branch 17 84 20.2
condition 4 27 14.8
subroutine 16 31 51.6
pod 19 20 95.0
total 123 352 34.9


line stmt bran cond sub pod time code
1             package Treex::Core::Phrase::BaseNTerm;
2             $Treex::Core::Phrase::BaseNTerm::VERSION = '2.20210102';
3 1     1   728 use utf8;
  1         4  
  1         6  
4 1     1   36 use namespace::autoclean;
  1         5  
  1         6  
5              
6 1     1   68 use Moose;
  1         2  
  1         7  
7 1     1   6660 use List::MoreUtils qw(any);
  1         3  
  1         13  
8 1     1   751 use Treex::Core::Log;
  1         3  
  1         74  
9 1     1   9 use Treex::Core::Phrase::NTerm;
  1         2  
  1         2588  
10              
11             extends 'Treex::Core::Phrase';
12              
13              
14              
15             has '_dependents_ref' =>
16             (
17             is => 'ro',
18             isa => 'ArrayRef[Treex::Core::Phrase]',
19             default => sub { [] },
20             documentation => 'The public should not access directly the array reference. '.
21             'They may use the public method dependents() to get the list.'
22             );
23              
24             has 'dead' =>
25             (
26             is => 'rw',
27             isa => 'Bool',
28             writer => '_set_dead',
29             reader => 'dead',
30             default => 0,
31             documentation => 'Most non-terminal phrases cannot exist without children. '.
32             'If we want to change the class of a non-terminal phrase, we construct '.
33             'an object of the new class and move the children there from the old '.
34             'one. But the old object will not be physically destroyed until it '.
35             'gets out of scope. So we will mark it as “dead”. If anyone tries to '.
36             'use the dead object, an exception will be thrown.'
37             );
38              
39              
40              
41             #------------------------------------------------------------------------------
42             # Tells whether this phrase is terminal. We could probably use the Moose's
43             # methods to query the class name but this will be more convenient.
44             #------------------------------------------------------------------------------
45             sub is_terminal
46             {
47 2     2 1 6 my $self = shift;
48 2         10 return 0;
49             }
50              
51              
52              
53             #------------------------------------------------------------------------------
54             # Returns the head child of the phrase. This is an abstract method that must be
55             # defined in every derived class.
56             #------------------------------------------------------------------------------
57             sub head
58             {
59 0     0 1 0 my $self = shift;
60 0         0 log_fatal("The head() method is not implemented");
61             }
62              
63              
64              
65             #------------------------------------------------------------------------------
66             # Takes a dependent child of this phrase and makes it the head. The standard
67             # NTerm phrase will define this method as just moving the head flag among its
68             # children. However, special classes of phrases (such as Coordination) do not
69             # allow to simply set the head. For such phrases, making them dependent on one
70             # of their current dependents means encapsulating them in a new nonterminal
71             # phrase. Such behavior is defined here. Note that the caller must be prepared
72             # that they will get a different phrase object than the one whose method they
73             # called! The current phrase or its replacement is returned by the method.
74             #------------------------------------------------------------------------------
75             sub set_head
76             {
77 0     0 0 0 my $self = shift;
78 0         0 my $new_head = shift; # Treex::Core::Phrase
79 0 0       0 log_fatal('Dead') if($self->dead());
80 0         0 my $old_head = $self->head();
81 0 0       0 return $self if ($new_head == $old_head);
82             # Remove the new head from the list of non-head children.
83 0         0 $new_head->set_parent(undef);
84             # Create a new nonterminal phrase with this head.
85 0         0 my $ntphrase = new Treex::Core::Phrase::NTerm('head' => $new_head);
86             # If the current phrase is a core child of another phrase, we must carefully
87             # replace it by the new one, otherwise the parent will complain.
88 0 0       0 if(defined($self->parent()))
89             {
90 0         0 $self->parent()->replace_child($self, $ntphrase);
91             }
92             # Attach the current phrase as a dependent to the new phrase.
93 0         0 $self->set_parent($ntphrase);
94             # Return the new nonterminal phrase that replaces me.
95 0         0 return $ntphrase;
96             }
97              
98              
99              
100             #------------------------------------------------------------------------------
101             # Figures out whether an ordered list of children is required. Allows both hash
102             # and non-hash notations, i.e.
103             # my @c = $p->dependents({'ordered' => 1});
104             # my @c = $p->dependents('ordered' => 1);
105             # my @c = $p->dependents('ordered');
106             #------------------------------------------------------------------------------
107             sub _order_required
108             {
109 13     13   24 my $self = shift;
110 13         22 my @parray = @_;
111 13 50       91 return 0 unless(@parray);
112 0 0       0 return $parray[0]->{ordered} if(ref($parray[0]) eq 'HASH');
113 0         0 my %phash = @_;
114 0 0       0 if(exists($phash{ordered}))
115             {
116             # To accommodate the $p->dependents('ordered') calling style, even undefined value will count as true.
117 0 0 0     0 if(defined($phash{ordered}) && $phash{ordered}==0)
118             {
119 0         0 return 0;
120             }
121 0         0 return 1;
122             }
123 0         0 return 0;
124             }
125              
126              
127              
128             #------------------------------------------------------------------------------
129             # Sorts a list of phrases according to the word order of their head nodes.
130             #------------------------------------------------------------------------------
131             sub order_phrases
132             {
133 0     0 1 0 my $self = shift;
134 0         0 return sort {$a->ord() <=> $b->ord()} (@_);
  0         0  
135             }
136              
137              
138              
139             #------------------------------------------------------------------------------
140             # Returns the list of all nodes covered by the phrase, i.e. the head node of
141             # this phrase and of all its descendants.
142             #------------------------------------------------------------------------------
143             sub nodes
144             {
145 0     0 1 0 my $self = shift;
146 0 0       0 log_fatal('Dead') if($self->dead());
147 0         0 my @children = $self->children();
148 0         0 my @nodes;
149 0         0 foreach my $child (@children)
150             {
151 0         0 my @child_nodes = $child->nodes();
152 0         0 push(@nodes, @child_nodes);
153             }
154             # Well, not the best possible naming, but... order_phrases() will work even
155             # for nodes, as long as they have the ord() attribute (which they must if they
156             # are wrapped in phrases).
157 0 0       0 return $self->_order_required(@_) ? $self->order_phrases(@nodes) : @nodes;
158             }
159              
160              
161              
162             #------------------------------------------------------------------------------
163             # Returns the list of all terminal descendants of this phrase. Similar to
164             # nodes(), but instead of Node objects returns the Phrase::Term objects, in
165             # which the nodes are wrapped.
166             #------------------------------------------------------------------------------
167             sub terminals
168             {
169 0     0 1 0 my $self = shift;
170 0 0       0 log_fatal('Dead') if($self->dead());
171 0         0 my @children = $self->children();
172 0         0 my @terminals;
173 0         0 foreach my $child (@children)
174             {
175 0         0 my @child_terminals = $child->terminals();
176 0         0 push(@terminals, @child_terminals);
177             }
178 0 0       0 return $self->_order_required(@_) ? $self->order_phrases(@terminals) : @terminals;
179             }
180              
181              
182              
183             #------------------------------------------------------------------------------
184             # Returns the list of dependents of the phrase. The only difference from the
185             # getter _dependents_ref() is that the getter returns a reference to the array
186             # of dependents, while this method returns a list of dependents, hence it is
187             # more similar to the other methods that return lists of children.
188             #------------------------------------------------------------------------------
189             sub dependents
190             {
191 7     7 1 18 my $self = shift;
192 7 50       216 log_fatal('Dead') if($self->dead());
193 7         16 my @dependents = @{$self->_dependents_ref()};
  7         212  
194 7 50       37 return $self->_order_required(@_) ? $self->order_phrases(@dependents) : @dependents;
195             }
196              
197              
198              
199             #------------------------------------------------------------------------------
200             # Returns the list of non-head children of the phrase. By default these are the
201             # dependents. However, in special nonterminal phrases there may be children
202             # that are neither head nor dependents.
203             #------------------------------------------------------------------------------
204             sub nonhead_children
205             {
206 1     1 1 5 my $self = shift;
207 1 50       39 log_fatal('Dead') if($self->dead());
208 1         9 return $self->dependents(@_);
209             }
210              
211              
212              
213             #------------------------------------------------------------------------------
214             # Returns the list of the children of the phrase that are not dependents. By
215             # default this is just the head child. However, in special nonterminal phrases
216             # there may be other children that have a special status but are not the
217             # current head.
218             #------------------------------------------------------------------------------
219             sub core_children
220             {
221 4     4 1 10 my $self = shift;
222 4 50       122 log_fatal('Dead') if($self->dead());
223 4         120 my @children = ($self->head());
224 4         37 return @children;
225             }
226              
227              
228              
229             #------------------------------------------------------------------------------
230             # Returns the list of all children of the phrase, i.e. core children and
231             # dependents.
232             #------------------------------------------------------------------------------
233             sub children
234             {
235 3     3 1 10 my $self = shift;
236 3 50       112 log_fatal('Dead') if($self->dead());
237 3         28 my @children = ($self->core_children(), $self->dependents());
238 3 50       9 return $self->_order_required(@_) ? $self->order_phrases(@children) : @children;
239             }
240              
241              
242              
243             #------------------------------------------------------------------------------
244             # Returns the head node of the phrase. For nonterminal phrases this recursively
245             # returns head node of their head child.
246             #------------------------------------------------------------------------------
247             sub node
248             {
249 9     9 1 21 my $self = shift;
250 9 50       307 log_fatal('Dead') if($self->dead());
251 9         182 return $self->head()->node();
252             }
253              
254              
255              
256             #------------------------------------------------------------------------------
257             # Returns the type of the dependency relation of the phrase to the governing
258             # phrase. A general nonterminal phrase has the same deprel as its head child.
259             #------------------------------------------------------------------------------
260             sub deprel
261             {
262 0     0 1 0 my $self = shift;
263 0 0       0 log_fatal('Dead') if($self->dead());
264 0         0 return $self->head()->deprel();
265             }
266              
267              
268              
269             #------------------------------------------------------------------------------
270             # Sets a new type of the dependency relation of the phrase to the governing
271             # phrase. For nonterminal phrases the label is propagated to one (or several)
272             # of their children. It is not propagated to the underlying dependency tree
273             # (the project_dependencies() method would have to be called to achieve that).
274             #------------------------------------------------------------------------------
275             sub set_deprel
276             {
277 0     0 1 0 my $self = shift;
278 0 0       0 log_fatal('Dead') if($self->dead());
279 0         0 $self->head()->set_deprel(@_);
280             }
281              
282              
283              
284             #------------------------------------------------------------------------------
285             # Returns the deprel that should be used when the phrase tree is projected back
286             # to a dependency tree (see the method project_dependencies()). In most cases
287             # this is identical to what deprel() returns. However, for instance
288             # prepositional phrases in Prague treebanks are attached using AuxP. Their
289             # relation to the parent (returned by deprel()) is projected to the argument of
290             # the preposition.
291             #------------------------------------------------------------------------------
292             sub project_deprel
293             {
294 0     0 1 0 my $self = shift;
295 0 0       0 log_fatal('Dead') if($self->dead());
296 0         0 return $self->head()->project_deprel();
297             }
298              
299              
300              
301             #------------------------------------------------------------------------------
302             # Returns the lowest and the highest ord values of the nodes covered by this
303             # phrase (always a pair of scalar values; they will be identical for terminal
304             # phrases). Note that there is no guarantee that all nodes within the span are
305             # covered by this phrase. There may be gaps!
306             #------------------------------------------------------------------------------
307             sub span
308             {
309 0     0 1 0 my $self = shift;
310             # The phrases may overlap, thus requesting ordering of the children will not help us.
311 0         0 my @children = $self->children();
312 0         0 my ($min, $max);
313 0         0 foreach my $child (@children)
314             {
315 0         0 my ($left, $right) = $child->span();
316 0 0 0     0 if(!defined($min) || $left < $min)
317             {
318 0         0 $min = $left;
319             }
320 0 0 0     0 if(!defined($max) || $right > $max)
321             {
322 0         0 $max = $right;
323             }
324             }
325 0         0 return ($min, $max);
326             }
327              
328              
329              
330             #------------------------------------------------------------------------------
331             # Adds a child phrase (subphrase). By default, the new child will not be head,
332             # it will be an ordinary modifier. This is a private method that should be
333             # called only from the public method Phrase::set_parent().
334             #------------------------------------------------------------------------------
335             sub _add_child
336             {
337 2 50   2   10 log_fatal('Incorrect number of arguments') if(scalar(@_) != 2);
338 2         6 my $self = shift;
339 2         4 my $new_child = shift; # Treex::Core::Phrase
340 2 50       71 log_fatal('Dead') if($self->dead());
341             # If we are called correctly from Phrase::set_parent(), then the child already knows about us.
342 2 50 33     63 if(!defined($new_child) || !defined($new_child->parent()) || $new_child->parent() != $self)
      33        
343             {
344 0         0 log_fatal("The child must point to the parent first. This private method must be called only from Phrase::set_parent()");
345             }
346 2         64 my $nhc = $self->_dependents_ref();
347 2         6 push(@{$nhc}, $new_child);
  2         7  
348             }
349              
350              
351              
352             #------------------------------------------------------------------------------
353             # Removes a child phrase (subphrase). Only non-head children can be removed
354             # this way. If the head is to be removed, it must be first replaced by another
355             # child; or the whole nonterminal phrase must be destroyed. This is a private
356             # method that should be called only from the public method Phrase::set_parent().
357             #------------------------------------------------------------------------------
358             sub _remove_child
359             {
360 1 50   1   5 log_fatal('Incorrect number of arguments') if(scalar(@_) != 2);
361 1         3 my $self = shift;
362 1         2 my $child = shift; # Treex::Core::Phrase
363 1 50       32 log_fatal('Dead') if($self->dead());
364 1 50 33     32 if(!defined($child) || !defined($child->parent()) || $child->parent() != $self)
      33        
365             {
366 0         0 log_fatal("The child does not think I'm its parent");
367             }
368 1 50   1   12 if(any {$_ == $child} ($self->core_children()))
  1         5  
369             {
370 0         0 log_warn($self->as_string());
371 0         0 log_warn($child->as_string());
372 0         0 log_fatal("Cannot remove the head child or any other core child");
373             }
374 1         33 my $nhc = $self->_dependents_ref();
375 1         3 my $found = 0;
376 1         3 for(my $i = 0; $i <= $#{$nhc}; $i++)
  1         6  
377             {
378 1 50       5 if($nhc->[$i] == $child)
379             {
380 1         3 $found = 1;
381 1         2 splice(@{$nhc}, $i, 1);
  1         5  
382 1         3 last;
383             }
384             }
385 1 50       6 if(!$found)
386             {
387 0           log_fatal("Could not find the phrase among my non-head children");
388             }
389             }
390              
391              
392              
393             #------------------------------------------------------------------------------
394             # Common validation for replace_child() and replace_core_child(). May throw
395             # exceptions.
396             #------------------------------------------------------------------------------
397             sub _check_old_new_child
398             {
399 0     0     my $self = shift;
400 0           my $old_child = shift; # Treex::Core::Phrase
401 0           my $new_child = shift; # Treex::Core::Phrase
402 0 0         log_fatal('Dead') if($self->dead());
403 0 0 0       if(!defined($old_child) || !defined($old_child->parent()) || $old_child->parent() != $self)
      0        
404             {
405 0           log_fatal("The child to be replaced does not think I'm its parent");
406             }
407 0 0         if(!defined($new_child))
408             {
409 0           log_fatal("The replacement child is not defined");
410             }
411 0 0         if(defined($new_child->parent()))
412             {
413 0 0         if($new_child->parent() == $self)
414             {
415 0           log_fatal("The replacement already is my child");
416             }
417             else
418             {
419 0           log_fatal("The replacement child already has a parent");
420             }
421             }
422             }
423              
424              
425              
426             #------------------------------------------------------------------------------
427             # Replaces a child by another phrase. This method will work with any child,
428             # including the core children. The core children cannot be undefined but if we
429             # immediately replace them by a new child, the phrase will remain valid.
430             #------------------------------------------------------------------------------
431             sub replace_child
432             {
433 0     0 1   my $self = shift;
434 0           my $old_child = shift; # Treex::Core::Phrase
435 0           my $new_child = shift; # Treex::Core::Phrase
436 0 0         log_fatal('Dead') if($self->dead());
437 0           $self->_check_old_new_child($old_child, $new_child);
438             # If the child is dependent, we can do it here. If it is a core child,
439             # we need a subclass to decide what to do.
440 0           my $nhc = $self->_dependents_ref();
441 0           for(my $i = 0; $i <= $#{$nhc}; $i++)
  0            
442             {
443 0 0         if($nhc->[$i] == $old_child)
444             {
445 0           splice(@{$nhc}, $i, 1, $new_child);
  0            
446 0           $old_child->_set_parent(undef);
447 0           $new_child->_set_parent($self);
448 0           return;
449             }
450             }
451             # If we are here, we did not find the old child among the dependents.
452             # Thus it has to be a core child.
453 0           $self->replace_core_child($old_child, $new_child);
454             }
455              
456              
457              
458             #------------------------------------------------------------------------------
459             # Replaces a core child by another phrase. This is an abstract method that must
460             # be defined in every derived class.
461             #------------------------------------------------------------------------------
462             sub replace_core_child
463             {
464 0     0 1   my $self = shift;
465 0           log_fatal("The replace_core_child() method is not implemented");
466             }
467              
468              
469              
470             #------------------------------------------------------------------------------
471             # Detaches all children (including core children) and then marks itself as dead
472             # so that it cannot be used any more. This method should be called when we want
473             # to replace a non-terminal phrase by a new phrase of a different class. The
474             # method will not detach the dying phrase from its parent! That could kill the
475             # parent too (if the dying phrase is a core child) but we probably want the
476             # parent to survive and to replace the dying child by a new phrase we create.
477             # However, it is the caller's responsibility to modify the parent immediately.
478             #------------------------------------------------------------------------------
479             sub detach_children_and_die
480             {
481 0     0 1   my $self = shift;
482             # Visit all children and tell them they have no parent now. We cannot use
483             # the public method set_parent() because it will call our method _remove_child()
484             # and that only works for non-core children. (Besides, we want to destroy
485             # our links to children all at once. The _remove_child() method would be
486             # unnecessarily slow for that purpose, as it works with only one child and
487             # has to find it first.) Thus we will directly modify the one-way link via
488             # _set_parent().
489 0           my @children = $self->children();
490 0           foreach my $child (@children)
491             {
492 0           $child->_set_parent(undef);
493             }
494             # Remove the references leading from this phrase to its dependents.
495 0           splice(@{$self->_dependents_ref()});
  0            
496             # We cannot remove the references to the core children because we do not
497             # know how many core children there are and how they are accessed, and
498             # they cannot be undefined anyway. However, we will mark this phrase as
499             # dead, so it cannot be used until it is physically destroyed by Perl.
500 0           $self->_set_dead(1);
501 0           return @children;
502             }
503              
504              
505              
506             #------------------------------------------------------------------------------
507             # Projects dependencies between the head and the dependents back to the
508             # underlying dependency structure.
509             #------------------------------------------------------------------------------
510             sub project_dependencies
511             {
512 0     0 1   my $self = shift;
513 0 0         log_fatal('Dead') if($self->dead());
514             # Recursion first, we work bottom-up.
515 0           my @children = $self->children();
516 0           foreach my $child (@children)
517             {
518 0           $child->project_dependencies();
519             }
520 0           my $head_node = $self->node();
521 0           my @dependents = $self->nonhead_children();
522 0           foreach my $dependent (@dependents)
523             {
524 0           my $dep_node = $dependent->node();
525 0           $dep_node->set_parent($head_node);
526 0           $dep_node->set_deprel($dependent->project_deprel());
527             }
528             }
529              
530              
531              
532             #------------------------------------------------------------------------------
533             # Returns a textual representation of the phrase and all subphrases. Useful for
534             # debugging.
535             #------------------------------------------------------------------------------
536             sub as_string
537             {
538 0     0 1   my $self = shift;
539 0           my @core_children = $self->core_children('ordered' => 1);
540 0           my $core = 'CORE '.join(', ', map {$_->as_string()} (@core_children));
  0            
541 0           my @dependents = $self->dependents('ordered' => 1);
542 0           my $deps = join(', ', map {$_->as_string()} (@dependents));
  0            
543 0 0         $deps = 'DEPS '.$deps if($deps);
544 0           my $subtree = join(' ', ($core, $deps));
545 0 0         $subtree .= ' _M' if($self->is_member());
546 0           return "(BNT $subtree)";
547             }
548              
549              
550              
551             __PACKAGE__->meta->make_immutable();
552              
553             1;
554              
555              
556              
557             =for Pod::Coverage BUILD
558              
559             =encoding utf-8
560              
561             =head1 NAME
562              
563             Treex::Core::Phrase::BaseNTerm
564              
565             =head1 VERSION
566              
567             version 2.20210102
568              
569             =head1 DESCRIPTION
570              
571             C<BaseNTerm> is an abstract class that defines the basic interface of
572             nonterminal phrases. The general nonterminal phrase, C<NTerm>, is derived from
573             C<BaseNTerm>. So are some special cases of nonterminals, such as C<PP>.
574             (They cannot be derived from C<NTerm> because they implement certain parts
575             of the interface differently.)
576              
577             See also L<Treex::Core::Phrase> and L<Treex::Core::Phrase::NTerm>.
578              
579             =head1 ATTRIBUTES
580              
581             =over
582              
583             =item _dependents_ref
584              
585             Reference to array of sub-C<Phrase>s (children) of this phrase that do not belong to the
586             core of the phrase. By default the core contains only the head child. However,
587             some specialized subclasses may define a larger core where two or more
588             children have a special status, but only one of them can be the head.
589              
590             =item dead
591              
592             Most non-terminal phrases cannot exist without children.
593             If we want to change the class of a non-terminal phrase, we construct
594             an object of the new class and move the children there from the old
595             one. But the old object will not be physically destroyed until it
596             gets out of scope. So we will mark it as “dead”. If anyone tries to
597             use the dead object, an exception will be thrown.
598              
599             =back
600              
601             =head1 METHODS
602              
603             =over
604              
605             =item head
606              
607             A sub-C<Phrase> of this phrase that is at the moment considered the head phrase (in the sense of dependency syntax).
608             A general C<NTerm> phrase just has a C<head> attribute.
609             Special cases of nonterminals may have multiple children with special behavior,
610             and they may choose which one of these children shall be head under the current
611             annotation style.
612              
613             =item nodes
614              
615             Returns the list of all nodes covered by the phrase, i.e. the head node of
616             this phrase and of all its descendants.
617              
618             =item terminals
619              
620             Returns the list of all terminal descendants of this phrase. Similar to
621             C<nodes()>, but instead of C<Node> objects returns the C<Phrase::Term> objects, in
622             which the nodes are wrapped.
623              
624             =item dependents
625              
626             Returns the list of dependents of the phrase. The only difference from the
627             getter C<_dependents_ref()> is that the getter returns a reference to the array
628             of dependents, while this method returns a list of dependents. Hence this method is
629             more similar to the other methods that return lists of children.
630              
631             =item nonhead_children
632              
633             Returns the list of non-head children of the phrase. By default these are the
634             dependents. However, in special nonterminal phrases there may be children
635             that are neither head nor dependents.
636              
637             =item core_children
638              
639             Returns the list of the children of the phrase that are not dependents. By default this
640             is just the head child. However, in specialized nonterminal phrases there may be
641             other children that have a special status but are not the current head.
642              
643             =item children
644              
645             Returns the list of all children of the phrase, i.e. core children and
646             dependents.
647              
648             =item order_phrases
649              
650             Sorts a list of phrases according to the word order of their head nodes.
651             All methods that return lists of children (C<dependents()>, C<nonhead_children()>,
652             C<core_children()>, C<children()>) can be asked to sort the list using this
653             method. The following calling styles are possible:
654              
655             my @ordered_children = $phrase->children({'ordered' => 1});
656             my @ordered_children = $phrase->children('ordered' => 1);
657             my @ordered_children = $phrase->children('ordered');
658              
659             =item deprel
660              
661             Returns the type of the dependency relation of the phrase to the governing
662             phrase. A general nonterminal phrase has the same deprel as its head child.
663              
664             =item set_deprel
665              
666             Sets a new type of the dependency relation of the phrase to the governing
667             phrase. For nonterminal phrases the label is propagated to one (or several)
668             of their children. It is not propagated to the underlying dependency tree
669             (the C<project_dependencies()> method would have to be called to achieve that).
670              
671             =item span
672              
673             Returns the lowest and the highest ord values of the nodes covered by this
674             phrase (always a pair of scalar values; they will be identical for terminal
675             phrases). Note that there is no guarantee that all nodes within the span are
676             covered by this phrase. There may be gaps!
677              
678             =item replace_child
679              
680             $nonterminal->replace_child ($old_child, $new_child);
681              
682             Replaces a child by another phrase. This method will work with any child,
683             including the core children. The core children cannot be undefined but if we
684             immediately replace them by a new child, the phrase will remain valid.
685              
686             =item replace_core_child
687              
688             Same as C<replace_child()> but used with core children only. If we know that we
689             are replacing a core child, it is more efficient to call directly this method.
690             If we do not know what type of child we have, we can call the more general
691             C<replace_child()> and it will decide.
692              
693             C<BaseNTerm::replace_core_child()> is an abstract method that must be defined
694             in every derived class.
695              
696             =item detach_children_and_die
697              
698             my $parent = $phrase->parent();
699             my $replacement = new Treex::Core::Phrase::PP (...);
700             my @children = $phrase->detach_children_and_die();
701             $parent->replace_child ($phrase, $replacement);
702              
703             Detaches all children (including core children) and then marks itself as dead
704             so that it cannot be used any more. This method should be called when we want
705             to replace a non-terminal phrase by a new phrase of a different class. The
706             method will not detach the dying phrase from its parent! That could kill the
707             parent too (if the dying phrase is a core child) but we probably want the
708             parent to survive and to replace the dying child by a new phrase we create.
709             However, it is the caller's responsibility to modify the parent immediately.
710              
711             =item project_dependencies
712              
713             Recursively projects dependencies between the head and the dependents back to the
714             underlying dependency structure.
715              
716             =item as_string
717              
718             Returns a textual representation of the phrase and all subphrases. Useful for
719             debugging.
720              
721             =back
722              
723             =head1 AUTHORS
724              
725             Daniel Zeman <zeman@ufal.mff.cuni.cz>
726              
727             =head1 COPYRIGHT AND LICENSE
728              
729             Copyright © 2013, 2015 by Institute of Formal and Applied Linguistics, Charles University in Prague
730             This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.