-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathzakaz.pm
206 lines (188 loc) · 7.63 KB
/
zakaz.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
package zakaz;
use utf8;
#------------------------------------------------------------------------------
# Přidá závislost na černou listinu (resp. přidá další důvod, proč ji tam
# nechat, pokud už tam je).
#------------------------------------------------------------------------------
sub pridat_zakaz
{
my $zakaz = shift; # odkaz na skalár se seznamem zákazů
my $r = shift; # index řídícího uzlu hrany, která se má zakázat
my $z = shift; # index závislého uzlu hrany, která se má zakázat
my $duvod = shift; # důvod zákazu (aby bylo možné odvolat zákazy mající stejnou příčinu)
if($$zakaz !~ m/\($r-$z:$duvod\)/)
{
$$zakaz .= "($r-$z:$duvod)";
}
}
#------------------------------------------------------------------------------
# Odebere jeden důvod zákazu dané závislosti z černé listiny. Pokud toto byl
# poslední důvod, závislost se stane povolenou a je opět schopna soutěže.
#------------------------------------------------------------------------------
sub zrusit_zakaz
{
my $zakaz = shift; # odkaz na skalár se seznamem zákazů
my $r = shift; # index řídícího uzlu hrany, která se má zakázat
my $z = shift; # index závislého uzlu hrany, která se má zakázat
my $duvod = shift; # důvod zákazu (aby bylo možné odvolat zákazy mající stejnou příčinu)
$$zakaz =~ s/\($r-$z:$duvod\)//g;
}
#------------------------------------------------------------------------------
# Zjistí, zda je závislost na černé listině (dočasně zakázaná).
#------------------------------------------------------------------------------
sub je_zakazana
{
my $zakaz = shift; # skalár se seznamem zákazů
my $r = shift; # index řídícího uzlu hrany, která se má zakázat
my $z = shift; # index závislého uzlu hrany, která se má zakázat
return $zakaz =~ m/\($r-$z:/;
}
#------------------------------------------------------------------------------
# Inicializuje seznam zákazů na začátku zpracování věty.
# Vrátí řetězec se zakódovaným seznamem zákazů.
# (Jazykově závislá funkce.)
#------------------------------------------------------------------------------
sub formulovat_zakazy
{
my $anot = shift; # odkaz na pole hashů
my $stav = shift; # odkaz na hash
my $prislusnost_k_useku = $stav->{prislusnost_k_useku}; # odkaz na pole s příslušností slov k mezičárkovým úsekům
my $hotovost_useku = $stav->{hotovost_useku}; # odkaz na pole s údaji o úplnosti analýzy mezi dvěma čárkami
my $zakaz; # výstupní řetězec
# Zatím globální proměnné.
my $konfig = \%main::konfig;
### Závislosti na čárkách jsou zakázány ###
# Ve skutečnosti totiž závislost na čárce vždy znamená Coord nebo Apos.
if($konfig->{carka_je_list})
{
for(my $i = 1; $i<=$#{$anot}; $i++)
{
if($anot->[$i]{slovo} eq ",")
{
for(my $j = 1; $j<=$#{$anot}; $j++)
{
pridat_zakaz(\$zakaz, $i, $j, "carky jsou listy");
}
}
}
}
### Úseky mezi čárkami ###
if($konfig->{mezicarkove_useky})
{
# Zapamatovat si rozdělení věty interpunkcí na úseky.
splice(@{$prislusnost_k_useku});
splice(@{$hotovost_useku});
my $i_usek = -1;
my $carka = 0;
my $je_co_zakazovat = 0;
for(my $i = 0; $i<=$#{$anot}; $i++)
{
if($i==0 || $anot->[$i]{slovo} eq "," || $i==$#{$anot} && $stav->{uznck}[$i]=~m/^Z/)
{
$i_usek++;
$carka = 1;
$hotovost_useku->[$i_usek] = 1;
}
elsif($carka)
{
$i_usek++;
$carka = 0;
$hotovost_useku->[$i_usek] = 1;
}
else
{
$hotovost_useku->[$i_usek]++;
$je_co_zakazovat = 1;
}
$prislusnost_k_useku->[$i] = $i_usek;
}
# Zakázat závislosti vedoucí přes čárku. Povoleny budou až po spojení všech
# mezičárkových úseků.
if($je_co_zakazovat)
{
for(my $i = 0; $i<=$#{$anot}; $i++)
{
for(my $j = $i+1; $j<=$#{$anot}; $j++)
{
if($prislusnost_k_useku->[$i]!=$prislusnost_k_useku->[$j])
{
pridat_zakaz(\$zakaz, $i, $j, "carky");
pridat_zakaz(\$zakaz, $j, $i, "carky");
}
}
}
}
}
if($konfig->{predlozky})
{
### Přeskakování bezdětných předložek ###
# Zakázat závislosti, které přeskakují předložku, jež dosud nemá dítě.
for(my $i = 0; $i<=$#{$anot}; $i++)
{
if($stav->{uznck}[$i] =~ m/^R/)
{
for(my $j = 0; $j<$i; $j++)
{
for(my $k = $i+1; $k<=$#{$anot}; $k++)
{
pridat_zakaz(\$zakaz, $j, $k, "predlozka $i");
pridat_zakaz(\$zakaz, $k, $j, "predlozka $i");
}
}
}
}
}
return $stav->{zakaz} = $zakaz;
}
#------------------------------------------------------------------------------
# Zváží uvolnění některých zákazů na základě naposledy přidané závislosti.
# (Jazykově závislá funkce.)
#------------------------------------------------------------------------------
sub prehodnotit_zakazy
{
my $anot = shift; # odkaz na pole hashů
my $stav = shift; # odkaz na hash
my $r = shift; # index řídícího uzlu naposledy přidané závislosti
my $z = shift; # index závislého uzlu naposledy přidané závislosti
my $prislusnost_k_useku = $stav->{prislusnost_k_useku}; # odkaz na pole s příslušností slov k mezičárkovým úsekům
my $hotovost_useku = $stav->{hotovost_useku}; # odkaz na pole s údaji o úplnosti analýzy mezi dvěma čárkami
my $n_zbyva_zavesit = $stav->{zbyva}; # počet uzlů, kteří dosud nemají rodiče
# Zatím globální proměnné.
my $konfig = \%main::konfig;
### Úseky mezi čárkami ###
# Zvýšit hotovost úseku, ke kterému náleží naposledy zavěšený uzel.
my $hotovost = --$hotovost_useku->[$prislusnost_k_useku->[$z]];
# Jestliže už jsou hotové mezičárkové úseky, povolit i závislosti vedoucí
# mezi úseky.
if($hotovost<=1 && $stav->{zakaz} =~ m/:carky/)
{
for(my $i = 0; $i <= $#{$hotovost_useku}; $i++)
{
if($hotovost_useku->[$i] > 1)
{
goto nektere_useky_jeste_nejsou_hotove;
}
}
zrusit_zakaz(\$stav->{zakaz}, "\\d+", "\\d+", "carky");
nektere_useky_jeste_nejsou_hotove:
}
### Přeskakování bezdětných předložek ###
if($konfig->{predlozky})
{
### Přeskakování bezdětných předložek ###
# Zrušit zákaz závislostí, které přeskakují předložku, jež už má dítě.
if($stav->{uznck}[$r] =~ m/^R/)
{
zrusit_zakaz(\$stav->{zakaz}, "\\d+", "\\d+", "predlozka $r");
}
# Teoreticky se může stát, že na každém konci věty zůstane jedna
# bezdětná předložka a zbytek zůstane mezi nimi uvězněn a nebude se
# moci připojit ani na jednu stranu. Proto ve chvíli, kdy zbývá
# zavěsit poslední uzel, uvolnit všechny zákazy.
if($n_zbyva_zavesit==1)
{
zrusit_zakaz(\$stav->{zakaz}, "\\d+", "\\d+", "predlozka \\d+");
}
}
}
1;