#!/usr/bin/perl -w
#todo: subtitle masih mengandung singkatan, mis: "bagai minyak dng air". ini dari kbbi sendiri.
#todo: babylon support tag apa aja selain
?
use strict;
use Data::Dumper;
use HTML::Entities;
use List::MoreUtils qw/uniq/;
=head1 DESCRIPTION
format babylon dapat diinput ke stardict-editor untuk dijadikan
dictionary stardict. selain format babylon terdapat juga format tab
tapi tidak support alias.
=head1 FORMAT HTML
LEMA:lerang (1)
1le·rang /lérang/ n jalur tepi (pd kain batik atau tenun); setrip; pias
LEMA:lerang (2)
2le·rang /lérang/, le·rang-le·rang n tandu; usungan
LEMA adalah akar kata. homograf dipisah dalam entri berbeda (contoh di
atas). untuk stardict gw ingin menyatukan kedua entri di atas dalam 1
entri.
setiap baris adalah "subentri" bisa berisi varian: ditambahi imbuhan
(men-cari), peribahasa (main air basah main api hangus, pb), kiasan,
frase dua kata. sebelnya, dalam satu baris bisa ada lebih dari satu
untuk yang mengandung --.
resenya, ";" dipakai sebagai pemisah subentri dan juga pemisah arti
dalam 1 subentri yang sama. lalu atau juga ditutupnya kadang
gak pas. mis: ~ teritorial 1 definisi 1 2 definisi
2... tanda2x dibuatnya di word processor (ms word maybe).
LEMA:abdi
ab·di n 1 orang bawahan; pelayan; hamba; 2 budak tebusan;
-- dalem Jw pegawai keraton; -- masyarakat pegawai pemerintah yg pada dasarnya mempunyai kewaj...;
meng·ab·di v menghamba; menghambakan diri; berbakti: mereka berjanji akan benar-benar ~ ...
meng·ab·di·kan v 1 menjadikan diri abdi; memperhambakan: kami ~ diri kpd ...
peng·ab·di n orang yg mengabdi: jangan kamu menjadi ~ harta benda; ...
peng·ab·di·an n proses, cara, perbuatan mengabdi atau mengabdikan: ia memperlih ...
untuk stardict, gw ingin membuatkan entri terpisah untuk setiap
subentri tersebut.
=head1 FORMAT TAB
lerang|baris pertama\nbaris kedua
jika ingin encode "\" literal, gunakan "\\".
teks dalam encoding UTF8.
=head1 FORMAT BABYLON
lerang
arti pertama
arti kedua
abdi|abdi dalem|mengabdi|pengabdi|pengabdian
bla bla bla
=cut
my $mdash_sub;
my $tilde_sub;
# subentri2x yg sudah diketahui sebetulnya adalah contoh kalimat
my @kalimat = (
' paham: ~ terlarang',
'rupanya orang-orang di kampung ini kurang --',
' pohon -- yg kautanam?',
'seorang -- muda ingin memperistrinya',
' kantor pos --',
'Amarantus',
'-- sayangnya kpd kekasihnya sehingga dia tega',
' usahanya adalah menjual dan membeli mobil --',
'Mugil cephalus',
'Picidae (banyak macamnya spt',
'Alocasia indica (ada bermacam-macam',
'Erythrina (ada bermacam-macam',
'Dyena costulata, ada banyak macam',
'Colocasia esculenta (ada bermacam-macam',
'Cucurbitaceae (banyak macamnya',
'Cyprus rotundus, banyak macamnya',
' Scomberomorus (jenisnya bermacam-macam',
'Solanum melongena (spt',
'Ipomoea batatas (banyak macamnya',
' (ada bermacam-macam, spt -- belanda',
'belum terbayang dl -- saya, bagaimana memecahkan persoalan itu',
' Ayah tidak kuasa menahan -- nya melihat anaknya dipukul orang',
' kalau penyakit sudah -- susah diobati',
'-- nya gelap buruk nasibnya (sial, tidak beruntung)',
' -- tembaga',
'-- melati',
'pipanya sampai ~ krn tidak pernah dibersihkan',
' rumah ini hanya -- untuk restoran',
' ban mobil itu --',
'lantainya ~',
'~ tuah untung-untungan saja',
'-- kesenian daerah dl rangka peringatan 17 Agustus',
'~ perahu yg rusak',
'ia sudah tidak ~ lagi, ia sudah tidak berkuasa',
' ~ waktu',
'-- kuda dng bunyi tembakan (melatih',
' -- tenang, jangan gelisah',
' -- panas',
' tetap bergerak terus: arloji saya masih',
'-- , -- bendi, putih, putih sadah, pb', # sambungan peribahasa sebelumnya
'~ tak cukup sebelit pinggang; tak ~ sehelai benang', # sambungan peribahasa sebelumnya
'-- makan perut lapar), pb', # sambungan peribahasa sebelumnya
'-- tongkat bertelekan), pb', # sambungan peribahasa sebelumnya
'~ muka dng tedung, pb', # sambungan peribahasa sebelumnya
'hantu ~; perempuan ~; laki-laki ~',
'dia merasa ~ dng peraturan baru itu',
'apakah pekerjaanmu kemari hanya untuk ~ ?',
'Argusianus argus (ada bermacam-macam spt',
' -- karang',
'~ hak demokrasi',
'~ modal, kita bisa gulung tikar',
'obat ~',
'gi: sekrupnya --', # terjadi pemotongan pada "la-gi"
'sebelum praktik mengajar, para calon guru mengadakan -- ke sekolah-sekolah',
'~ ikan',
'-- hatinya krn temannya tidak menepati janjinya',
'dng --',
' berlekuk-lekuk: memakai topi yg ~',
'apa -- dimakannya (jua)',
'~ muatan',
'air ~ pd bagian sungai yg dalam',
' ~ kejadian yg satu dng kejadian yg lain',
'~ hasil rapat',
'alam (jagat) --',
' -- madat',
' -- pondoh salak yg berbuah kecil-kecil, rasanya gurih dan manis',
'kabar --',
'cerita --',
' (menurut jurusannya, ada) -- dagang',
'-- nanas',
'Bhinneka Tunggal Ika ialah -- Republik Indonesia',
'seniman tari sering juga menciptakan -- susastra yg indah',
'-- melejang',
'-- Eropa',
'-- babi',
'berpesan: neneknya ~ kpd cucu-cucunya agar mereka rukun',
'dr -- yg halus dapat dibuat pakaian yg halus pula',
'c bahan tertulis untuk dasar memberikan pelajaran',
'~ muka dan bertukar pikiran dng golongan tua telah diadakannya',
' -- rumah',
' menyajikan: pengarang itu ~ gagasannya dl karangannya',
'kakak ~ saya menjaga anak-anak di rumah',
'dl surat ini ~ surat Pak Guru',
'mereka ~ rukun Islam yg kelima, yaitu melaksanakan ibadah haji',
'~ daun johar',
'-- , siapa nama gurumu?',
'-- lampu',
'-- kuk ke leher lembu',
'',
);
my $kalimat_re = join "|", map { quotemeta($_) } grep {/\S/} @kalimat;
$kalimat_re = qr/^(?:$kalimat_re)/;
sub info($) { print STDERR "INFO: $_[0]\n" }
sub debug($) { print STDERR "DEBUG: $_[0]\n" }
sub strip_hyphenations {
local $_ = shift;
s/\xb7//g;
$_;
}
sub process_title {
local $_ = shift;
#s/·//g;
$_ = decode_entities($_);
if (/--/) { die "BUG#4: mdash_sub is undefined!" unless defined($mdash_sub); s/--/$mdash_sub/g; }
if (/~/) { die "BUG#5: tilde_sub is undefined!" unless defined($tilde_sub); s/~/$tilde_sub/g; }
s!^\s*\d+\s*!!;
s/<[^>]+>//g;
s/^\d+//;
s/\s\d+$//;
s/\s+$//; s/^\s+//;
die "BUG#6: title is empty!" unless /\S/;
s/,$//;
#die "BUG#7: title mengandung koma di akhir!" if /,\s*$/;
$_;
}
{
local $/ = undef;
$_ = <>;
info "ukuran html mentah: ".length($_);
# bekas2x ms word/wordprocessor
s!<([bi])>(\s*)\1>!$2!sg;
s!([bi])>(\s*)<\1>!$2!sg;
}
my @raw_entries;
my $i;
while (m!^LEMA:([^<]+)
\s+(.+?)^
!msg) {
push @raw_entries, [++$i, $1, $2];
}
info "jumlah entri: ".@raw_entries;
#debug Dumper @raw_entries;
my %entries;
for my $r (@raw_entries) {
my $i = $r->[0];
my $title0 = $r->[1];
my $def = $r->[2];
info "memroses entri #$i: $title0 ...";
my $title = lc $title0;
$title =~ s/ \(\d+\)//;
$mdash_sub = $title;
$tilde_sub = $title;
# -- kadang ditulis -, sucks
$def =~ s!>- !>-- !g;
$def =~ s! - ! -- !g;
$def =~ s! -)?\n?
|;\s*(?=--)|;\s*(?=~)|;\s*(?=<)!, $def;
#debug Dumper(\@subentries);
for (my $i=0; $i<@subentries; $i++) {
next if $i == 0;
my $alasan = "";
my $s = $subentries[$i];
if ($s =~ m!^(?:\s*)?\s*\d+\s*!) { $alasan = "arti lain" }
elsif ($s !~ m!~|--|·!) { $alasan = "contoh kalimat" }
elsif ($s =~ m!^[^<]+$!) { $alasan = "contoh kalimat (2)" }
elsif ($s =~ m!^.+?$! && $s !~ /·/) { $alasan = "contoh kalimat (3)" }
elsif ($s =~ m!^[^<]+$!) { $alasan = "contoh kalimat (4)" }
elsif ($s =~ $kalimat_re) { $alasan = "contoh kalimat (manual)" }
next unless $alasan;
#debug "menggabungkan [".$subentries[$i-1]."] dan [".$subentries[$i]."] karena $alasan";
$subentries[$i-1] .= "; ".$subentries[$i];
splice @subentries, $i, 1;
$i--;
}
debug Dumper(\@subentries);
my @aliases;
my $j;
for my $se (@subentries) {
$se =~ s!-!-!g; # oleh kbbi foo-bar diformatnya foo-bar
my $raw_subtitle;
my $subtitle;
my $subtype;
my $subdef;
$j++;
$se =~ s!^!!;
$se =~ s!^\s*!!;
if ($se =~ m!^((?:--|~)?(?:)(?:\s*\d+\s*)?[^<]+)\s*(?:/[^/]+/)?\s*\s*([^<]+)\s*\s*(.+)\s*!) {
$raw_subtitle = $1;
$subtitle = process_title($1);
$subtype = $2;
$subdef = $3;
$tilde_sub = $subtitle if $raw_subtitle =~ /·/;
if ($j == 1 && $subdef =~ /(\S+·\S+)/) {
my $t2 = process_title($1);
$mdash_sub = $t2;
$tilde_sub = $t2;
}
} elsif ($se =~ m!^((?:--|~)?.+?), (?:)?(pb|pb Mk|ki|ki kas)\s*\s*(.+)!) {
$raw_subtitle = $1;
$subtitle = process_title($1);
$subtype = $2;
$subdef = $3;
} elsif ($se =~ m!^(?:)?((?:--)?(?:\s*\d+\s*)?[^<]+)\s*(.+)\s*!) {
$raw_subtitle = $1;
$subtitle = process_title($1);
$subtype = "";
$subdef = $2;
$tilde_sub = $subtitle if $raw_subtitle =~ /·/;
} elsif ($se =~ m!^((?:~)?\s*(?:)?[^<]+)\s*(.+)\s*!) {
$raw_subtitle = $1;
$subtitle = process_title($1);
$subtype = "";
$subdef = $2;
# yang gak pas
if ($subtitle =~ /(\d+)$/) {
$subdef = "$1 $subdef";
$subtitle =~ s/\d+$//;
}
$tilde_sub = $subtitle if $raw_subtitle =~ /·/;
} elsif ($se =~ m!^((?:--|~)?(?:)?[^<]+)\s*(.+)!) {
$raw_subtitle = $1;
$subtitle = process_title($1);
warn "BUG#1: salah tangkap contoh menjadi subentri?: $se" unless $raw_subtitle =~ /--|~/;
next;
$subtype = "";
$subdef = $2;
} elsif ($se =~ m!^((?:\d+)?[^<]+?)\s*(?:/[^/]+/)?\s*\? ([^<]+)(?:)?$!) {
# variasi ejaan
$raw_subtitle = $1;
$subtitle = process_title($1);
$subtype = "Lihat {".strip_hyphenations(process_title($2))."}";
$subdef = "";
} else {
warn "BUG#2: gagal parsing subentri $j: `$se'";
next;
}
info "memroses subentri #$j: [$raw_subtitle] ($subtitle) [$subtype] [$subdef] ...";
my $sts = strip_hyphenations($subtitle);
do { warn "BUG#3: kemungkinan ada 2 subentri yang masih tergabungkan"; next }
if $subdef =~ /·/ && $title ne $sts && $sts !~ /^(sedua|menetal|setungging|rubu, merubu)$/;
# peribahasa kan panjang2x?
#warn "BUG#8: kemungkinan salah, title terlalu panjang? title=$subtitle" if length($subtitle) > 25;
$entries{$subtitle} ||= {aliases=>[], defs=>[]};
push @{ $entries{$subtitle}{aliases} }, $subtitle;
if ($subtype) {
$subtype =~ s/,\s*$//;
$subdef = "[$subtype] $subdef";
}
push @{ $entries{$subtitle}{defs} }, $subdef;
}
}
#debug Dumper \%entries; exit;
# output
for my $e (sort keys %entries) {
my @aliases = uniq @{ $entries{$e}{aliases} };
my $type = $entries{$e}{type};
my $defs = $entries{$e}{defs};
for (@$defs) {
s/\n//g;
s!\s*(\d+)\s*!"($1)"!eg;
$_ = decode_entities($_);
s/<[^>]+>//g;
tr/\xe9\x97\x93\x94\xb4\xfe\xb7/E\-""'p./; # XXX: stardict kok gak mau nampilin \xe9 dll ya, kan UTF8?
s!\xBD!1/2!g;
s!\xBC!1/4!g;
s!\x96!--!g;
s!\xe2!a^!g;
s!\xfb!u^!g;
s!\xe4!a:!g;
s!\x89!permil!g;
#die "$e: Definisi masih mengandung karakter aneh: $_" if /[^\x00-\x7f]/;
}
print join("|", map { strip_hyphenations($_) } @aliases), "\n";
my $ee = $e; $ee =~ s/\xb7/./g; # stardict gak mau nampilin \xb7?
print "$ee
" if $ee ne $e;
print join "
", @$defs;
print "\n\n";
}