line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Treex::Core::Node::EffectiveRelations; |
2
|
|
|
|
|
|
|
$Treex::Core::Node::EffectiveRelations::VERSION = '2.20210102'; |
3
|
24
|
|
|
24
|
|
18937
|
use Moose::Role; |
|
24
|
|
|
|
|
68
|
|
|
24
|
|
|
|
|
208
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
# with Moose >= 2.00, this must be present also in roles |
6
|
24
|
|
|
24
|
|
131812
|
use MooseX::SemiAffordanceAccessor; |
|
24
|
|
|
|
|
69
|
|
|
24
|
|
|
|
|
229
|
|
7
|
24
|
|
|
24
|
|
65155
|
use Treex::Core::Log; |
|
24
|
|
|
|
|
70
|
|
|
24
|
|
|
|
|
39215
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
has is_member => ( |
10
|
|
|
|
|
|
|
is => 'rw', |
11
|
|
|
|
|
|
|
isa => 'Bool', |
12
|
|
|
|
|
|
|
documentation => 'Is this node a member of a coordination (i.e. conjunct) or apposition?', |
13
|
|
|
|
|
|
|
); |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
# Shared modifiers of coordinations can be distinguished in PDT style |
16
|
|
|
|
|
|
|
# just based on the fact they are hanged on the conjunction (coord. head). |
17
|
|
|
|
|
|
|
# However, in other styles (e.g. Stanford) this attribute might be useful. |
18
|
|
|
|
|
|
|
has is_shared_modifier => ( |
19
|
|
|
|
|
|
|
is => 'rw', |
20
|
|
|
|
|
|
|
isa => 'Bool', |
21
|
|
|
|
|
|
|
documentation => 'Is this node a shared modifier of a coordination?', |
22
|
|
|
|
|
|
|
); |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
requires 'is_coap_root'; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# Implementation details: |
27
|
|
|
|
|
|
|
# Members of a coordination can be distinguished from shared modifiers |
28
|
|
|
|
|
|
|
# according to the attribute is_member. The only problem is when some |
29
|
|
|
|
|
|
|
# members are hanged on prepositions(afun=AuxP) or subord. conjunctions(AuxC). |
30
|
|
|
|
|
|
|
# The PDT style is that Aux[CP] nodes can never have is_member=1, resulting in |
31
|
|
|
|
|
|
|
# e.g. "It was in(parent=and) Prague(parent=in,is_member=1) |
32
|
|
|
|
|
|
|
# and(parent=was) in(parent=and) London(parent=in,is_member=1)." |
33
|
|
|
|
|
|
|
# The style adpoted in Treex is that members have always is_member=1 |
34
|
|
|
|
|
|
|
# no matter what afun they have. This results in: |
35
|
|
|
|
|
|
|
# "It was in(parent=and,is_member=1) Prague(parent=in) |
36
|
|
|
|
|
|
|
# and(parent=was) in(parent=and,is_member=1) London(parent=in)." |
37
|
|
|
|
|
|
|
# Both annotation styles have their pros and cons. |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
sub get_echildren { |
40
|
12
|
|
|
12
|
1
|
5566
|
my ( $self, $arg_ref ) = @_; |
41
|
12
|
50
|
|
|
|
63
|
if ( !defined $arg_ref ) { |
42
|
0
|
|
|
|
|
0
|
$arg_ref = {}; |
43
|
|
|
|
|
|
|
} |
44
|
12
|
50
|
|
|
|
38
|
log_fatal('Incorrect number of arguments') if @_ > 2; |
45
|
|
|
|
|
|
|
|
46
|
12
|
|
|
|
|
24
|
my @echildren; |
47
|
12
|
100
|
|
|
|
40
|
if ( $self->_can_apply_eff($arg_ref) ) { |
48
|
|
|
|
|
|
|
# 1) Get my own effective children (i.e. I am their only eff. parent). |
49
|
|
|
|
|
|
|
# These are in my subtree. |
50
|
9
|
|
|
|
|
32
|
@echildren = $self->_get_my_own_echildren($arg_ref); |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
# 2) Add shared effective children |
53
|
|
|
|
|
|
|
# (i.e. I am their eff. parent, but not the only one). |
54
|
|
|
|
|
|
|
# This can happen only if I am member of a coordination |
55
|
|
|
|
|
|
|
# and these eff. children are shared modifiers of the coordination. |
56
|
9
|
|
|
|
|
36
|
push @echildren, $self->_get_shared_echildren($arg_ref); |
57
|
|
|
|
|
|
|
} else { |
58
|
3
|
|
|
|
|
15
|
@echildren = $self->get_children(); |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# 3) Process eventual switches (ordered=>1, add_self=>1,...) |
62
|
|
|
|
|
|
|
#return @echildren if !$arg_ref; TODO this cannot happen now, see $arg_ref = {} if !defined $arg_ref; |
63
|
12
|
|
|
|
|
47
|
delete $arg_ref->{dive}; |
64
|
12
|
|
|
|
|
26
|
delete $arg_ref->{or_topological}; |
65
|
12
|
|
|
|
|
22
|
delete $arg_ref->{ignore_incorrect_tree_structure}; |
66
|
12
|
|
|
|
|
61
|
return $self->_process_switches( $arg_ref, @echildren ); |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub get_eparents { |
70
|
10
|
|
|
10
|
1
|
5396
|
my ( $self, $arg_ref ) = @_; |
71
|
10
|
50
|
|
|
|
34
|
if ( !defined $arg_ref ) { |
72
|
0
|
|
|
|
|
0
|
$arg_ref = {}; |
73
|
|
|
|
|
|
|
} |
74
|
10
|
50
|
|
|
|
33
|
log_fatal('Incorrect number of arguments') if @_ > 2; |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
# Get effective parents |
77
|
10
|
50
|
|
|
|
34
|
my @eparents = $self->_can_apply_eff($arg_ref) ? |
78
|
|
|
|
|
|
|
$self->_get_eparents($arg_ref) : ($self->get_parent()); |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# Process eventual switches (ordered=>1, add_self=>1,...) |
81
|
10
|
|
|
|
|
33
|
delete $arg_ref->{dive}; |
82
|
10
|
|
|
|
|
21
|
delete $arg_ref->{or_topological}; |
83
|
10
|
|
|
|
|
19
|
delete $arg_ref->{ignore_incorrect_tree_structure}; |
84
|
10
|
|
|
|
|
41
|
return $self->_process_switches( $arg_ref, @eparents ); |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
sub _get_eparents { |
88
|
10
|
|
|
10
|
|
27
|
my ( $self, $arg_ref ) = @_; |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# 0) Check if there is a topological parent. |
91
|
|
|
|
|
|
|
# Otherwise, there is no chance getting effective parents. |
92
|
10
|
50
|
|
|
|
40
|
if ( !$self->get_parent() ) { |
93
|
0
|
|
|
|
|
0
|
my $id = $self->id; |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
#TODO: log_fatal if !$robust |
96
|
0
|
|
|
|
|
0
|
log_warn( "The node $id has no effective nor topological parent, using the root", 1 ); |
97
|
0
|
|
|
|
|
0
|
return $self->get_root(); |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
# 1) If $self is a member of a coordination/aposition, |
101
|
|
|
|
|
|
|
# get the highest node representing $self -- i.e. the coord/apos root. |
102
|
|
|
|
|
|
|
# Otherwise, let $node be $self. |
103
|
10
|
|
66
|
|
|
74
|
my $node = $self->_get_transitive_coap_root($arg_ref) || $self; |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# 2) Get the parent |
106
|
10
|
50
|
|
|
|
31
|
$node = $node->get_parent() or return $self->_fallback_parent($arg_ref); |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
# 3) If it is a node to be dived, look above for the first non-dive ancestor. |
109
|
10
|
|
|
|
|
56
|
while ( $arg_ref->{dive}->($node) ) { |
110
|
0
|
0
|
|
|
|
0
|
$node = $node->get_parent() or return $self->_fallback_parent($arg_ref); |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
# If $node is not a head of a coordination/aposition, |
114
|
|
|
|
|
|
|
# it is the effective parent we are looking for. |
115
|
10
|
100
|
|
|
|
33
|
return $node if !$node->is_coap_root(); |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# Otherwise, there can be more than one effective parent. |
118
|
|
|
|
|
|
|
# All effective parents (of $self) are shared modifiers |
119
|
|
|
|
|
|
|
# of the coordination rooted in $node. |
120
|
2
|
|
|
|
|
11
|
my @eff = $node->get_coap_members($arg_ref); |
121
|
2
|
50
|
|
|
|
24
|
return @eff if @eff; |
122
|
|
|
|
|
|
|
|
123
|
0
|
|
|
|
|
0
|
return $self->_fallback_parent($arg_ref); |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# --- Utility methods for get_echildren and get_eparents |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
sub _is_auxCP { |
129
|
58
|
|
|
58
|
|
102
|
my ($self) = @_; |
130
|
58
|
|
100
|
|
|
1631
|
my $afun = $self->afun || ''; |
131
|
58
|
|
|
|
|
259
|
return $afun =~ /^Aux[CP]$/; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub _get_direct_coap_root { |
135
|
37
|
|
|
37
|
|
76
|
my ( $self, $arg_ref ) = @_; |
136
|
37
|
50
|
|
|
|
91
|
my $parent = $self->get_parent() or return; |
137
|
37
|
100
|
|
|
|
193
|
return $parent if $self->get_attr('is_member'); |
138
|
13
|
50
|
33
|
|
|
61
|
return if !$arg_ref->{dive} || $arg_ref->{dive}->($self); |
139
|
13
|
|
|
|
|
33
|
while ( $arg_ref->{dive}->($parent) ) { |
140
|
2
|
50
|
|
|
|
8
|
return $parent->get_parent() if $parent->get_attr('is_member'); |
141
|
0
|
0
|
|
|
|
0
|
$parent = $parent->get_parent() or return; |
142
|
|
|
|
|
|
|
} |
143
|
11
|
|
|
|
|
79
|
return; |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub _get_transitive_coap_root { |
147
|
10
|
|
|
10
|
|
23
|
my ( $self, $arg_ref ) = @_; |
148
|
10
|
100
|
|
|
|
25
|
my $root = $self->_get_direct_coap_root($arg_ref) or return; |
149
|
8
|
|
|
|
|
32
|
while ( $root->get_attr('is_member') ) { |
150
|
6
|
50
|
|
|
|
21
|
$root = $root->_get_direct_coap_root($arg_ref) or return; |
151
|
|
|
|
|
|
|
} |
152
|
8
|
|
|
|
|
22
|
return $root; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub _can_apply_eff { |
156
|
22
|
|
|
22
|
|
52
|
my ( $self, $arg_ref ) = @_; |
157
|
22
|
100
|
|
|
|
85
|
if ( !$arg_ref->{dive} ) { |
|
|
50
|
|
|
|
|
|
158
|
11
|
|
|
45
|
|
62
|
$arg_ref->{dive} = sub {0}; |
|
45
|
|
|
|
|
216
|
|
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
elsif ( $arg_ref->{dive} eq 'AuxCP' ) { |
161
|
11
|
|
|
|
|
30
|
$arg_ref->{dive} = \&_is_auxCP; |
162
|
|
|
|
|
|
|
} |
163
|
22
|
100
|
|
|
|
62
|
my $error = $arg_ref->{dive}->($self) |
|
|
100
|
|
|
|
|
|
164
|
|
|
|
|
|
|
? 'a node that is "to be dived"' |
165
|
|
|
|
|
|
|
: $self->is_coap_root() ? 'coap root' : 0; |
166
|
22
|
100
|
|
|
|
103
|
return 1 if !$error; |
167
|
3
|
50
|
|
|
|
17
|
return 0 if $arg_ref->{or_topological}; #TODO: document |
168
|
0
|
|
|
|
|
0
|
my $method_name = ( caller 1 )[3]; |
169
|
0
|
|
|
|
|
0
|
my $id = $self->id; |
170
|
0
|
|
|
|
|
0
|
log_warn( "$method_name called on $error ($id). Fallback to topological one.", 1 ); |
171
|
0
|
|
|
|
|
0
|
return 0; |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
# used only if there is an error in the tree structure, |
175
|
|
|
|
|
|
|
# eg. there is a coordination with no members or a non-root node with no parent |
176
|
|
|
|
|
|
|
sub _fallback_parent { |
177
|
0
|
|
|
0
|
|
0
|
my ( $self, $arg_ref ) = @_; |
178
|
0
|
|
|
|
|
0
|
my $id = $self->get_attr('id'); |
179
|
|
|
|
|
|
|
log_warn "The node $id has no effective parent, using the topological one." |
180
|
0
|
0
|
0
|
|
|
0
|
if ( !$arg_ref || !$arg_ref->{ignore_incorrect_tree_structure} ); |
181
|
0
|
|
|
|
|
0
|
return $self->get_parent(); |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
# Get my own effective children (i.e. I am their only eff. parent). |
185
|
|
|
|
|
|
|
sub _get_my_own_echildren { |
186
|
9
|
|
|
9
|
|
23
|
my ( $self, $arg_ref ) = @_; |
187
|
9
|
|
|
|
|
17
|
my @members = (); |
188
|
9
|
|
|
|
|
49
|
my @queue = $self->get_children(); |
189
|
9
|
|
|
|
|
32
|
while (@queue) { |
190
|
6
|
|
|
|
|
14
|
my $node = shift @queue; |
191
|
6
|
50
|
|
|
|
18
|
if ( $arg_ref->{dive}->($node) ) { |
|
|
100
|
|
|
|
|
|
192
|
0
|
|
|
|
|
0
|
push @queue, $node->get_children(); |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
elsif ( $node->is_coap_root() ) { |
195
|
3
|
|
|
|
|
16
|
push @members, $node->get_coap_members($arg_ref); |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
#push @queue, grep { $_->get_attr('is_member') } $node->get_children(); |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
else { |
200
|
3
|
|
|
|
|
14
|
push @members, $node; |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
} |
203
|
9
|
|
|
|
|
26
|
return @members; |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
# Get shared effective children |
207
|
|
|
|
|
|
|
# (i.e. I am their eff. parent but not the only one). |
208
|
|
|
|
|
|
|
sub _get_shared_echildren { |
209
|
9
|
|
|
9
|
|
22
|
my ( $self, $arg_ref ) = @_; |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
# Only members of coord/apos can have shared eff. children |
212
|
9
|
100
|
|
|
|
28
|
my $coap_root = $self->_get_direct_coap_root($arg_ref) or return (); |
213
|
6
|
|
|
|
|
19
|
my @shared_echildren = (); |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
# All shared modifiers of $coap_root are eff. children of $self. |
216
|
|
|
|
|
|
|
# We must process all possibly nested coap_roots. |
217
|
|
|
|
|
|
|
# In the first iteration, $self is one of children of $coap_root. |
218
|
|
|
|
|
|
|
# (In case of "diving", it's not $self, but its governing Aux[CP].) |
219
|
|
|
|
|
|
|
# However, it has is_member==1, so it won't get into @shared_echildren. |
220
|
|
|
|
|
|
|
# Similarly for other iterations. |
221
|
6
|
|
|
|
|
20
|
while ($coap_root) { |
222
|
|
|
|
|
|
|
push @shared_echildren, |
223
|
6
|
|
|
|
|
21
|
map { $_->get_coap_members($arg_ref) } |
224
|
12
|
|
|
|
|
41
|
grep { !$_->get_attr('is_member') } |
|
36
|
|
|
|
|
82
|
|
225
|
|
|
|
|
|
|
$coap_root->get_children(); |
226
|
12
|
|
|
|
|
37
|
$coap_root = $coap_root->_get_direct_coap_root($arg_ref); |
227
|
|
|
|
|
|
|
} |
228
|
6
|
|
|
|
|
16
|
return @shared_echildren; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
sub get_coap_members { |
232
|
19
|
|
|
19
|
1
|
1663
|
my ( $self, $arg_ref ) = @_; |
233
|
19
|
50
|
|
|
|
54
|
log_fatal('Incorrect number of arguments') if @_ > 2; |
234
|
19
|
100
|
|
|
|
63
|
return $self if !$self->is_coap_root(); |
235
|
13
|
|
|
|
|
32
|
my $direct_only = $arg_ref->{direct_only}; |
236
|
13
|
|
100
|
13
|
|
59
|
my $dive = $arg_ref->{dive} || sub {0}; |
|
13
|
|
|
|
|
44
|
|
237
|
13
|
100
|
|
|
|
43
|
if ( $dive eq 'AuxCP' ) { $dive = \&_is_auxCP; } |
|
4
|
|
|
|
|
13
|
|
238
|
13
|
|
|
|
|
28
|
my @members = (); |
239
|
|
|
|
|
|
|
|
240
|
13
|
|
|
|
|
56
|
my @queue = grep { $_->is_member } $self->get_children(); |
|
38
|
|
|
|
|
1123
|
|
241
|
13
|
|
|
|
|
48
|
while (@queue) { |
242
|
52
|
|
|
|
|
123
|
my $node = shift @queue; |
243
|
52
|
100
|
100
|
|
|
131
|
if ( $dive->($node) ) { |
|
|
100
|
|
|
|
|
|
244
|
5
|
|
|
|
|
24
|
push @queue, $node->get_children(); |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
elsif ( !$direct_only && $node->is_coap_root() ) { |
247
|
5
|
|
|
|
|
23
|
push @queue, grep { $_->is_member } $node->get_children(); |
|
20
|
|
|
|
|
561
|
|
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
else { |
250
|
42
|
|
|
|
|
124
|
push @members, $node; |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
} |
253
|
13
|
|
|
|
|
97
|
return @members; |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
|
256
|
24
|
|
|
24
|
|
266
|
use List::MoreUtils "any"; |
|
24
|
|
|
|
|
70
|
|
|
24
|
|
|
|
|
318
|
|
257
|
|
|
|
|
|
|
sub is_echild_of { |
258
|
0
|
|
|
0
|
0
|
|
my ($potential_echild, $eparent, $arg_ref) = @_; |
259
|
|
|
|
|
|
|
|
260
|
0
|
|
|
|
|
|
my @echildren = $eparent->get_echildren( $arg_ref ); |
261
|
0
|
|
|
0
|
|
|
return any { $_ == $potential_echild } @echildren; |
|
0
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
my @eff_args = qw(dive or_topological ignore_incorrect_tree_structure); |
265
|
|
|
|
|
|
|
# Remove args relevant only to eff relations from arg_ref and return them |
266
|
|
|
|
|
|
|
sub _extract_eff_args { |
267
|
0
|
|
|
0
|
|
|
my ($self, $arg_ref) = @_; |
268
|
|
|
|
|
|
|
|
269
|
0
|
|
|
|
|
|
my $eff_arg_ref = {}; |
270
|
0
|
|
|
|
|
|
foreach my $eff_arg (@eff_args) { |
271
|
0
|
0
|
|
|
|
|
if (defined $arg_ref->{$eff_arg}) { |
272
|
0
|
|
|
|
|
|
$eff_arg_ref->{$eff_arg} = $arg_ref->{$eff_arg}; |
273
|
0
|
|
|
|
|
|
delete $arg_ref->{$eff_arg}; |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
|
277
|
0
|
|
|
|
|
|
return $eff_arg_ref; |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
sub get_esiblings { |
281
|
0
|
|
|
0
|
0
|
|
my ( $self, $arg_ref ) = @_; |
282
|
0
|
0
|
|
|
|
|
log_fatal('Incorrect number of arguments') if @_ > 2; |
283
|
0
|
0
|
|
|
|
|
if ( !defined $arg_ref ) { |
284
|
0
|
|
|
|
|
|
$arg_ref = {}; |
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
|
287
|
0
|
|
|
|
|
|
my $eff_arg_ref = $self->_extract_eff_args($arg_ref); |
288
|
|
|
|
|
|
|
|
289
|
0
|
|
|
|
|
|
my @eparents = $self->get_eparents($eff_arg_ref); |
290
|
|
|
|
|
|
|
|
291
|
0
|
|
|
|
|
|
my %esiblings_hash; |
292
|
0
|
|
|
|
|
|
foreach my $eparent (@eparents) { |
293
|
0
|
|
|
|
|
|
my @esiblings = grep { $_ ne $self } $eparent->get_echildren($eff_arg_ref); |
|
0
|
|
|
|
|
|
|
294
|
0
|
|
|
|
|
|
foreach my $esibling (@esiblings) { |
295
|
0
|
|
|
|
|
|
$esiblings_hash{$esibling->id} = $esibling; |
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
} |
298
|
0
|
|
|
|
|
|
my @esiblings = values %esiblings_hash; |
299
|
|
|
|
|
|
|
|
300
|
0
|
|
|
|
|
|
return $self->_process_switches($arg_ref, @esiblings); |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
1; |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
__END__ |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
=encoding utf-8 |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
=head1 NAME |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
Treex::Core::Node::EffectiveRelations |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
=head1 VERSION |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
version 2.20210102 |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
=head1 DESCRIPTION |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
Moose role for nodes with a notion of so called |
320
|
|
|
|
|
|
|
I<effective> parents and I<effective> children. |
321
|
|
|
|
|
|
|
This notion is used both |
322
|
|
|
|
|
|
|
on the a-layer (L<Treex::Core::Node::A>) and |
323
|
|
|
|
|
|
|
on the t-layer (L<Treex::Core::Node::T>). |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
TODO: explain it, some examples, reference to PDT manual |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
Eg. in the sentence "Martin and Rudolph came", the tree structure is |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
came(and(Martin,Rudolph)) |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
where "and" is a head of a coordination with members "Martin" and "Rudolph". |
332
|
|
|
|
|
|
|
See what the methods C<get_children>, C<get_echildren>, C<get_parent> |
333
|
|
|
|
|
|
|
and C<get_eparents> return when called on various nodes |
334
|
|
|
|
|
|
|
(some pseudocode used for better readability): |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
# CHILDREN AND EFFECTIVE CHILDREN |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
"came"->get_children() |
340
|
|
|
|
|
|
|
# returns "and" |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
"came"->get_echildren() |
343
|
|
|
|
|
|
|
# returns ("Martin", "Rudolph") |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
"and"->get_children() |
346
|
|
|
|
|
|
|
# returns ("Martin", "Rudolph") |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
"and"->get_echildren() |
349
|
|
|
|
|
|
|
# returns ("Martin", "Rudolph") and issues a warning: |
350
|
|
|
|
|
|
|
# get_echildren called on coap root ([id_of_and]). Fallback to topological one. |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
"and"->get_echildren({or_topological => 1}) |
353
|
|
|
|
|
|
|
# returns ("Martin", "Rudolph") with no warning |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
# PARENTS AND EFFECTIVE PARENTS |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
"Rudolph"->get_parent() |
359
|
|
|
|
|
|
|
# returns "and" |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
"Rudolph"->get_eparents() |
362
|
|
|
|
|
|
|
# returns "came" |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
"and"->get_parent() |
365
|
|
|
|
|
|
|
# returns "came" |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
"and"->get_eparents() |
368
|
|
|
|
|
|
|
# returns "came" and issues a warning: |
369
|
|
|
|
|
|
|
# get_eparents called on coap root ([id_of_and]). Fallback to topological one. |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
"and"->get_eparents({or_topological => 1}) |
372
|
|
|
|
|
|
|
# returns "came" with no warning |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
Note that to skip prepositions and subordinating conjunctions on the a-layer, |
376
|
|
|
|
|
|
|
you must use option C<dive>, e.g.: |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
my $eff_children = $node->get_echildren({dive=>'AuxCP'}); |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
Methods C<get_eparents> and C<get_echildren> produce a warning |
381
|
|
|
|
|
|
|
"C<called on coap root ($id). Fallback to topological one.>" |
382
|
|
|
|
|
|
|
when called on a root of coordination or apposition, |
383
|
|
|
|
|
|
|
because effective children/parents are not properly defined in this case. |
384
|
|
|
|
|
|
|
This warning can be supressed by option C<or_topological>. |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
=head1 METHODS |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
=over |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
=item my @effective_children = $node->get_echildren($arg_ref?) |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
Returns a list of effective children of the C<$node>. It means that |
393
|
|
|
|
|
|
|
a) instead of coordination/aposition heads, their members are returned |
394
|
|
|
|
|
|
|
b) shared modifiers of a coord/apos (technically hanged on the head of coord/apos) |
395
|
|
|
|
|
|
|
count as effective children of the members. |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
OPTIONS: |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
=over |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
=item dive=>$sub_ref |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
Using C<dive>, you can define nodes to be skipped (or I<dived>). |
404
|
|
|
|
|
|
|
C<dive> is a reference to a subroutine that decides |
405
|
|
|
|
|
|
|
whether the given node should be skipped or not. |
406
|
|
|
|
|
|
|
Typically this is used for prepositions and subord. conjunctions on a-layer. |
407
|
|
|
|
|
|
|
You can set C<dive> to the string C<AuxCP> which is a shortcut |
408
|
|
|
|
|
|
|
for C<sub {my $self=shift;return $self->afun =~ /^Aux[CP]$/;}>. |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
=item or_topological |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
If the notion of effective child is not defined |
413
|
|
|
|
|
|
|
(if C<$node> is a head of coordination), |
414
|
|
|
|
|
|
|
return the topological children without warnings. |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
=item ordered, add_self, following_only, preceding_only, first_only, last_only |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
You can specify the same options as in |
419
|
|
|
|
|
|
|
L<Treex::Core::Node::get_children()|Treex::Core::Node/get_children>. |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
=back |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
=item my @effective_parents = $node->get_eparents($arg_ref?) |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
Returns a list of effective parents of the C<$node>. |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
OPTIONS |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
=over |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
=item dive |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
see L<get_echildren> |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
=item or_topological |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
If the notion of effective parent is not defined |
439
|
|
|
|
|
|
|
(if C<$node> is a head of coordination), |
440
|
|
|
|
|
|
|
return the topological parent without warnings. |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
=item ignore_incorrect_tree_structure |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
If there is an error in the tree structure, |
445
|
|
|
|
|
|
|
eg. there is a coordination with no members or a non-root node with no parent, |
446
|
|
|
|
|
|
|
a warning is issued |
447
|
|
|
|
|
|
|
(C<The node [node_id] has no effective parent, using the topological one.>). |
448
|
|
|
|
|
|
|
This option supresses the warning. |
449
|
|
|
|
|
|
|
Use thoughtfully (preferably do not use at all). |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
=item ordered, add_self, following_only, preceding_only, first_only, last_only |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
You can specify the same options as in |
454
|
|
|
|
|
|
|
L<Treex::Core::Node::get_children()|Treex::Core::Node/get_children>. |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
=back |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
=item $node->get_coap_members($arg_ref?) |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
If the node is a coordination/apposition head (see |
463
|
|
|
|
|
|
|
L<Node::A::is_coap_root()|Node::A/is_coap_root> and |
464
|
|
|
|
|
|
|
L<Node::T::is_coap_root()|Node::T/is_coap_root>) a list of all coordinated |
465
|
|
|
|
|
|
|
members is returned. Otherwise, the node itself is returned. |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
OPTIONS |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
=over |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
=item direct_only |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
In case of nested coordinations return only "first-level" members. |
474
|
|
|
|
|
|
|
The default is to return I<transitive> members. |
475
|
|
|
|
|
|
|
For example "(A and B) or C": |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
$or->get_coap_members(); # returns A,B,C |
478
|
|
|
|
|
|
|
$or->get_coap_members({direct_only=>1}); # returns and,C |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
=item dive |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
see L<get_echildren> |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
=back |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
=back |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
=head1 AUTHOR |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
Martin Popel <popel@ufal.mff.cuni.cz> |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
Copyright © 2011 by Institute of Formal and Applied Linguistics, Charles University in Prague |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. |