line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Lingua::Jspell; |
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
86559
|
use warnings; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
69
|
|
4
|
2
|
|
|
2
|
|
16
|
use strict; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
38
|
|
5
|
|
|
|
|
|
|
|
6
|
2
|
|
|
2
|
|
46
|
use 5.008001; |
|
2
|
|
|
|
|
8
|
|
7
|
|
|
|
|
|
|
|
8
|
2
|
|
|
2
|
|
1300
|
use POSIX qw(locale_h); |
|
2
|
|
|
|
|
13396
|
|
|
2
|
|
|
|
|
10
|
|
9
|
|
|
|
|
|
|
setlocale(LC_CTYPE, "pt_PT"); |
10
|
2
|
|
|
2
|
|
4352
|
use locale; |
|
2
|
|
|
|
|
1249
|
|
|
2
|
|
|
|
|
12
|
|
11
|
|
|
|
|
|
|
|
12
|
2
|
|
|
2
|
|
87
|
use base 'Exporter'; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
288
|
|
13
|
|
|
|
|
|
|
our @EXPORT_OK = (qw.onethat verif nlgrep setstopwords |
14
|
|
|
|
|
|
|
onethatverif any2str hash2str isguess.); |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
our %EXPORT_TAGS = (basic => [qw.onethat verif onethatverif |
17
|
|
|
|
|
|
|
any2str hash2str isguess.], |
18
|
|
|
|
|
|
|
greps => [qw.nlgrep setstopwords.]); |
19
|
|
|
|
|
|
|
# use Data::Dumper; |
20
|
2
|
|
|
2
|
|
1058
|
use File::Spec::Functions; |
|
2
|
|
|
|
|
1726
|
|
|
2
|
|
|
|
|
167
|
|
21
|
2
|
|
|
2
|
|
1007
|
use Lingua::Jspell::ConfigData; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
75
|
|
22
|
2
|
|
|
2
|
|
931
|
use Lingua::Jspell::EAGLES; |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
63
|
|
23
|
2
|
|
|
2
|
|
1164
|
use IPC::Open3; |
|
2
|
|
|
|
|
8452
|
|
|
2
|
|
|
|
|
119
|
|
24
|
2
|
|
|
2
|
|
1134
|
use YAML qw/LoadFile/; |
|
2
|
|
|
|
|
17128
|
|
|
2
|
|
|
|
|
109
|
|
25
|
2
|
|
|
2
|
|
1145
|
use Data::Compare; |
|
2
|
|
|
|
|
30429
|
|
|
2
|
|
|
|
|
14
|
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=head1 NAME |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=encoding utf8 |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
Lingua::Jspell - Perl interface to the Jspell morphological analyser. |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=cut |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
our $VERSION = '1.96'; |
36
|
|
|
|
|
|
|
our $JSPELL; |
37
|
|
|
|
|
|
|
our $JSPELLLIB; |
38
|
|
|
|
|
|
|
our $MODE = { nm => "af", flags => 0 }; |
39
|
|
|
|
|
|
|
our $DELIM = '==='; |
40
|
|
|
|
|
|
|
our %STOP =(); |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
BEGIN { |
43
|
2
|
|
|
2
|
|
4953
|
delete @ENV{qw(IFS CD PATH ENV BASH_ENV)}; # Make %ENV safer |
44
|
|
|
|
|
|
|
|
45
|
2
|
|
|
|
|
6
|
my $EXE = ""; |
46
|
2
|
50
|
|
|
|
10
|
if ($^O eq "MSWin32") { |
47
|
0
|
|
|
|
|
0
|
$ENV{PATH} = "blib\\usrlib"; |
48
|
0
|
|
|
|
|
0
|
$EXE=".exe" ; |
49
|
|
|
|
|
|
|
|
50
|
0
|
|
|
|
|
0
|
my $dllpath = Lingua::Jspell::ConfigData->config("libdir"); |
51
|
0
|
|
|
|
|
0
|
$ENV{PATH} = join(";", $dllpath, $ENV{PATH}); |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
2
|
|
|
|
|
4
|
local $_; |
55
|
|
|
|
|
|
|
|
56
|
2
|
|
|
|
|
22
|
$JSPELL = catfile("blib","bin","jspell$EXE"); |
57
|
2
|
50
|
|
|
|
57
|
$JSPELL = Lingua::Jspell::ConfigData->config("jspell") unless -x $JSPELL; |
58
|
|
|
|
|
|
|
|
59
|
2
|
50
|
|
|
|
43
|
die "jspell binary cannot be found!\n" unless -x $JSPELL; |
60
|
|
|
|
|
|
|
|
61
|
2
|
|
|
|
|
20
|
local $.; |
62
|
2
|
50
|
|
|
|
5565
|
open X, "$JSPELL -vv|" or die "Can't execute $JSPELL"; |
63
|
2
|
|
|
|
|
1552
|
while () { |
64
|
118
|
100
|
|
|
|
441
|
if (/LIBDIR = "([^"]+)"/) { |
65
|
2
|
|
|
|
|
61
|
$JSPELLLIB = $1; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
} |
68
|
2
|
|
|
|
|
96
|
close X; |
69
|
2
|
50
|
|
|
|
15419
|
die "Can't find out jspell lib dir" unless $JSPELLLIB; |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=head1 SYNOPSIS |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
use Lingua::Jspell; |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
my $dict = Lingua::Jspell->new( "dict_name"); |
77
|
|
|
|
|
|
|
my $dict = Lingua::Jspell->new( "dict_name" , "personal_dict_name"); |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
$dict->rad("gatinho"); # list of radicals (gato) |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
$dict->fea("gatinho"); # list of possible analysis |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
$dict->der("gato"); # list of derivated words |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
$dict->flags("gato"); # list of roots and flags |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
=head1 FUNCTIONS |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
=head2 new |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
Use to open a dictionary. Pass it the dictionary name and optionally a |
93
|
|
|
|
|
|
|
personal dictionary name. A new jspell dictionary object will be |
94
|
|
|
|
|
|
|
returned. |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=cut |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
sub new { |
99
|
0
|
|
|
0
|
1
|
|
my ($self, $dr, $pers, $flag); |
100
|
0
|
|
|
|
|
|
local $/="\n"; |
101
|
0
|
|
|
|
|
|
my $class = shift; |
102
|
|
|
|
|
|
|
|
103
|
0
|
|
|
|
|
|
$self->{dictionary} = shift; |
104
|
|
|
|
|
|
|
$self->{pdictionary} = shift || |
105
|
0
|
|
0
|
|
|
|
(defined($ENV{HOME})?"$ENV{HOME}/.jspell.$self->{dictionary}":""); |
106
|
|
|
|
|
|
|
|
107
|
0
|
0
|
|
|
|
|
$pers = $self->{pdictionary}?"-p $self->{pdictionary}":""; |
108
|
0
|
0
|
|
|
|
|
$flag = defined($self->{'undef'})?$self->{'undef'}:"-y"; |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
## Get yaml info ---------------------------------- |
111
|
0
|
|
|
|
|
|
my $yaml_file = _yaml_file($self->{dictionary}); |
112
|
0
|
0
|
|
|
|
|
if (-f $yaml_file) { |
113
|
0
|
|
|
|
|
|
$self->{yaml} = LoadFile($yaml_file); |
114
|
|
|
|
|
|
|
} else { |
115
|
0
|
|
|
|
|
|
$self->{yaml} = {}; |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
|
119
|
0
|
|
|
|
|
|
my $js = "$JSPELL -d $self->{dictionary} -a $pers -W 0 $flag -o'%s!%s:%s:%s:%s'"; |
120
|
0
|
|
|
|
|
|
local $.; |
121
|
0
|
0
|
|
|
|
|
$self->{pid} = open3($self->{DW},$self->{DR},$self->{DE},$js) or die $!; |
122
|
|
|
|
|
|
|
|
123
|
0
|
|
|
|
|
|
binmode($self->{DW},":encoding(iso-8859-1)"); |
124
|
0
|
0
|
|
|
|
|
if ($^O ne "MSWin32") { |
125
|
0
|
|
|
|
|
|
binmode($self->{DR},":encoding(iso-8859-1)"); |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
else { |
128
|
0
|
|
|
|
|
|
binmode($self->{DR},":crlf:encoding(iso-8859-1)"); |
129
|
|
|
|
|
|
|
} |
130
|
0
|
|
|
|
|
|
$dr = $self->{DR}; |
131
|
0
|
|
|
|
|
|
my $first_line = <$dr>; |
132
|
0
|
0
|
0
|
|
|
|
die "Can't execute jspell with supplied dictionaries ($js)" unless $first_line && $first_line =~ /International Jspell/; |
133
|
|
|
|
|
|
|
|
134
|
0
|
|
0
|
|
|
|
$self->{mode} ||= $MODE; |
135
|
0
|
|
|
|
|
|
my $dw = $self->{DW}; |
136
|
0
|
|
|
|
|
|
print $dw _mode($self->{mode}); |
137
|
|
|
|
|
|
|
|
138
|
0
|
0
|
|
|
|
|
if ($first_line =~ /Jspell/) { |
139
|
0
|
|
|
|
|
|
return bless $self, $class # amen |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
else { |
142
|
|
|
|
|
|
|
return undef |
143
|
0
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=head2 nearmatches |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
This method returns a list of analysis for words that are near-matches |
149
|
|
|
|
|
|
|
to the supplied word. Note that although a word might exist, this |
150
|
|
|
|
|
|
|
method will compute the near-matches as well. |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
@nearmatches = $dictionary->nearmatches('cavale'); |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
To compute the list of words to analyze, the method uses a list of |
155
|
|
|
|
|
|
|
equivalence classes that are present on the C<< SNDCLASSES >> section |
156
|
|
|
|
|
|
|
of dictionaries yaml files. |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
It is also possible to specify a list of user-defined classes. These |
159
|
|
|
|
|
|
|
are supplied as a filename that contains, per line, the characters |
160
|
|
|
|
|
|
|
that are equivalent (with spaces separating them): |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
ch x |
163
|
|
|
|
|
|
|
ss ç |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
This example says that if a word uses C, then it can be replaced |
166
|
|
|
|
|
|
|
by C for near-matches calculation. The inverse is also true. |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
If these rules are stored in a file named C, you can |
169
|
|
|
|
|
|
|
supply this list with: |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
@nearmatches = $dictionary->nearmatches('chaile', rules => 'classes.txt'); |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=cut |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
sub nearmatches { |
176
|
0
|
|
|
0
|
1
|
|
my ($dict, $word, %ops) = @_; |
177
|
0
|
|
|
|
|
|
my %classes; |
178
|
0
|
0
|
|
|
|
|
if ($ops{rules}) { |
179
|
0
|
0
|
|
|
|
|
-f $ops{rules} or die "Can't find file $ops{rules}"; |
180
|
0
|
|
|
|
|
|
local $.; |
181
|
0
|
0
|
|
|
|
|
open RULES, $ops{rules} or die "Can't open file $ops{rules}"; |
182
|
0
|
|
|
|
|
|
my @rules; |
183
|
0
|
|
|
|
|
|
while() { |
184
|
0
|
|
|
|
|
|
chomp; |
185
|
0
|
|
|
|
|
|
push @rules, [split /\s+/]; |
186
|
|
|
|
|
|
|
} |
187
|
0
|
|
|
|
|
|
close RULES; |
188
|
0
|
|
|
|
|
|
%classes = _expand_classes(@rules); |
189
|
|
|
|
|
|
|
} else { |
190
|
0
|
0
|
|
|
|
|
if (exists($dict->{yaml}{META}{SNDCLASSES})) { |
191
|
0
|
|
|
|
|
|
%classes = _expand_classes(@{ $dict->{yaml}{META}{SNDCLASSES} }); |
|
0
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
} else { |
193
|
0
|
|
|
|
|
|
warn "No snd classes defined\n"; |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
} |
196
|
|
|
|
|
|
|
|
197
|
0
|
|
|
|
|
|
my @words = (); |
198
|
0
|
|
|
|
|
|
for my $c (keys %classes) { |
199
|
0
|
|
|
|
|
|
my @where; |
200
|
0
|
|
|
|
|
|
my $l = length($c); |
201
|
0
|
|
|
|
|
|
push @where, pos($word)-$l while $word =~ /$c/g; |
202
|
0
|
|
|
|
|
|
for my $i (@where) { |
203
|
0
|
|
|
|
|
|
my $o = $word; |
204
|
0
|
|
|
|
|
|
substr($o,$i,length($c), $classes{$c}); |
205
|
0
|
0
|
|
|
|
|
push @words, $o if $o ne $word; |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
|
209
|
0
|
|
|
|
|
|
my $current_mode = $dict->setmode; |
210
|
0
|
|
|
|
|
|
$dict->setmode({flags => 0, nm => "cc" }); |
211
|
|
|
|
|
|
|
|
212
|
0
|
|
|
|
|
|
my @nms; |
213
|
0
|
|
|
|
|
|
for my $w (@words) { |
214
|
0
|
|
0
|
|
|
|
my @analysis = map { $_->{guess}||=$w; $_ } $dict->fea($w); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
215
|
0
|
|
|
|
|
|
push @nms, @analysis; |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
0
|
|
|
|
|
|
@nms = grep { $_->{guess} ne $word } @nms; |
|
0
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
# This one is not a guess |
220
|
0
|
|
|
|
|
|
push @nms, $dict->fea($word); |
221
|
|
|
|
|
|
|
|
222
|
0
|
|
|
|
|
|
@nms = _remove_dups(@nms); |
223
|
|
|
|
|
|
|
|
224
|
0
|
|
|
|
|
|
$dict->setmode($current_mode); |
225
|
0
|
|
|
|
|
|
return @nms; |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
sub _remove_dups { |
229
|
0
|
|
|
0
|
|
|
my @new; |
230
|
0
|
|
|
|
|
|
while (my $struct = shift @_) { |
231
|
0
|
0
|
|
|
|
|
push @new, $struct unless grep { Compare($_,$struct) } @new; |
|
0
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
} |
233
|
0
|
|
|
|
|
|
@new; |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
|
236
|
0
|
|
|
0
|
|
|
sub _expand_classes { map { _expand_class($_) } @_ } |
|
0
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
sub _expand_class { |
239
|
0
|
|
|
0
|
|
|
my @class = @{ $_[0] }; |
|
0
|
|
|
|
|
|
|
240
|
0
|
|
|
|
|
|
my %subs; |
241
|
0
|
|
|
|
|
|
for my $c (@class) { |
242
|
0
|
|
|
|
|
|
my @other = grep { $_ ne $c } @class; |
|
0
|
|
|
|
|
|
|
243
|
0
|
|
|
|
|
|
for (@other) { |
244
|
0
|
|
|
|
|
|
$subs{$c} = $_; |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
%subs |
248
|
0
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
=head2 setmode |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
$dict->setmode({flags => 0, nm => "off" }); |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=over 4 |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=item af |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
(add flags) Enable parcial near misses, by using rules not officially |
259
|
|
|
|
|
|
|
associated with the current word. Does not give suggestions by |
260
|
|
|
|
|
|
|
changing letters on the original word. (default option) |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=item full |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
(add flags and change characters) Enable near misses, try to use rules |
265
|
|
|
|
|
|
|
where they are not applied, try to give suggestions by swapping |
266
|
|
|
|
|
|
|
adjacent letters on the original word. |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
=item cc |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
(change characters) Enable parcial near misses, by swapping adjacent, |
271
|
|
|
|
|
|
|
inserting or modifying letters on the original word. Does not use |
272
|
|
|
|
|
|
|
rules not associated with the current word. |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=item off |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
Disable near misses at all. |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
=back |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
=cut |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
sub setmode { |
283
|
0
|
|
|
0
|
1
|
|
my ($self, $mode) = @_; |
284
|
|
|
|
|
|
|
|
285
|
0
|
|
|
|
|
|
my $dw = $self->{DW}; |
286
|
0
|
0
|
|
|
|
|
if (defined($mode)) { |
287
|
0
|
|
|
|
|
|
$self->{mode} = $mode; |
288
|
0
|
|
|
|
|
|
print $dw _mode($mode); |
289
|
|
|
|
|
|
|
} else { |
290
|
0
|
|
|
|
|
|
return $self->{mode}; |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
=head2 fea |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
Returns a list of analisys of a word. Each analisys is a list of |
297
|
|
|
|
|
|
|
attribute value pairs. Attributes available: CAT, T, G, N, P, .... |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
@l = $dic->fea($word) |
300
|
|
|
|
|
|
|
@l = $dic->fea($word,{...att. value pair restriction}) |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
If a restriction is provided, just the analisys that verify |
303
|
|
|
|
|
|
|
it are returned. |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=cut |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
sub fea { |
309
|
0
|
|
|
0
|
1
|
|
my ( $self, $w, $res ) = @_; |
310
|
|
|
|
|
|
|
|
311
|
0
|
|
|
|
|
|
local $/ = "\n"; |
312
|
|
|
|
|
|
|
|
313
|
0
|
|
|
|
|
|
my @r = (); |
314
|
0
|
|
|
|
|
|
my ( $a, $rad, $cla, $flags ); |
315
|
|
|
|
|
|
|
|
316
|
0
|
0
|
|
|
|
|
if ( $w =~ /\!/ ) { |
317
|
0
|
|
|
|
|
|
@r = ( +{ CAT => 'punct', rad => '!' } ); |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
else { |
320
|
0
|
|
|
|
|
|
my ( $dw, $dr ) = ( $self->{DW}, $self->{DR} ); |
321
|
|
|
|
|
|
|
|
322
|
0
|
|
|
|
|
|
local $.; |
323
|
|
|
|
|
|
|
|
324
|
0
|
|
|
|
|
|
print $dw " $w\n"; |
325
|
0
|
|
|
|
|
|
$a = <$dr>; |
326
|
|
|
|
|
|
|
|
327
|
0
|
|
|
|
|
|
for ( ; ( $a ne "\n" ); $a = <$dr> ) { # l^e as respostas |
328
|
0
|
|
|
|
|
|
for ($a) { |
329
|
0
|
|
|
|
|
|
chop; |
330
|
0
|
|
|
|
|
|
my ( $lixo, $clas ); |
331
|
0
|
0
|
|
|
|
|
if (/(.*?) :(.*)/) { $clas = $2; $lixo = $1 } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
332
|
0
|
|
|
|
|
|
else { $clas = $_; $lixo = "" } |
|
0
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
|
334
|
0
|
|
|
|
|
|
for ( split( /[,;] /, $clas ) ) { |
335
|
0
|
|
|
|
|
|
( $rad, $cla ) = m{(.+?)\!:*(.*)$}; |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
# $cla undef quando nada preenchido... |
338
|
|
|
|
|
|
|
|
339
|
0
|
0
|
|
|
|
|
if ($cla) { |
340
|
0
|
0
|
|
|
|
|
if ( $cla =~ s/\/(.*)$// ) { $flags = $1 } |
|
0
|
|
|
|
|
|
|
341
|
0
|
|
|
|
|
|
else { $flags = "" } |
342
|
|
|
|
|
|
|
|
343
|
0
|
|
|
|
|
|
$cla =~ s/:+$//g; |
344
|
0
|
|
|
|
|
|
$cla =~ s/:+/,/g; |
345
|
|
|
|
|
|
|
|
346
|
0
|
|
|
|
|
|
my %ana = (); |
347
|
0
|
|
|
|
|
|
my @attrs = split /,/, $cla; |
348
|
0
|
|
|
|
|
|
for (@attrs) { |
349
|
0
|
0
|
|
|
|
|
if (m!=!) { |
350
|
0
|
|
|
|
|
|
$ana{$`} = $'; |
351
|
|
|
|
|
|
|
} |
352
|
|
|
|
|
|
|
else { |
353
|
0
|
|
|
|
|
|
print STDERR |
354
|
|
|
|
|
|
|
"** WARNING: Feature-structure parse error: $cla (for word '$w')\n"; |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
|
358
|
0
|
0
|
|
|
|
|
$ana{"flags"} = $flags if $flags; |
359
|
|
|
|
|
|
|
|
360
|
0
|
0
|
|
|
|
|
if ( $lixo =~ /^&/ ) { |
361
|
0
|
|
|
|
|
|
$rad =~ s/(.*?)= //; |
362
|
0
|
|
|
|
|
|
$ana{"guess"} = lc($1); |
363
|
0
|
|
|
|
|
|
$ana{"unknown"} = 1; |
364
|
|
|
|
|
|
|
} |
365
|
0
|
0
|
|
|
|
|
if ( $rad ne "" ) { |
366
|
0
|
|
|
|
|
|
push( @r, +{ "rad" => $rad, %ana } ); |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
} |
369
|
|
|
|
|
|
|
else { |
370
|
0
|
|
|
|
|
|
@r = ( +{ CAT => "?", rad => $rad } ); |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
} |
376
|
0
|
0
|
|
|
|
|
if ($res) { |
377
|
0
|
|
|
|
|
|
return ( grep { verif( $res, $_ ) } @r ); |
|
0
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
} |
379
|
0
|
|
|
|
|
|
else { return @r; } |
380
|
|
|
|
|
|
|
} |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
=head2 flags |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
returns the set of morphological flag associated with the word. |
385
|
|
|
|
|
|
|
Each flag is related with a set of morphological rules. |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
@f = flags("gato") |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
=cut |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
sub flags { |
392
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
393
|
0
|
|
|
|
|
|
my $w = shift; |
394
|
0
|
|
|
|
|
|
my ($a,$dr); |
395
|
0
|
|
|
|
|
|
local $/="\n"; |
396
|
|
|
|
|
|
|
|
397
|
0
|
|
|
|
|
|
local $.; |
398
|
|
|
|
|
|
|
|
399
|
0
|
|
|
|
|
|
print {$self->{DW}} "\$\"$w\n"; |
|
0
|
|
|
|
|
|
|
400
|
0
|
|
|
|
|
|
$dr = $self->{DR}; |
401
|
0
|
|
|
|
|
|
$a = <$dr>; |
402
|
|
|
|
|
|
|
|
403
|
0
|
|
|
|
|
|
chop $a; |
404
|
0
|
|
|
|
|
|
return split(/[# ,]+/,$a); |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
=head2 rad |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
Returns the list of all possible radicals/lemmas for the supplied word. |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
@l = $dic->rad($word) |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
=cut |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
sub rad { |
416
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
417
|
0
|
|
|
|
|
|
my $word = shift; |
418
|
|
|
|
|
|
|
|
419
|
0
|
0
|
|
|
|
|
return () if $word =~ /\!/; |
420
|
|
|
|
|
|
|
|
421
|
0
|
|
|
|
|
|
my %rad = (); |
422
|
0
|
|
|
|
|
|
my $a_ = ""; |
423
|
0
|
|
|
|
|
|
local $/ = "\n"; |
424
|
0
|
|
|
|
|
|
local $.; |
425
|
|
|
|
|
|
|
|
426
|
0
|
|
|
|
|
|
my ($dw,$dr) = ($self->{DW},$self->{DR}); |
427
|
|
|
|
|
|
|
|
428
|
0
|
|
|
|
|
|
print $dw " $word\n"; |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
|
431
|
0
|
|
|
|
|
|
for ($a_ = <$dr>; $a_ ne "\n"; $a_ = <$dr>) { |
432
|
0
|
|
|
|
|
|
chop $a_; |
433
|
0
|
|
|
|
|
|
%rad = ($a_ =~ m/(?: |:)([^ =:,!]+)(\!)/g ) ; |
434
|
|
|
|
|
|
|
} |
435
|
|
|
|
|
|
|
|
436
|
0
|
|
|
|
|
|
return (keys %rad); |
437
|
|
|
|
|
|
|
} |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
=head2 der |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
Returns the list of all possible words using the word as radical. |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
@l = $dic->der($word); |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
=cut |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
sub der { |
449
|
0
|
|
|
0
|
1
|
|
my ($self, $w) = @_; |
450
|
0
|
|
|
|
|
|
my @der = $self->flags($w); |
451
|
0
|
|
|
|
|
|
my %res = (); |
452
|
0
|
|
|
|
|
|
my $command; |
453
|
|
|
|
|
|
|
|
454
|
0
|
|
|
|
|
|
local $/ = "\n"; |
455
|
0
|
|
|
|
|
|
local $.; |
456
|
0
|
0
|
|
|
|
|
my $pid = open3(\*WR, \*RD, \*ERROR, "$JSPELL -d $self->{dictionary} -e -o \"\"") or die "Can't execute jspell."; |
457
|
0
|
|
|
|
|
|
print WR join("\n",@der),"\n"; |
458
|
0
|
0
|
|
|
|
|
print WR "\032" if ($^O =~ /win32/i); |
459
|
0
|
|
|
|
|
|
close WR; |
460
|
0
|
|
|
|
|
|
while () { |
461
|
0
|
|
|
|
|
|
chomp; |
462
|
0
|
|
|
|
|
|
s/(=|, | $)//g; |
463
|
0
|
|
|
|
|
|
for(split) { $res{$_}++; } |
|
0
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
} |
465
|
0
|
|
|
|
|
|
close RD; |
466
|
0
|
|
|
|
|
|
close ERROR; |
467
|
0
|
|
|
|
|
|
waitpid $pid, 0; |
468
|
|
|
|
|
|
|
|
469
|
0
|
|
|
|
|
|
my $irrcomm; |
470
|
0
|
|
|
|
|
|
my $irr_file = _irr_file($self->{dictionary}); |
471
|
|
|
|
|
|
|
|
472
|
0
|
|
|
|
|
|
local $.; |
473
|
0
|
0
|
|
|
|
|
if (open IRR, $irr_file) { |
474
|
0
|
|
|
|
|
|
while () { |
475
|
0
|
0
|
|
|
|
|
next unless /^\Q$w\E=/; |
476
|
0
|
|
|
|
|
|
chomp; |
477
|
0
|
|
|
|
|
|
for (split(/[= ]+/,$_)) { $res{$_}++; } |
|
0
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
} |
479
|
0
|
|
|
|
|
|
close IRR; |
480
|
|
|
|
|
|
|
} |
481
|
0
|
|
|
|
|
|
return keys %res; |
482
|
|
|
|
|
|
|
} |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
=head2 onethat |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
Returns the first Feature Structure from the supplied list that |
487
|
|
|
|
|
|
|
verifies the Feature Structure Pattern used. |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
%analysis = onethat( { CAT=>'adj' }, @features); |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
%analysis = onethat( { CAT=>'adj' }, $pt->fea("espanhol")); |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
=cut |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
sub onethat { |
496
|
0
|
|
|
0
|
1
|
|
my ($a, @b) = @_; |
497
|
0
|
|
|
|
|
|
for (@b) { |
498
|
0
|
0
|
|
|
|
|
return %$_ if verif($a,$_); |
499
|
|
|
|
|
|
|
} |
500
|
0
|
|
|
|
|
|
return () ; |
501
|
|
|
|
|
|
|
} |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
=head2 verif |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
Returns a true value if the second Feature Structure verifies the |
506
|
|
|
|
|
|
|
first Feature Structure Pattern. |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
if (verif( $pattern, $feature) ) { ... } |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
=cut |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
sub verif { |
513
|
0
|
|
|
0
|
1
|
|
my ($a, $b) = @_; |
514
|
0
|
|
|
|
|
|
for (keys %$a) { |
515
|
0
|
0
|
0
|
|
|
|
return 0 if (!defined($b->{$_}) || $a->{$_} ne $b->{$_}); |
516
|
|
|
|
|
|
|
} |
517
|
0
|
|
|
|
|
|
return 1; |
518
|
|
|
|
|
|
|
} |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
=head2 nlgrep |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
@line = $d->nlgrep( word , files); |
523
|
|
|
|
|
|
|
@line = $d->nlgrep( [word1, wordn] , files); |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
or with options to set a max number of entries, rec. separator, or tu use |
526
|
|
|
|
|
|
|
radtxt files format. |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
@line = $d->nlgrep( {max=>100, sep => "\n", radtxt=>0} , pattern , files); |
529
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
=cut |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
sub nlgrep { |
533
|
0
|
|
|
0
|
1
|
|
my ($self ) = shift; |
534
|
|
|
|
|
|
|
# max=int, sep:str, radtxt:bool |
535
|
0
|
|
|
|
|
|
my %opt = (max=>10000, sep => "\n",radtxt=>0); |
536
|
0
|
0
|
|
|
|
|
%opt = (%opt,%{shift(@_)}) if ref($_[0]) eq "HASH"; |
|
0
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
|
538
|
0
|
|
|
|
|
|
my $p = shift; |
539
|
|
|
|
|
|
|
|
540
|
0
|
0
|
0
|
|
|
|
if(!ref($p) && $p =~ /[ ()*,]/){ |
541
|
0
|
0
|
|
|
|
|
$p = [map {/\w/ ? ($_):()} split(/[\- ()*\|,]/,$a)];} |
|
0
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
|
543
|
0
|
|
|
|
|
|
my $p2 ; |
544
|
|
|
|
|
|
|
|
545
|
0
|
0
|
|
|
|
|
if(ref($p) eq "ARRAY"){ |
546
|
0
|
0
|
|
|
|
|
if($opt{radtxt}){ |
547
|
0
|
|
|
|
|
|
my @pat = @$p ; |
548
|
0
|
|
|
0
|
|
|
$p2 = sub{ my $x=shift; |
549
|
0
|
0
|
|
|
|
|
for(@pat){ return 0 unless $x =~ /\b(?:$_)\b/i;} |
|
0
|
|
|
|
|
|
|
550
|
0
|
|
|
|
|
|
return 1; }; |
|
0
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
} |
552
|
|
|
|
|
|
|
else { |
553
|
0
|
|
|
|
|
|
my @pat = map {join("|",($_,$self->der($_)))} @$p ; |
|
0
|
|
|
|
|
|
|
554
|
0
|
|
|
0
|
|
|
$p2 = sub{ my $x=shift; |
555
|
0
|
0
|
|
|
|
|
for(@pat){ return 0 unless $x =~ /\b(?:$_)\b/i;} |
|
0
|
|
|
|
|
|
|
556
|
0
|
|
|
|
|
|
return 1; } |
557
|
0
|
|
|
|
|
|
} |
558
|
|
|
|
|
|
|
} |
559
|
|
|
|
|
|
|
else { |
560
|
0
|
0
|
|
|
|
|
my $pattern = $opt{radtxt} ? $p : join("|",($p,$self->der($p))); |
561
|
0
|
|
|
0
|
|
|
$p2 = sub{ $_[0] =~ /\b(?:$pattern)\b/i }; |
|
0
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
} |
563
|
|
|
|
|
|
|
|
564
|
0
|
|
|
|
|
|
my @file_list=@_; |
565
|
0
|
|
|
|
|
|
local $/=$opt{sep}; |
566
|
|
|
|
|
|
|
|
567
|
0
|
|
|
|
|
|
my @res=(); |
568
|
0
|
|
|
|
|
|
my $n = 0; |
569
|
0
|
|
|
|
|
|
for(@file_list) { |
570
|
0
|
|
|
|
|
|
local $.; |
571
|
0
|
0
|
|
|
|
|
open(F,$_) or die("cant open $_\n"); |
572
|
0
|
|
|
|
|
|
while() { |
573
|
0
|
0
|
|
|
|
|
if ($p2->($_)) { |
574
|
0
|
|
|
|
|
|
chomp; |
575
|
0
|
0
|
|
|
|
|
s/$DELIM.*//g if $opt{radtxt}; |
576
|
0
|
|
|
|
|
|
push(@res,$_); |
577
|
0
|
0
|
|
|
|
|
last if $n++ == $opt{max}; |
578
|
|
|
|
|
|
|
} |
579
|
|
|
|
|
|
|
} |
580
|
0
|
|
|
|
|
|
close F; |
581
|
0
|
0
|
|
|
|
|
last if $n == $opt{max}; |
582
|
|
|
|
|
|
|
} |
583
|
0
|
|
|
|
|
|
return @res; |
584
|
|
|
|
|
|
|
} |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
=head2 setstopwords |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
=cut |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
sub setstopwords { |
591
|
0
|
|
|
0
|
1
|
|
$STOP{$_} = 1 for @_; |
592
|
|
|
|
|
|
|
} |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
=head2 eagles |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
=cut |
597
|
|
|
|
|
|
|
sub eagles { |
598
|
0
|
|
|
0
|
1
|
|
my ($dict, $palavra, @ar) = @_; |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
map { |
601
|
0
|
|
|
|
|
|
my $fea = $_; |
|
0
|
|
|
|
|
|
|
602
|
0
|
|
|
|
|
|
map { $_ . ":$fea->{rad}" } Lingua::Jspell::EAGLES::_cat2eagles(%$fea) |
|
0
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
} $dict->fea($palavra, @ar); |
604
|
|
|
|
|
|
|
} |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
# NOTA: Esta funcao é específica da língua TUGA! |
607
|
|
|
|
|
|
|
sub _cat2small { |
608
|
0
|
|
|
0
|
|
|
my %b = @_; |
609
|
|
|
|
|
|
|
# no warnings; |
610
|
|
|
|
|
|
|
|
611
|
0
|
|
0
|
|
|
|
$b{CAT} ||= "HEY!"; |
612
|
0
|
|
0
|
|
|
|
$b{G} ||= ""; |
613
|
0
|
|
0
|
|
|
|
$b{N} ||= ""; |
614
|
0
|
|
0
|
|
|
|
$b{P} ||= ""; |
615
|
0
|
|
0
|
|
|
|
$b{T} ||= ""; |
616
|
|
|
|
|
|
|
|
617
|
0
|
0
|
0
|
|
|
|
if ($b{CAT} eq 'art') { |
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
618
|
|
|
|
|
|
|
# Artigos: o léxico já prevê todos... |
619
|
|
|
|
|
|
|
# por isso, NUNCA SE DEVE CHEGAR AQUI!!! |
620
|
0
|
|
|
|
|
|
return "ART"; |
621
|
|
|
|
|
|
|
# 16 tags |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'card') { |
624
|
|
|
|
|
|
|
# Numerais cardinais: |
625
|
0
|
|
|
|
|
|
return "DNCNP"; |
626
|
|
|
|
|
|
|
# o léxico já prevê os que flectem (1 e 2); o resto é tudo neutro plural. |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'nord') { |
629
|
|
|
|
|
|
|
# Numerais ordinais: |
630
|
0
|
|
|
|
|
|
return "\UDNO$b{G}$b{N}"; |
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'ppes' || $b{CAT} eq 'prel' || |
633
|
|
|
|
|
|
|
$b{CAT} eq 'ppos' || $b{CAT} eq 'pdem' || |
634
|
|
|
|
|
|
|
$b{CAT} eq 'pind' || $b{CAT} eq 'pint') { |
635
|
|
|
|
|
|
|
# Pronomes: |
636
|
0
|
0
|
|
|
|
|
if ($b{CAT} eq 'ppes') { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
637
|
|
|
|
|
|
|
# Pronomes pessoais |
638
|
0
|
|
|
|
|
|
$b{CAT} = 'PS'; |
639
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'prel') { |
640
|
|
|
|
|
|
|
# Pronomes relativos |
641
|
0
|
|
|
|
|
|
$b{CAT} = 'PR'; |
642
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'ppos') { |
643
|
|
|
|
|
|
|
# Pronomes possessivos |
644
|
0
|
|
|
|
|
|
$b{CAT} = 'PP'; |
645
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'pdem') { |
646
|
|
|
|
|
|
|
# Pronomes demonstrativos |
647
|
0
|
|
|
|
|
|
$b{CAT} = 'PD'; |
648
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'pint') { |
649
|
|
|
|
|
|
|
# Pronomes interrogativos |
650
|
0
|
|
|
|
|
|
$b{CAT} = 'PI'; |
651
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'pind') { |
652
|
|
|
|
|
|
|
# Pronomes indefinidos |
653
|
0
|
|
|
|
|
|
$b{CAT} = 'PF'; |
654
|
|
|
|
|
|
|
} |
655
|
|
|
|
|
|
|
|
656
|
0
|
0
|
|
|
|
|
$b{G} = 'N' if $b{G} eq '_'; |
657
|
0
|
0
|
|
|
|
|
$b{N} = 'N' if $b{N} eq '_'; |
658
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
# $b{C} esta por inicializar... oops!? vou por como C para já |
660
|
0
|
|
|
|
|
|
$b{C} = "C"; |
661
|
0
|
|
|
|
|
|
return "\U$b{CAT}$b{'C'}$b{G}$b{'P'}$b{N}"; |
662
|
|
|
|
|
|
|
# $b{'C'}: caso latino. |
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'nc') { |
665
|
|
|
|
|
|
|
# Nomes comuns: |
666
|
0
|
0
|
0
|
|
|
|
$b{G} = 'N' if $b{G} eq '_' || $b{G} eq ''; |
667
|
0
|
0
|
0
|
|
|
|
$b{N} = 'N' if $b{N} eq '_' || $b{N} eq ''; |
668
|
0
|
|
0
|
|
|
|
$b{GR} ||= '' ; |
669
|
0
|
0
|
|
|
|
|
$b{GR}= 'd' if $b{GR} eq 'dim'; |
670
|
0
|
|
|
|
|
|
return "\U$b{CAT}$b{G}$b{N}$b{GR}"; |
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'np') { |
673
|
|
|
|
|
|
|
# Nomes próprios: |
674
|
0
|
0
|
0
|
|
|
|
$b{G} = 'N' if $b{G} eq '_' || $b{G} eq ''; |
675
|
0
|
0
|
0
|
|
|
|
$b{N} = 'N' if $b{N} eq '_' || $b{N} eq ''; |
676
|
0
|
|
|
|
|
|
return "\U$b{CAT}$b{G}$b{N}"; |
677
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'adj') { |
679
|
|
|
|
|
|
|
# Adjectivos: |
680
|
0
|
0
|
|
|
|
|
$b{G} = 'N' if $b{G} eq '_'; |
681
|
0
|
0
|
|
|
|
|
$b{G} = 'N' if $b{G} eq '2'; |
682
|
0
|
0
|
|
|
|
|
$b{N} = 'N' if $b{N} eq '_'; |
683
|
0
|
|
0
|
|
|
|
$b{GR} ||= '' ; |
684
|
0
|
0
|
|
|
|
|
$b{GR} = 'd' if $b{GR} eq 'dim'; |
685
|
|
|
|
|
|
|
# elsif ($b{N} eq ''){ |
686
|
|
|
|
|
|
|
# $b{N} = 'N'; |
687
|
|
|
|
|
|
|
# } |
688
|
0
|
|
|
|
|
|
return "\UJ$b{G}$b{N}$b{GR}"; |
689
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'a_nc') { |
691
|
|
|
|
|
|
|
# Adjectivos que podem funcionar como nomes comuns: |
692
|
0
|
0
|
|
|
|
|
$b{G} = 'N' if $b{G} eq '_'; |
693
|
0
|
0
|
|
|
|
|
$b{G} = 'N' if $b{G} eq '2'; |
694
|
0
|
0
|
|
|
|
|
$b{N} = 'N' if $b{N} eq '_'; |
695
|
0
|
|
0
|
|
|
|
$b{GR} ||= '' ; |
696
|
0
|
0
|
|
|
|
|
$b{GR} = 'd' if $b{GR} eq 'dim'; |
697
|
|
|
|
|
|
|
# elsif ($b{N} eq ''){ |
698
|
|
|
|
|
|
|
# $b{N} = 'N'; |
699
|
|
|
|
|
|
|
# } |
700
|
0
|
|
|
|
|
|
return "\UX$b{G}$b{N}$b{GR}"; |
701
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'v') { |
703
|
|
|
|
|
|
|
# Verbos: |
704
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
# formas nominais: |
706
|
0
|
0
|
|
|
|
|
if ($b{T} eq 'inf') { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
707
|
|
|
|
|
|
|
# infinitivo impessoal |
708
|
0
|
|
|
|
|
|
$b{T} = 'N'; |
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
} elsif ($b{T} eq 'ppa') { |
711
|
|
|
|
|
|
|
# Particípio Passado |
712
|
0
|
|
|
|
|
|
$b{T} = 'PP'; |
713
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
} elsif ($b{T} eq 'g') { |
715
|
|
|
|
|
|
|
# Gerúndio |
716
|
0
|
|
|
|
|
|
$b{T} = 'G'; |
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
} elsif ($b{T} eq 'p') { |
719
|
|
|
|
|
|
|
# modo indicativo: presente (Hoje) |
720
|
0
|
|
|
|
|
|
$b{T} = 'IH'; |
721
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
} elsif ($b{T} eq 'pp') { |
723
|
|
|
|
|
|
|
# modo indicativo: pretérito Perfeito |
724
|
0
|
|
|
|
|
|
$b{T} = 'IP'; |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
} elsif ($b{T} eq 'pi') { |
727
|
|
|
|
|
|
|
# modo indicativo: pretérito Imperfeito |
728
|
0
|
|
|
|
|
|
$b{T} = 'II'; |
729
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
} elsif ($b{T} eq 'pmp') { |
731
|
|
|
|
|
|
|
# modo indicativo: pretérito Mais-que-perfeito |
732
|
0
|
|
|
|
|
|
$b{T} = 'IM'; |
733
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
} elsif ($b{T} eq 'f') { |
735
|
|
|
|
|
|
|
# modo indicativo: Futuro |
736
|
0
|
|
|
|
|
|
$b{T} = 'IF'; |
737
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
} elsif ($b{T} eq 'pc') { |
739
|
|
|
|
|
|
|
# modo conjuntivo (Se): presente (Hoje) |
740
|
0
|
|
|
|
|
|
$b{T} = 'SH'; |
741
|
|
|
|
|
|
|
|
742
|
|
|
|
|
|
|
} elsif ($b{T} eq 'pic') { |
743
|
|
|
|
|
|
|
# modo conjuntivo (Se): pretérito Imperfeito |
744
|
0
|
|
|
|
|
|
$b{T} = 'SI'; |
745
|
|
|
|
|
|
|
|
746
|
|
|
|
|
|
|
} elsif ($b{T} eq 'fc') { |
747
|
|
|
|
|
|
|
# modo conjuntivo (Se): Futuro |
748
|
0
|
|
|
|
|
|
$b{T} = 'PI'; |
749
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
} elsif ($b{T} eq 'i') { |
751
|
|
|
|
|
|
|
# modo Imperativo: presente (Hoje) |
752
|
0
|
|
|
|
|
|
$b{T} = 'MH'; |
753
|
|
|
|
|
|
|
|
754
|
|
|
|
|
|
|
} elsif ($b{T} eq 'c') { |
755
|
|
|
|
|
|
|
# modo Condicional: presente (Hoje) |
756
|
0
|
|
|
|
|
|
$b{T} = 'CH'; |
757
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
} elsif ($b{T} eq 'ip') { |
759
|
|
|
|
|
|
|
# modo Infinitivo (Pessoal ou Presente): |
760
|
0
|
|
|
|
|
|
$b{T} = 'PI'; |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
# Futuro conjuntivo? Só se tiver um "se" antes! -> regras sintácticas... |
763
|
|
|
|
|
|
|
# modo&tempo não previstos ainda... |
764
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
} else { |
766
|
0
|
|
|
|
|
|
$b{T} = '_UNKNOWN'; |
767
|
|
|
|
|
|
|
} |
768
|
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
# converter 'P=1_3' em 'P=_': provisório(?)! |
770
|
0
|
|
|
|
|
|
$b{P} = ""; |
771
|
0
|
0
|
|
|
|
|
$b{P} = '_' if $b{P} eq '1_3'; # único sítio com '_' como rhs!!! |
772
|
|
|
|
|
|
|
|
773
|
|
|
|
|
|
|
|
774
|
0
|
0
|
|
|
|
|
if ($b{T} eq "vpp") { return "\U$b{CAT}$b{T}$b{G}$b{P}$b{N}"; } |
|
0
|
|
|
|
|
|
|
775
|
0
|
|
|
|
|
|
else { return "\U$b{CAT}$b{T}$b{P}$b{N}"; } |
776
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
|
778
|
|
|
|
|
|
|
# Género, só para VPP. |
779
|
|
|
|
|
|
|
# +/- 70 tags |
780
|
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'prep') { |
782
|
|
|
|
|
|
|
# Preposições¹: |
783
|
0
|
|
|
|
|
|
return "\UP"; |
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'adv') { |
786
|
|
|
|
|
|
|
# Advérbios²: |
787
|
0
|
|
|
|
|
|
return "\UADV"; |
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'con') { |
790
|
|
|
|
|
|
|
# Conjunções²: |
791
|
0
|
|
|
|
|
|
return "\UC"; |
792
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
} elsif ($b{CAT} eq 'in') { |
794
|
|
|
|
|
|
|
# Interjeições¹: |
795
|
0
|
|
|
|
|
|
return "\UI"; |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
# ¹: não sei se a tag devia ser tão atómica, mas para já não há confusão! |
798
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
} elsif ($b{CAT} =~ m/^cp(.*)/) { |
800
|
|
|
|
|
|
|
# Contracções¹: |
801
|
0
|
0
|
|
|
|
|
$b{G} = 'N' if $b{G} eq '_'; |
802
|
0
|
0
|
|
|
|
|
$b{N} = 'N' if $b{N} eq '_'; |
803
|
0
|
|
|
|
|
|
return "\U&$b{G}$b{N}"; |
804
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
# ²: falta estruturar estes no próprio dicionário... |
806
|
|
|
|
|
|
|
# Palavras do dicionário com categoria vazia ou sem categoria, |
807
|
|
|
|
|
|
|
# palavras não existentes ou sequências aleatórias de caracteres: |
808
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
} elsif (defined($b{CAT}) && $b{CAT} eq '') { |
810
|
0
|
|
|
|
|
|
return "\UUNDEFINED"; |
811
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
} else { # restantes categorias (...?) |
813
|
0
|
|
|
|
|
|
return "\UUNTREATED"; |
814
|
|
|
|
|
|
|
} |
815
|
|
|
|
|
|
|
} |
816
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
=head2 new_featags |
818
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
=cut |
820
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
sub new_featags { |
822
|
0
|
|
|
0
|
1
|
|
my ($self, $word) = @_; |
823
|
0
|
0
|
|
|
|
|
if (exists($self->{yaml}{META}{TAG})) { |
824
|
0
|
|
|
|
|
|
my $rules = $self->{yaml}{META}{TAG}; |
825
|
0
|
|
|
|
|
|
return map { $self->_compact($rules, $_) } $self->fea($word); |
|
0
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
} else { |
827
|
0
|
|
|
|
|
|
warn "Dictionary without a YAML file, or without rules for fea-compression\n"; |
828
|
0
|
|
|
|
|
|
return undef; |
829
|
|
|
|
|
|
|
} |
830
|
|
|
|
|
|
|
} |
831
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
sub _compact { |
833
|
0
|
|
|
0
|
|
|
my ($self,$rules, $fs) = @_; |
834
|
0
|
|
|
|
|
|
my $tag; |
835
|
0
|
0
|
|
|
|
|
if (ref($rules) eq "HASH") { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
836
|
0
|
|
|
|
|
|
my ($key) = (%$rules); |
837
|
|
|
|
|
|
|
|
838
|
0
|
0
|
|
|
|
|
if (exists($fs->{$key})) { |
839
|
0
|
|
|
|
|
|
$tag = $self->_compact_id($key, $fs->{$key}); |
840
|
0
|
0
|
|
|
|
|
if (exists($rules->{$key}{$fs->{$key}})) { |
|
|
0
|
|
|
|
|
|
841
|
0
|
|
|
|
|
|
$tag.$self->_compact($rules->{$key}{$fs->{$key}}, $fs); |
842
|
|
|
|
|
|
|
} |
843
|
|
|
|
|
|
|
elsif (exists($rules->{$key}{'-'})) { |
844
|
0
|
|
|
|
|
|
$tag.$self->_compact($rules->{$key}{'-'}, $fs); |
845
|
|
|
|
|
|
|
} |
846
|
|
|
|
|
|
|
else { |
847
|
0
|
|
|
|
|
|
$tag |
848
|
|
|
|
|
|
|
} |
849
|
|
|
|
|
|
|
} |
850
|
|
|
|
|
|
|
else { |
851
|
0
|
|
|
|
|
|
"" |
852
|
|
|
|
|
|
|
} |
853
|
|
|
|
|
|
|
} |
854
|
|
|
|
|
|
|
elsif (ref($rules) eq "ARRAY") { |
855
|
0
|
|
|
|
|
|
for my $cat (@$rules) { |
856
|
0
|
|
|
|
|
|
$tag .= $self->_compact($cat, $fs); |
857
|
|
|
|
|
|
|
} |
858
|
|
|
|
|
|
|
$tag |
859
|
0
|
|
|
|
|
|
} |
860
|
|
|
|
|
|
|
elsif (!ref($rules)) { |
861
|
0
|
0
|
0
|
|
|
|
if ($rules && exists($fs->{$rules})) { |
862
|
0
|
|
|
|
|
|
$self->_compact_id($rules, $fs->{$rules}) |
863
|
|
|
|
|
|
|
} else { |
864
|
0
|
|
|
|
|
|
"" |
865
|
|
|
|
|
|
|
} |
866
|
|
|
|
|
|
|
} |
867
|
|
|
|
|
|
|
} |
868
|
|
|
|
|
|
|
|
869
|
|
|
|
|
|
|
sub _compact_id { |
870
|
0
|
|
|
0
|
|
|
my ($self, $cat, $id) = @_; |
871
|
0
|
0
|
|
|
|
|
if (exists($self->{yaml}{"$cat-TAG"}{$id})) { |
872
|
0
|
|
|
|
|
|
return $self->{yaml}{"$cat-TAG"}{$id} |
873
|
|
|
|
|
|
|
} else { |
874
|
0
|
|
|
|
|
|
return $id |
875
|
|
|
|
|
|
|
} |
876
|
|
|
|
|
|
|
} |
877
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
|
879
|
|
|
|
|
|
|
=head2 featags |
880
|
|
|
|
|
|
|
|
881
|
|
|
|
|
|
|
Given a word, returns a set of analysis. Each analysis is a morphosintatic tag |
882
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
@l= $pt->featags("lindas") |
884
|
|
|
|
|
|
|
JFS , ... |
885
|
|
|
|
|
|
|
@l= $pt->featags("era",{CAT=>"v"}) ## with a constraint |
886
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
=cut |
889
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
sub featags{ |
891
|
0
|
|
|
0
|
1
|
|
my ($self, $palavra,@Ar) = @_; |
892
|
0
|
|
|
|
|
|
return (map {_cat2small(%$_)} ($self->fea($palavra,@Ar))); |
|
0
|
|
|
|
|
|
|
893
|
|
|
|
|
|
|
} |
894
|
|
|
|
|
|
|
|
895
|
|
|
|
|
|
|
=head2 featagsrad |
896
|
|
|
|
|
|
|
|
897
|
|
|
|
|
|
|
Given a word, returns a set of analysis. Each analysis is a morphosintatic tag |
898
|
|
|
|
|
|
|
and the lemma information |
899
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
@l= $pt->featagsrad("lindas") |
901
|
|
|
|
|
|
|
JFS:lindo , ... |
902
|
|
|
|
|
|
|
@l= $pt->featagsrad("era",{CAT=>"v"}) ## with a constraint |
903
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
=cut |
905
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
sub featagsrad{ |
907
|
0
|
|
|
0
|
1
|
|
my ($self, $palavra,@Ar) = @_; |
908
|
|
|
|
|
|
|
|
909
|
0
|
|
|
|
|
|
return (map {_cat2small(%$_).":$_->{rad}"} ($self->fea($palavra,@Ar))); |
|
0
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
} |
911
|
|
|
|
|
|
|
|
912
|
|
|
|
|
|
|
|
913
|
|
|
|
|
|
|
=head2 onethatverif |
914
|
|
|
|
|
|
|
|
915
|
|
|
|
|
|
|
Given a pattern feature structure and a list of analysis (feature |
916
|
|
|
|
|
|
|
structures), returns a true value is there is one analysis that |
917
|
|
|
|
|
|
|
verifies the pattern. |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
# onethatverif( cond:fs , conj:fs-set) :: bool |
920
|
|
|
|
|
|
|
# exists x in conj: verif(cond , x) |
921
|
|
|
|
|
|
|
|
922
|
|
|
|
|
|
|
if(onethatverif({CAT=>"adj"},$pt->fea("linda"))) { |
923
|
|
|
|
|
|
|
... |
924
|
|
|
|
|
|
|
} |
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
=cut |
927
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
sub onethatverif { |
929
|
0
|
|
|
0
|
1
|
|
my ($a, @b) = @_; |
930
|
0
|
|
|
|
|
|
for (@b) { |
931
|
0
|
0
|
|
|
|
|
return 1 if verif($a,$_); |
932
|
|
|
|
|
|
|
} |
933
|
0
|
|
|
|
|
|
return 0 ; |
934
|
|
|
|
|
|
|
} |
935
|
|
|
|
|
|
|
|
936
|
|
|
|
|
|
|
=head2 mkradtxt |
937
|
|
|
|
|
|
|
|
938
|
|
|
|
|
|
|
=cut |
939
|
|
|
|
|
|
|
|
940
|
|
|
|
|
|
|
sub mkradtxt { |
941
|
0
|
|
|
0
|
1
|
|
my ($self, $f1, $f2) = @_; |
942
|
0
|
|
|
|
|
|
local $.; |
943
|
0
|
0
|
|
|
|
|
open F1, $f1 or die "Can't open '$f1'\n"; |
944
|
0
|
0
|
|
|
|
|
open F2, "> $f2" or die "Can't create '$f2'\n"; |
945
|
0
|
|
|
|
|
|
while() { |
946
|
0
|
|
|
|
|
|
chomp; |
947
|
0
|
|
|
|
|
|
print F2 "$_$DELIM"; |
948
|
0
|
|
|
|
|
|
while (/((\w|-)+)/g) { |
949
|
0
|
0
|
|
|
|
|
print F2 " ",join(" ",$self->rad($1)) unless $STOP{$1} |
950
|
|
|
|
|
|
|
} |
951
|
0
|
|
|
|
|
|
print F2 "\n"; |
952
|
|
|
|
|
|
|
} |
953
|
0
|
|
|
|
|
|
close F1; |
954
|
0
|
|
|
|
|
|
close F2; |
955
|
|
|
|
|
|
|
} |
956
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
=head2 isguess |
958
|
|
|
|
|
|
|
|
959
|
|
|
|
|
|
|
Lingua::Jspell::isguess(@ana) |
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
returns True if list of analisys are near |
962
|
|
|
|
|
|
|
misses (unknown attribut is 1). |
963
|
|
|
|
|
|
|
|
964
|
|
|
|
|
|
|
=cut |
965
|
|
|
|
|
|
|
|
966
|
|
|
|
|
|
|
sub isguess{ |
967
|
0
|
|
|
0
|
1
|
|
my @a=@_; |
968
|
0
|
|
0
|
|
|
|
return @a && $a[0]{unknown}; |
969
|
|
|
|
|
|
|
} |
970
|
|
|
|
|
|
|
|
971
|
|
|
|
|
|
|
=head2 any2str |
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
Lingua::Jspell::any2str($ref) |
974
|
|
|
|
|
|
|
Lingua::Jspell::any2str($ref,$indentation) |
975
|
|
|
|
|
|
|
Lingua::Jspell::any2str($ref,"compact") |
976
|
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
=cut |
978
|
|
|
|
|
|
|
|
979
|
|
|
|
|
|
|
sub any2str { |
980
|
0
|
|
|
0
|
1
|
|
my ($r, $i) = @_; |
981
|
0
|
|
0
|
|
|
|
$i ||= 0; |
982
|
0
|
0
|
|
|
|
|
if (not $r) {return ""} |
|
0
|
|
|
|
|
|
|
983
|
0
|
0
|
|
|
|
|
if (ref $i) { any2str([@_]);} |
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
984
|
|
|
|
|
|
|
elsif ($i eq "compact") { |
985
|
0
|
0
|
|
|
|
|
if (ref($r) eq "HASH") { |
|
|
0
|
|
|
|
|
|
986
|
0
|
|
|
|
|
|
return "{". hash2str($r,$i) . "}" |
987
|
|
|
|
|
|
|
} elsif (ref($r) eq "ARRAY") { |
988
|
0
|
|
|
|
|
|
return "[" . join(",", map (any2str($_,$i), @$r)) . "]" |
989
|
|
|
|
|
|
|
} else { |
990
|
0
|
|
|
|
|
|
return "$r" |
991
|
|
|
|
|
|
|
} |
992
|
|
|
|
|
|
|
} elsif ($i eq "f1") { |
993
|
0
|
0
|
|
|
|
|
if (ref($r) eq "HASH") { |
|
|
0
|
|
|
|
|
|
994
|
0
|
|
|
|
|
|
return "{". hash2str($r,"f1") . "}" |
995
|
|
|
|
|
|
|
} elsif (ref($r) eq "ARRAY") { |
996
|
0
|
|
|
|
|
|
return "[ " . join(" ,\n ", map (any2str($_,"compact"), @$r)) . "]" |
997
|
|
|
|
|
|
|
} else { |
998
|
0
|
|
|
|
|
|
return "$r" |
999
|
|
|
|
|
|
|
} |
1000
|
|
|
|
|
|
|
} else { |
1001
|
0
|
0
|
|
|
|
|
my $ind = ($i >= 0)? (" " x $i) : ""; |
1002
|
0
|
0
|
|
|
|
|
if (ref($r) eq "HASH") { |
|
|
0
|
|
|
|
|
|
1003
|
0
|
|
|
|
|
|
return "$ind {". hash2str($r,abs($i)+3) . "}" |
1004
|
|
|
|
|
|
|
} elsif (ref($r) eq "ARRAY") { |
1005
|
0
|
|
|
|
|
|
return "$ind [\n" . join("\n", map (any2str($_,abs($i)+3), @$r)) . "]" |
1006
|
|
|
|
|
|
|
} else { |
1007
|
0
|
|
|
|
|
|
return "$ind$r" |
1008
|
|
|
|
|
|
|
} |
1009
|
|
|
|
|
|
|
} |
1010
|
|
|
|
|
|
|
} |
1011
|
|
|
|
|
|
|
|
1012
|
|
|
|
|
|
|
=head2 hash2str |
1013
|
|
|
|
|
|
|
|
1014
|
|
|
|
|
|
|
=cut |
1015
|
|
|
|
|
|
|
|
1016
|
|
|
|
|
|
|
sub hash2str { |
1017
|
0
|
|
|
0
|
1
|
|
my ($r, $i) = @_; |
1018
|
0
|
|
|
|
|
|
my $c = ""; |
1019
|
0
|
0
|
|
|
|
|
if ($i eq "compact") { |
|
|
0
|
|
|
|
|
|
1020
|
0
|
|
|
|
|
|
for (keys %$r) { |
1021
|
0
|
|
|
|
|
|
$c .= any2str($_,$i). "=". any2str($r->{$_},$i). ","; |
1022
|
|
|
|
|
|
|
} |
1023
|
0
|
|
|
|
|
|
chop($c); |
1024
|
|
|
|
|
|
|
} elsif ($i eq "f1") { |
1025
|
0
|
|
|
|
|
|
for (keys %$r) { |
1026
|
0
|
|
|
|
|
|
$c .= "\n ". any2str($_,"compact"). "=". any2str($r->{$_},"compact"). "\n"; |
1027
|
|
|
|
|
|
|
} |
1028
|
0
|
|
|
|
|
|
chop($c); |
1029
|
|
|
|
|
|
|
} else { |
1030
|
0
|
|
|
|
|
|
for (keys %$r) { |
1031
|
0
|
|
|
|
|
|
$c .= "\n". any2str($_,$i). " => ". any2str($r->{$_},-$i); |
1032
|
|
|
|
|
|
|
} |
1033
|
|
|
|
|
|
|
} |
1034
|
0
|
|
|
|
|
|
return $c; |
1035
|
|
|
|
|
|
|
} |
1036
|
|
|
|
|
|
|
|
1037
|
|
|
|
|
|
|
=head1 AUTHOR |
1038
|
|
|
|
|
|
|
|
1039
|
|
|
|
|
|
|
Jose Joao Almeida, C<< >> |
1040
|
|
|
|
|
|
|
Alberto Simões, C<< >> |
1041
|
|
|
|
|
|
|
|
1042
|
|
|
|
|
|
|
=head1 BUGS |
1043
|
|
|
|
|
|
|
|
1044
|
|
|
|
|
|
|
Please report any bugs or feature requests to |
1045
|
|
|
|
|
|
|
C, or through the web interface at |
1046
|
|
|
|
|
|
|
L. I |
1047
|
|
|
|
|
|
|
will be notified, and then you'll automatically be notified of |
1048
|
|
|
|
|
|
|
progress on your bug as I make changes. |
1049
|
|
|
|
|
|
|
|
1050
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
1051
|
|
|
|
|
|
|
|
1052
|
|
|
|
|
|
|
Copyright 2007-2009 Projecto Natura |
1053
|
|
|
|
|
|
|
|
1054
|
|
|
|
|
|
|
This program is free software; licensed under GPL. |
1055
|
|
|
|
|
|
|
|
1056
|
|
|
|
|
|
|
=cut |
1057
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
sub _yaml_file { |
1059
|
0
|
|
|
0
|
|
|
my $dic_file = shift; |
1060
|
0
|
0
|
|
|
|
|
if ($dic_file =~ m!\.hash$!) { |
1061
|
|
|
|
|
|
|
# we have a local dictionary |
1062
|
0
|
|
|
|
|
|
$dic_file =~ s/\.hash/.yaml/; |
1063
|
|
|
|
|
|
|
} else { |
1064
|
0
|
|
|
|
|
|
$dic_file = "$JSPELLLIB/$dic_file.yaml" |
1065
|
|
|
|
|
|
|
} |
1066
|
0
|
|
|
|
|
|
return $dic_file; |
1067
|
|
|
|
|
|
|
} |
1068
|
|
|
|
|
|
|
|
1069
|
|
|
|
|
|
|
sub _mode { |
1070
|
0
|
|
|
0
|
|
|
my $m = shift; |
1071
|
0
|
|
|
|
|
|
my $r=""; |
1072
|
0
|
0
|
|
|
|
|
if ($m->{nm}) { |
1073
|
0
|
0
|
|
|
|
|
if ($m->{nm} eq "af") ### af = GPy --> Gym |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
1074
|
0
|
|
|
|
|
|
{ $r .= "\$G\n\$m\n\$y\n" } |
1075
|
|
|
|
|
|
|
elsif ($m->{nm} eq "full") ### full = GYm |
1076
|
0
|
|
|
|
|
|
{ $r .= "\$G\n\$Y\n\$m\n" } |
1077
|
|
|
|
|
|
|
elsif ($m->{nm} eq "cc") ### cc = GPY |
1078
|
0
|
|
|
|
|
|
{ $r .= "\$G\n\$P\n\$Y\n" } |
1079
|
|
|
|
|
|
|
elsif ($m->{nm} eq "off") ### off = gPy |
1080
|
0
|
|
|
|
|
|
{ $r .= "\$g\n\$P\n\$y\n" } |
1081
|
|
|
|
|
|
|
else {} |
1082
|
|
|
|
|
|
|
} |
1083
|
0
|
0
|
|
|
|
|
if ($m->{flags}) {$r .= "\$z\n"} |
|
0
|
|
|
|
|
|
|
1084
|
0
|
|
|
|
|
|
else {$r .= "\$Z\n"} |
1085
|
0
|
|
|
|
|
|
return $r; |
1086
|
|
|
|
|
|
|
} |
1087
|
|
|
|
|
|
|
|
1088
|
|
|
|
|
|
|
|
1089
|
|
|
|
|
|
|
sub _irr_file { |
1090
|
0
|
|
|
0
|
|
|
my $irr_file = shift; |
1091
|
0
|
0
|
|
|
|
|
if ($irr_file =~ m!\.hash$!) { |
1092
|
|
|
|
|
|
|
# we have a local dictionary |
1093
|
0
|
|
|
|
|
|
$irr_file =~ s/\.hash/.irr/; |
1094
|
|
|
|
|
|
|
} else { |
1095
|
0
|
|
|
|
|
|
$irr_file = "$JSPELLLIB/$irr_file.irr" |
1096
|
|
|
|
|
|
|
} |
1097
|
0
|
|
|
|
|
|
return $irr_file; |
1098
|
|
|
|
|
|
|
} |
1099
|
|
|
|
|
|
|
|
1100
|
|
|
|
|
|
|
|
1101
|
|
|
|
|
|
|
|
1102
|
|
|
|
|
|
|
|
1103
|
|
|
|
|
|
|
'\o/ yay!'; # End of Lingua::Jspell |
1104
|
|
|
|
|
|
|
|
1105
|
|
|
|
|
|
|
__END__ |