BAB III
PERANCANGAN
3.1 Spesifikasi bahasa DOGI
3.1.1 Token
Karakter-karakter yang diijinkan dipakai dalam bahasa DOGI adalah sembarang karakter selain karakter kontrol, dalam set karakter ASCII. DOGI tidak mendukung penggunaan karakter-karakter unicode. Carriage return, line feed, dan tab dianggap sebagai white space. Frasa “sembarang karakter” yang digunakan selanjutnya akan selalu berarti “sembarang karakter dalam set karakter yang diijinkan bahasa DOGI”.
A. Kata kunci
Kata-kata kunci yang digunakan oleh DOGI adalah:
package imports exports class access interface method property hidden
visible get set new kill begin end B. Pengenal (identifier)
Pengenal (identifier) dalam bahasa DOGI dimulai dengan huruf atau garis bawah atau @. Setiap karakter selanjutnya bisa merupakan salah satu dari huruf, garisbawah, @ maupun angka, tidak dibatasi panjangnya. Pengenal dalam bahasa DOGI tidak membedakan huruf besar maupun kecil (bersifat case-insensitive).
Contoh nama-nama pengenal:
dogi anjing si_manis @anak_dogi_1 bopi@home C. Literal
Literal merepresentasikan data. Bahasa DOGI mengenal tujuh macam literal, yaitu null, integer, floating-point, string, boolean, array dan code.
Null
Literal null tidak merepresentasikan data secara konkret. Null digunakan untuk menandai bahwa suatu nama tidak mereferensikan objek apa pun, walaupun itu
berarti nama tersebut mereferensikan sebuah objek – yaitu objek null sendiri. Null merupakan instansiasi dari kelas void. Dituliskan sebagai #null.
Integer
Literal integer merupakan representasi dari bilangan bulat. Literal integer sendiri terdiri dari dua macam representasi, yaitu desimal dan heksadesimal. Literal desimal terdiri dari barisan angka-angka yang panjangnya tidak dibatasi (walaupun aturan semantik akan membatasi nilainya, yang tergantung pada arsitektur komputer saat ini). Literal heksadesimal diawali dengan 0x, dilanjutkan dengan barisan angka maupun salah satu huruf a sampai f tanpa dibedakan huruf besar maupun kecil. Literal integer merupakan instansiasi dari kelas int. Graf sintaks untuk digit desimal, digit heksadesimal, dan literal integer dapat dilihat pada Gambar 3.1, Gambar 3.2, dan Gambar 3.3.
digit 0 1 2 3 4 5 6 7 8 9
hexdigi t digit A F E D C B
Gambar 3.2 Graf sintaks untuk digit heksadesimal
integer digit
hexdigit
0 x
Gambar 3.3 Graf sintaks untuk literal integer
Contoh-contoh literal integer:
2152332
3154258763248678 0x42AB38C
0x32cFf
Floating-point
Literal floating-point merupakan representasi dari bilangan real, dan instansiasi dari kelas real. Literal floating-point terdiri dari beberapa bagian, yaitu bagian integer, titik desimal, bagian pecahan dan eksponen.
Pembentukan literal floating-point yang valid adalah
• Eksponen diawali huruf E atau e, diikuti langsung dengan angka-angka, atau bisa juga dengan plus atau minus, diikuti angka-angka.
• Bagian integer diikuti langsung dengan eksponen, atau
• Bagian integer diikuti dengan titik desimal, bagian pecahan, dan bisa diikuti oleh eksponen maupun tidak.
Graf sintaks untuk literal floating-point dapat dilihat pada Gambar 3.4.
Floating-point . E
+
-digit digit digit
Gambar 3.4 Graf sintaks untuk literal floating-point
Contoh-contoh literal floating-point:
124.12525 3.2 0.52e23 325.253e-004 5321124.4e+2 String
Literal string adalah barisan sembarang karakter (kecuali tanda kutip ganda), di antara dua tanda kutip ganda (“). Backslash (\) digunakan sebagai karakter escape, untuk menyatakan karakter kontrol ataupun karakter lainnya. Literal string merupakan instansiasi dari kelas string. Graf sintaks untuk karakter tunggal, karakter, dan string dapat dilihat pada Gambar 3.5, Gambar 3.6, Gambar 3.7, sedangkan daftar karakter escape dapat dilihat pada Tabel 3.1.
\b Backspace \t Tabulasi \n line feed \f Form feed \r carriage return \” kutip ganda \\ Backslash
\m## mengulang karakter sebelumnya sebanyak ## \u#### karakter unicode nomor ####
\0x## karakter ASCII nomor ##
Tabel 3.1 Karakter-karakter escape yang berlaku
Contoh-contoh literal string:
“Aku gigi mulut rumahku”
“ \”Aku gigi mulut rumahku\” adalah string” “Aku\ngigi\nmulut\nrumahku\0x0D”
singlechar ! A ~ 0 9 Z a z ... ... ... ... ... ... ...
Gambar 3.5 Graf sintaks untuk karakter tunggal
singlechar m u hexdigit hexdigit 0 x Char \ singlechar
hexdigit hexdigit hexdigit hexdigit
Gambar 3.6 Graf sintaks untuk karakter
String “ “
char
Gambar 3.7 Graf sintaks untuk literal string
Boolean
Literal boolean hanya ada dua, yaitu #true dan #false. Sesuai namanya, #true menunjukkan nilai benar, dan #false menunjukkan nilai salah. Kedua
literal ini merupakan instansiasi dari kelas bool. Pemberian tanda # mempermudah pembedaan dari nama objek.
Array
Literal array merepresentasikan array, dan merupakan instansiasi dari kelas array. Literal array dituliskan sebagai daftar yang dipisahkan tanda koma, dan dituliskan di antara tanda kurung kurawal. Graf sintaks untuk array dapat dilihat pada Gambar 3.8.
expr
array { }
,
Gambar 3.8 Graf sintaks untuk literal array Contoh-contoh literal array:
{ 5, 2, 9, 4, 3, 2 }
{ console.writeln(3), Count()+2, 2+4*con_9, #false } { [ 5-f ], #true, { 5, 4, { 3, 2 }, 4 }, “abcde” }
Code
Dalam bahasa DOGI terdapat tambahan literal yang lain, yaitu kode (code). Sifatnya seperti block pada SmallTalk. Literal kode yang dituliskan dalam sebuah metoda tidak akan dieksekusi, melainkan dianggap sebagai objek instansiasi dari kelas code. Penulisannya selalu berada di antara kata begin..end untuk kode dengan nol atau lebih statement, dan di antara [ .. ] untuk kode dengan nol atau satu statement. Kode tidak secara otomatis dieksekusi. Graf sintaks untuk kode dapat dilihat pada Gambar 3.9.
code begin end [ ] exprList expr exprList expr ;
Gambar 3.9 Graf sintaks untuk literal code
Contoh-contoh berikut adalah literal code: begin dogi makan; end
begin out.write(“Guk!”); end D. Pemisah
Pemisah (separator) digunakan untuk memisahkan token-token. Daftar lengkap pemisah yang digunakan dapat dilihat pada Tabel 3.2 berikut.
( Berpasangan dengan ), digunakan untuk mengawali daftar parameter sebuah metoda, atau untuk memberikan presedensi bagi ekspresi
) Merupakan penutup bagi (
{ Berpasangan dengan }, digunakan untuk mengawali suatu literal array } Merupakan penutup bagi {
[ Berpasangan dengan ], digunakan untuk indexer (dicadangkan), maupun code dengan satu ekspresi
] Merupakan penutup bagi [ (dicadangkan)
dalam sebuah method. < juga digunakan sebagai operator. > Merupakan penutup bagi <, juga digunakan sebagai operator. ; Digunakan untuk memisahkan bagian-bagian dalam program DOGI , Pemisah dalam daftar
. Titik desimal, juga digunakan sebagai qualifier bagi objek
Tabel 3.2 Pemisah dalam bahasa DOGI
E. Operator
Operator adalah metoda. Operator tidak mendapat perlakuan khusus seperti pada bahasa-bahasa pemrograman lainnya. Operator hanyalah metoda yang diberi nama dengan simbol-simbol tertentu. Operator dibentuk dari satu atau sepasang simbol-simbol berikut dan masing-masing tidak didefinisikan.
= < > + - * / ! & | % ^ : ? \
Pasangan operator /* dan */ tidak dapat dipakai karena sudah dipakai sebagai tanda awal dan akhir komentar.
Contoh operator:
+ = += <<
F. White space
Karakter-karakter yang termasuk white space adalah spasi, tabulasi, new line, carriage return, dan line feed. Karakter-karakter tersebut diabaikan dalam proses kompilasi.
G. Komentar
Komentar dalam DOGI sama dengan yang dipakai pada bahasa C++. Ada dua jenis komentar, yaitu komentar satu baris, dan komentar bersarang (nested comment). Komentar satu baris diawali dengan tanda //, dan karakter-karakter berikutnya merupakan komentar sampai baris tersebut berakhir. Komentar bersarang diawali tanda /* dan diakhiri dengan */, tidak harus dituliskan dalam baris yang sama. Graf sintaks untuk komentar dapat dilihat pada Gambar 3.10.
c o m m e n t / * * /
/ / ↵
a n y c h a r a c t e r
s i n g l e c h a r
Gambar 3.10 Graf sintaks untuk komentar
Contoh komentar bersarang:
/* Komentar komentar komentar komentar komentar komentar komentar komentar komentar komentar komentar komentar */
Contoh komentar satu baris:
3.1.2 Struktur program
Suatu program dalam bahasa DOGI dibentuk oleh daftar kelas, antarmuka kelas, dan antarmuka. Masing-masing deklarasi dipisahkan oleh tanda titik koma (;). Deklarasi-deklarasi tersebut disatukan dalam package, yang dituliskan dalam sebuah file kode sumber. Sebuah file kode sumber DOGI dapat memiliki lebih dari sebuah package. Graf sintaks untuk kode sumber dalam bahasa DOGI dapat dilihat pada Gambar 3.11.
source package ;
Gambar 3.11 Graf sintaks untuk file program dalam bahasa DOGI
3.1.3 Package
Package adalah satuan paling kecil yang dapat dikompilasi secara mandiri. Sebuah package berisi daftar kelas, antarmuka kelas, dan antarmuka. Dituliskan dengan bentuk:
package <nama_package> begin <daftar_deklarasi> end;
Sebuah package dapat mengimpor antarmuka-antarmuka kelas dari package lain dengan menuliskan dalam daftar deklarasi:
imports <nama_package> . <nama_simbol> { ,
<nama_package> . <nama_simbol> } ;
Penulisan <nama_package>.* akan mengimpor semua nama yang diekspor oleh package yang dimaksud. Simbol-simbol yang dapat diimpor haruslah telah diekspor pada package yang bersangkutan, dengan menyebutkan:
exports <nama_simbol> { , <nama_simbol> } ;
Hanya antarmuka kelas (ditandai dengan kata kunci access) dan antarmuka (interface) yang dapat diekspor dan diimpor oleh sebuah package. Package tanpa nama adalah package yang tidak dapat diimpor oleh kelas manapun. Package tanpa nama adalah untuk package yang berisi program siap eksekusi, sehingga tidak perlu diimpor oleh kelas manapun. Kompiler DOGI untuk saat ini hanya mendukung satu package dalam sebuah file.
Graf sintaks untuk package dapat dilihat pada Gambar 3.12.
packageHeader package packageName
package packageHeader begin packageItems end
packageItems packageItem ; imports exports access interface class packageItem
3.1.4 Kelas
A. Deklarasi kelas
Sebuah kelas dideklarasikan menggunakan kata kunci class, diikuti nama kelas induk, diikuti nama kelas yang akan dibuat. Bagian ini dinamakan class declaration header, dan sudah cukup untuk mendeklarasikan sebuah kelas.
class <nama_akses> <nama_kelas> [ ( [ <nama_interface>
{ , <nama_interface> }] ) ]
Kelas yang dihasilkan dengan cara ini akan memiliki sifat sama persis dengan kelas induknya, yang memiliki visibilitas <nama_akses>. Modifikasi terhadap anggota-anggota kelas dapat dituliskan setelah declaration header, diawali kata begin dan diakhiri kata end.
<class_header> begin <daftar_anggota_kelas> end;
Graf sintaks untuk kelas dapat dilihat pada Gambar 3.13. Contoh deklarasi kelas:
class binatang anjing
…
// anggota-anggota kelas di sini …
classMember
property field method
class baseAccessName className
classHeader ( interfaceList )
interfaceList interfaceName ,
class classHeader begin classMember ; end
Gambar 3.13 Graf sintaks untuk class
B. Anggota-anggota kelas
Sebuah kelas memiliki lima macam anggota (class member) yaitu: • Field,
• Metoda (method),
• Konstruktor, yaitu metoda khusus yang bertugas untuk menciptakan instance.
• Destruktor, yaitu metoda khusus untuk menghapus instance yang sudah dibuat.
• Properti, yaitu antarmuka terhadap field/metoda dengan memperlakukannya sebagai nama objek.
C. Field
Field dideklarasikan dengan bentuk umum
[ field ] <nama_kelas> [*] <nama_field> { , [*] <nama_field> }
Penggunaan kata kunci field adalah optional. Tanda * dipakai sebagai tanda bahwa field yang bersangkutan tidak secara otomatis dialokasikan (dengan memanggil metoda new dari field yang bersangkutan), melainkan menunjuk pada #null.
Graf sintaksnya seperti pada Gambar 3.14.
field accessName fieldName
,
field *
Gambar 3.14 Graf sintaks untuk field
Contoh:
int umur; anjing * dogi;
field kucing si_manis, * si_putih; D. Metoda
Deklarasi metoda memiliki dua bagian, yaitu method signature dan kode. Method signature berupa nama kelas, diikuti nama metoda, diikuti daftar parameter yang dituliskan di antara tanda kurung.
<nama_kelas_hasil> <nama_metoda>
Deklarasinya berupa kata kunci method diikuti method signature. Jika diikuti dengan kode program, artinya metoda tersebut langsung diimplementasikan dalam kode-kode di dalamnya. Jika tidak, metoda tersebut dianggap sebagai metoda abstrak dan tidak boleh dipanggil sebelum diimplementasikan dalam kelas turunannya.
Kode program dituliskan di antara kata kunci begin dan end seperti pada bahasa Pascal. Objek-objek lokal dapat dituliskan di antara signature dan kodenya, diapit tanda < dan >.
method <method_signature>
[ < <nama_kelas> <nama_objek_lokal> , … > ]
begin <kode> end;
Selain dengan cara menuliskan barisan kode-kodenya, DOGI memiliki alternatif penulisan definisi metoda dengan menuliskan ekspresinya secara langsung, jika kode hanya terdiri dari sebuah ekspresi saja.
method <method_signature> [ < <nama_kelas>
<nama_objek_lokal> , … > ] = <ekspresi> ;
Dengan menambahkan titik pada nama metoda, metoda tersebut akan dianggap sebagai class method atau static method, yaitu metoda yang dikaitkan dengan nama kelas. Class method tidak dapat mengakses field yang dideklarasikan dalam kelas yang bersangkutan. Graf sintaks untuk metoda dapat dilihat pada Gambar 3.15.
accessName
methodSignature methodName ( declArgList )
. .new
kill ( )
declArgList accessName argName
,
method method methodSignature < localList >
begin exprList end = expr
localList accessName localName
,
;
Gambar 3.15 Graf sintaks untuk metoda
Contoh:
method int jumlah (int a, int b) < int hasil >
begin
hasil = a + b; return (hasil);
end;
method real kuadrat (int x) = x * x;
E. Konstruktor
Konstruktor adalah metoda khusus, berguna untuk menginstansiasikan sebuah kelas. Karena konstruktor adalah class method, maka nama konstruktor harus diawali titik. Konstruktor diijinkan untuk lebih dari satu dalam satu kelas, dibedakan berdasarkan signature-nya. Untuk field yang dialokasikan secara otomatis (tidak diberi tanda *), konstruktor akan mengalokasikan field tersebut dengan konstruktor .new() yang terdapat pada field tersebut. Graf sintaks untuk konstruktor dapat dilihat pada Gambar 3.15.
method .new ( [ <nama_kelas_parameter>
<nama_parameter> , … ] ) Contoh: method .new () begin … end;
method .new (int A) begin
…
end;
F. Destruktor
Berbeda dengan konstruktor, destruktor hanya diijinkan satu untuk setiap kelas, dan tidak menggunakan parameter. Destruktor digunakan untuk menghapus objek. Karena destruktor bukanlah class method, maka penamaannya tidak diawali tanda titik. Graf sintaks untuk destruktor dapat dilihat pada Gambar 3.15.
method kill ( ) Contoh: method kill() begin … end; G. Properti
Properti sebenarnya adalah penyingkatan dari penggunaan dua buah metoda yang berlaku sebagai getter (pengambil nilai) dan setter (pengeset nilai), disingkat penulisannya menjadi sebuah nama yang diperlakukan sebagai objek tunggal.
Properti dapat dideklarasikan menggunakan salah satu dari penulisan ini:
property <nama_akses> <nama_properti> = <nama_field> property <nama_akses> <nama_properti> [ get begin
<definisi_get> end ] [ set begin <definisi_set>
end]
property <nama_akses> <nama_properti> [ get =
<definisi_get> ] [ set = <definisi_set> ]
Graf sintaks untuk properti dapat dilihat pada Gambar 3.16. Contoh:
property int Count=fCount;
property TColor Color get = fColor set begin
fColor = Color; return (fColor);
getter get propertyDef
setter set propertyDef
propertyDef
expr
=
begin exprList end
< localList >
property property propertySignature
getter setter
getter setter
= fieldName
propertySignature accessName propertyName
Gambar 3.16 Graf sintaks untuk properti
H. Akses (access) atau antarmuka kelas (class interface)
Antarmuka kelas (class interface) atau disebut akses merupakan hal yang tidak terdapat dalam bahasa pemrograman OOP lainnya. Antarmuka kelas secara esensial merupakan visibilitas dari anggota-anggota kelas. Setiap anggota kelas yang didaftar dalam deklarasi class secara default memiliki visibilitas private, atau tidak dapat diakses oleh objek lain maupun kelas turunannya.
Setiap anggota kelas yang didaftar dalam antarmuka kelas secara default memiliki visibilitas public. Visibilitas public juga dapat diperoleh dengan memberi awalan visible. Jika diberi awalan hidden, artinya anggota kelas yang
bersangkutan memiliki visibilitas protected. Selain yang didaftar dalam antarmuka kelas, anggota kelas bersifat private.
Anggota-anggota yang dapat didaftar dalam antarmuka kelas hanya metoda dan properti saja (termasuk konstruktor dan destruktor). Field tidak dapat, untuk menjaga objek dari perubahan-perubahan yang tak terkendali.
Setiap anggota yang hendak di-publish didaftarkan signature-nya tepat seperti yang telah didaftarkan di deklarasi kelasnya. Hanya saja tidak ada ketentuan bahwa nama parameter harus sama persis dengan yang telah dituliskan dalam deklarasi kelas.
Antarmuka kelas atau akses dituliskan dengan header:
access <nama_kelas> [ <nama_antarmuka_kelas> ]
Sebuah kelas dapat memiliki lebih dari satu antarmuka. Jika nama antarmuka kelas tidak disebutkan, atau bahkan antarmuka untuk sebuah kelas tidak dibuat, dianggap antarmuka untuk kelas tersebut sama dengan nama kelasnya. Untuk setiap kelas selalu terdapat satu antarmuka yang namanya sama dengan nama kelasnya.
Untuk menurunkan sebuah kelas dari kelas lain, harus menyebutkan nama antarmukanya, dan bukan nama kelasnya. Anggota-anggota base class yang dapat diakses hanyalah yang disebutkan dalam antarmuka base class yang dipakai. Dengan demikian suatu kelas dapat memiliki banyak ‘muka’ untuk berhubungan dengan kelas lainnya.
Hal ini berguna salah satunya untuk menghemat jumlah kelas yang harus dibuat. Dalam VCL Delphi, untuk setiap komponen kontrol biasanya terdapat
komponen abstraknya. Misalnya terdapat komponen TListView turunan TCustomListView, yang pada deklarasinya hanya mengubah visibilitas anggota-anggota TCustomListView yang protected menjadi published. Dengan antarmuka kelas, tidak perlu dilakukan hal seperti itu. Cukup dibuat dua buah antarmuka untuk TCustomListView, yaitu TCustomListView dengan semua anggotanya hidden, dan TListView dengan semua anggotanya visible.
Penggunaan kata access dan bukan interface di sini dimaksudkan untuk mencadangkan dukungan abstraksi dengan interface.
Bentuk umum deklarasi antarmuka kelas adalah:
access <nama_kelas> [ <nama_antarmuka_kelas> ] begin
<daftar_anggota> end;
Graf sintaks untuk antarmuka kelas atau akses dapat dilihat pada Gambar 3.17.
access accessHeader begin accessMember ; end
accessMember hiddenMember visibleMember
hiddenMember hidden propertySignature methodSignature
visibleMember visible propertySignature methodSignature
accessHeader access className accessName
Contoh:
class TWinControl TCustomListView
property Items … ; property ViewStyle … ; end; access TCustomListView hidden Items; hidden ViewStyle; end;
access TCustomListView TListView
Items; ViewStyle;
end;
access TCustomListView TfixedStyleListView
visible Items; hidden ViewStyle;
end; 3.1.5 Ekspresi
Walaupun DOGI, seperti halnya bahasa pemrograman OOP lainnya, masih menggunakan gaya imperatif, namun cara penulisan kode programnya dibuat sedemikian rupa sehingga dapat mudah dipahami.
Setiap statement dalam DOGI merupakan sebuah ekspresi. Sebuah ekspresi merupakan operasi yang dilakukan terhadap sebuah objek, dengan mengirimkan pesan melalui metoda yang dimiliki objek tersebut. Satuan terkecil dari ekspresi hanya ada dua macam, yaitu objek dan metoda.
Suatu objek tunggal adalah elemen terkecil sebuah ekspresi. Objek tersebut dapat berupa objek dengan nama atau literal integer, floating-point, boolean, string, null, code atau array. Graf sintaks objek tunggal dapat dilihat pada Gambar 3.20.
Suatu term adalah bagian dari ekspresi yang dapat berupa objek, ekspresi lain di antara tanda kurung, properti dan pengiriman pesan. Berikut ini adalah kemungkinan bentuk-bentuk term. Graf sintaks untuk term dapat dilihat pada pada Gambar 3.19.
<objek_tunggal>
( <ekspresi> )
<term_lain>.<properti> <pengiriman_pesan>
Pengiriman pesan dapat berbentuk satu dari:
<term> [ <daftar_ekspresi> ]
<term> . <metoda> ( <daftar_ekspresi> ) <metoda> ( <daftar_ekspresi> )
. <metoda> ( <daftar_ekspresi> )
<operator> <objek_tunggal>
Sebuah ekspresi dapat berupa sebuah term maupun pengiriman pesan ekspresi kepada sebuah term. Graf sintaks untuk ekspresi dapat dilihat pada Gambar 3.18.
<term> <metoda> <ekspresi_lain> <term>
expr term method\ term
sendMsg term singleObject expr term property ) ( sendMsg term [ ] term . method ( ) . method argList argList ( argList ) term operator
Gambar 3.19 Graf sintaks untuk term
singleObject objectName className array code integer float string boolean null
Gambar 3.20 Graf sintaks untuk objek
Contoh-contoh ekspresi:
dogi.duduk().salam();
console << ”Hello” + “ “ + “world!”; e = (29 * 94)+(24-3*c);
if (a>b) then begin put() end else [ 4 ];
3.1.6 Package System
Package System berisi kelas-kelas dasar yang dipakai oleh DOGI. Package System tidak perlu diimpor secara eksplisit karena otomatis akan dipakai oleh kompiler DOGI. Setiap kelas dalam System memiliki dua buah antarmuka, yang
berbeda dengan awalan @. Antarmuka yang diberi awalan @ semua method dan propertinya bersifat hidden. Sebagai contoh, antarmuka void dan @void menunjuk pada kelas yang sama, berbeda dalam hal setiap anggota @void hidden dan ada anggota void yang bersifat visible. Selanjutnya hanya akan dibahas antarmuka yang bersifat visible.
A. Kelas void
Kelas void merupakan kelas induk dari semua kelas yang dibuat dalam program DOGI (seperi object dalam Java dan C#). Dinamakan void, dan bukan object, setidaknya dengan alasan-alasan berikut:
• Pada C, C++ dan Java void adalah tipe data yang tidak mengandung apa-apa. Perlakuan khusus terhadap void pada Java sepertinya tidak fair, karena sudah terdapat pembedaan kelas dengan tipe data, ditambah satu lagi “tipe data” void hanya untuk menunjukkan bahwa sebuah metoda tidak mengembalikan nilai. Karena itu dalam DOGI void dibuat sebagai kelas. Dan karena sifatnya yang tidak mengandung apa-apa, maka dibuatlah void sebagai kelas induk dari semuanya. Semua metoda dalam DOGI mengembalikan nilai. Jika tidak dituliskan secara eksplisit, nilai yang dikembalikan adalah #null.
• Istilah object lebih bersifat konkret. Sedangkan kelas merupakan abstraksi. Dengan demikian, istilah object seharusnya lebih tepat digunakan sebagai nama instance, daripada nama kelas.
• Berdasarkan filosofi creatio ex nihilo, atau Allah menciptakan segala sesuatu dari tidak ada menjadi ada. Demikian juga setiap kelas diturunkan dari “ketiadaan” void.
Konstruktor
Kelas void memiliki hanya satu konstruktor, yang dipanggil tanpa parameter. Tugasnya adalah menciptakan sebuah objek dari kelas yang memanggilnya.
Destruktor
Destruktor kelas void bertugas untuk menghapus objek yang telah dibuat menggunakan konstruktor. Destruktor hanya akan menghapus objek yang bersangkutan jika reference count dari objek tersebut telah mencapai nol. Dengan kata lain, tidak ada lagi nama yang menunjuk objek tersebut.
Metoda-metoda kelas void
Metoda-metoda dalam kelas void diperlihatkan dalam Tabel 3.3.
void self() mengacu pada instance yang sedang aktif, dengan akses kepada metoda-metoda kelas aktif
void base() mengacu pada instance yang sedang aktif, dengan akses kepada metoda-metoda kelas induk
int refcount() mengembalikan jumlah reference count int addRef() menambah reference count
int release() mengurangi reference count void = (void) sama dengan assign(void) void assign(void) mengkopi objek lain
void assignTo(void) menyediakan layanan jika objek lain berusaha mengkopi objek yang bersangkutan
void applyTo(void, int) menyediakan layanan jika objek lain berusaha melakukan operasi terhadap objek yang bersangkutan
void .refTo(void) mereferensikan nama pada suatu objek void .->(void) sama dengan refTo(void)
array : (void) menyediakan operasi bagi bentuk kondisi?a:b seperti pada bahasa C
void .return(void) mengembalikan alur program pada metoda pemanggil, dan mengembalikan suatu objek _if .if(bool) menguji suatu kondisi, digunakan untuk seleksi _loop while(code cond) perulangan dengan kondisi cond
_loop loop(int n) perulangan sebanyak nilai tertentu _loop for(int i, int a,
int b) perulangan dengan counter i, dari nilai a hingga b _loop foreach(void x,
array A) perulangan dengan membaca hingga akhir array array A dari awal
Tabel 3.3 Daftar metoda yang terdapat dalam kelas void
B. Kelas data
Kelas data dimaksudkan untuk menjadi kelas induk dari semua kelas yang bertugas menangani data atau bertindak sebagai tipe data. Kelas ini adalah turunan langsung dari void.
C. Kelas number
Kelas number dimaksudkan sebagai kelas induk dari kelas-kelas yang menangani bilangan, seperti int dan real.
D. Kelas int
Kelas int merupakan kelas yang bertugas menangani bilangan-bilangan integer. Literal integer merupakan instansiasi dari kelas int. Kelas ini merupakan turunan langsung dari number.
Metoda-metoda kelas int diperlihatkan pada Tabel 3.4.
int + () mengembalikan nilai tanpa perubahan int - () mengembalikan nilai negatifnya
int + (int) menjumlahkan dengan bilangan integer real + (real) menjumlahkan dengan bilangan real int – (int) mengurangkan dengan bilangan integer
real – (real) mengurangkan dengan bilangan real int * (int) mengalikan dengan bilangan integer real * (real) mengalikan dengan bilangan real real / (int) membagi dengan bilangan integer real / (real) membagi dengan bilangan real
bool == (int) menguji kesamaan dengan integer lain bool != (int) menguji ketaksamaan dengan integer lain bool > (int) menguji apakah lebih besar dari integer lain bool < (int) menguji apakah lebih kecil integer lain bool >= (int) menguji apakah lebih besar atau sama dengan
integer lain
bool <= (int) menguji apakah lebih kecil atau sama dengan integer lain
Tabel 3.4 Daftar metoda yang terdapat dalam kelas int
E. Kelas bool
Kelas bool adalah turunan dari data. Kelas ini berkaitan dengan literal boolean pada bahasa DOGI.
Metoda-metoda kelas bool diperlihatkan pada Tabel 3.5.
bool ! () mengembalikan negasi dari objek yang bersangkutan
bool & (bool) melakukan operasi konjungsi terhadap boolean lain
bool | (bool) melakukan operasi disjungsi terhadap boolean lain bool == (bool) menguji kesamaan dengan boolean lain
bool != (bool) menguji ketaksamaan dengan boolean lain void ? (void o) mengembalikan o jika objek bernilai benar, dan
#null jika salah
void ? (array a) mengembalikan elemen pertama dari a jika kondisi benar, dan elemen kedua dari a jika kondisi salah
Tabel 3.5 Daftar metoda yang terdapat dalam kelas bool
F. Kelas real
Kelas real digunakan untuk bilangan real, merupakan turunan dari kelas number.
Metoda-metoda kelas real diperlihatkan pada Tabel 3.6.
real + () mengembalikan nilai tanpa perubahan real - () mengembalikan nilai negatifnya real + (int) menjumlahkan dengan bilangan real real + (real) menjumlahkan dengan bilangan real real – (int) mengurangkan dengan bilangan real real – (real) mengurangkan dengan bilangan real real * (int) mengalikan dengan bilangan real real * (real) mengalikan dengan bilangan real real / (int) membagi dengan bilangan real real / (real) membagi dengan bilangan real bool == (real) menguji kesamaan dengan real lain bool != (real) menguji ketaksamaan dengan real lain bool > (real) menguji apakah lebih besar dari real lain bool < (real) menguji apakah lebih kecil real lain
bool >= (real) menguji apakah lebih besar atau sama dengan real lain
bool <= (real) menguji apakah lebih kecil atau sama dengan real lain
Tabel 3.6 Daftar metoda yang terdapat dalam kelas real
G. Kelas string
Kelas string merupakan turunan dari kelas data yang bertugas menangani data string.
Metoda-metoda kelas string diperlihatkan pada tabel Tabel 3.8Tabel 3.7. int length() mengembalikan panjang string
string + (string) menggabungkan dengan string lain bool == (string) menguji kesamaan dengan string lain bool != (string) menguji ketaksamaan dengan string lain
Tabel 3.7 Daftar metoda yang terdapat dalam kelas string
H. Kelas array
Kelas array merupakan turunan dari data yang berguna untuk menciptakan array.
Metoda-metoda kelas array diperlihatkan pada tabel Tabel 3.8. int count() mengembalikan banyaknya elemen array int setCount(int) menentukan banyaknya elemen array void item(int i) mengembalikan elemen ke i
void setItem(int i,
void object) mengganti elemen ke i dengan object
Tabel 3.8 Daftar metoda yang terdapat dalam kelas array
I. Kelas code
Kelas code juga adalah turunan dari kelas data, ialah kelas yang menginstansiasikan semua kode yang ditulis dalam blok [ .. ] untuk kode yang hanya terdiri dari sebuah ekspresi, atau ditulis dalam blok begin..end untuk kode yang terdiri dari nol atau lebih ekspresi.
Metoda-metoda kelas code diperlihatkan pada Tabel 3.9. code exec() mengeksekusi kode
void value() mengembalikan hasil eksekusi kode
array else(code) membentuk array yang terdiri dari dua elemen bertipe code, untuk digunakan dalam struktur seleksi menggunakan if.
Tabel 3.9 Daftar metoda yang terdapat dalam kelas code
J. Kelas control
Kelas control menurunkan kelas-kelas yang berguna dalam pembentukan struktur kontrol. Kelas control adalah turunan langsung dari kelas void.
K. Kelas _if
Kelas _if merupakan kelas turunan control yang bertugas untuk menangani struktur seleksi dengan menggunakan metoda if.
Kelas _if hanya memiliki sebuah metoda, yaitu then dalam dua bentuk, seperti diperlihatkan dalam Tabel 3.10.
bool .then (code c) jika bernilai benar, kerjakan c
bool .then (array a) jika bernilai benar, kerjakan elemen pertama dari a, dan jika tidak, kerjakan elemen kedua dari a.
Tabel 3.10 Daftar metoda yang terdapat dalam kelas _if
L. Kelas _loop
Kelas _loop merupakan kelas turunan control yang bertugas menangani struktur perulangan menggunakan metoda loop.
Metoda-metoda kelas _loop diperlihatkan dalam Tabel 3.11.
int .do(code) melakukan perulangan terhadap kode yang
diberikan, dan mengembalikan jumlah perulangan yang telah dilakukan
Tabel 3.11 Daftar metoda yang terdapat dalam kelas _loop
M. Kelas console
Kelas console adalah turunan dari kelas void, ialah kelas yang bertugas untuk menangani input/output.
Metoda-metoda kelas console diperlihatkan dalam Tabel 3.12. void .<< (void) menuliskan suatu objek pada console void .>> (string) membaca suatu string dari console void .>> (int) membaca suatu integer dari console void .>> (real) membaca suatu real dari console void .>> (bool) membaca suatu boolean dari console
void .writeln (void) menuliskan suatu objek pada console (+newline) void .readln (string) membaca suatu string dari console (+newline) void .readln (int) membaca suatu integer dari console (+newline) void .readln (real) membaca suatu real dari console (+newline) void .readln (bool) membaca suatu boolean dari console (+newline)
3.2 Perancangan kompiler DOGI
Seperti telah disebutkan pada 1.2, untuk penyederhanaan perancangan kompiler, maka kompiler DOGI disatukan dengan eksekutornya (virtual machine). Kedua modul ini disatukan menjadi sebuah program. Untuk selanjutnya frasa “program DOGI” menunjuk pada program yang akan dibuat sebagai gabungan kompiler DOGI dan virtual machine.
Program DOGI dibuat seluruhnya dengan C++, dengan bantuan program Flex untuk membuat scanner, serta Bison untuk membuat parser. Program DOGI versi Windows dikompilasi menggunakan Borland C++ 5.6.4 for Win32. Kompilasi dengan Minimalist GNU for Win32 versi 2.0.0 juga berhasil dilakukan. Untuk versi Linux dikompilasi menggunakan GNU C++ Compiler.
3.2.1 Spesifikasi rancangan
Spesifikasi komputer yang digunakan dalam pembuatan dan pengujian program DOGI adalah:
• Prosesor Pentium III 733 MHz • RAM 320MB
• 2 Hard Disk berukuran 80GB dan 40GB • 2 Sistem operasi:
a. Windows XP Professional Edition
b. Linux dengan paket distribusi Mandrake 9.1
3.2.2 Antarmuka pemakai
Program DOGI dijalankan dari command-line interpreter, dengan menuliskan:
dogi { [<opsi>] } [<file_kode_sumber>]
Opsi yang disediakan adalah seperti diperlihatkan pada Tabel 3.13 ( case-insensitive). Jika kode sumber mengandung kesalahan, akan ditampilkan posisi dan jenis kesalahan yang terjadi.
-i menampilkan setiap instruksi yang sedang dieksekusi
-s menampilkan state pada setiap eksekusi instruksi -e menampilkan isi stack pada setiap eksekusi
instruksi
-d gabungan dari -i, -s, dan -e
-v menampilkan daftar isi package dalam file -x<accessname> membuat dan mengeksekusi instance dari akses
bernama <accessname>
Tabel 3.13 Daftar opsi yang tersedia dalam program DOGI
3.2.3 Scanner
Kode sumber scanner DOGI (dogi.lpp) dikompilasi dengan Flex untuk menghasilkan dogi.yy.cpp yang merupakan program dalam bahasa C++. Selanjutnya, dogi.yy.cpp dikompilasi menggunakan kompiler C++.
Kode sumber scanner DOGI dapat dilihat pada Lampiran B. 3.2.4 Parser
Kode sumber parser DOGI (dogi.ypp) dikompilasi dengan Bison untuk menghasilkan dogi.tab.hpp dan dogi.tab.cpp yang merupakan program dalam bahasa C++, untuk dikompilasi kembali dengan kompiler C++.
Kode sumber parser DOGI dapat dilihat pada Lampiran B, dan tata bahasanya dalam format BNF dapat dilihat pada Lampiran A. Dituliskan dalam format BNF dan bukan EBNF karena Bison hanya dapat mengenali BNF.
3.2.5 Aturan semantik tata bahasa DOGI
Tidak setiap aturan semantik produksi tata bahasa DOGI akan dibahas di sini. Hanya definisi metoda dan ekspresi yang akan dibahas, karena merupakan bagian yang berhubungan erat dengan pembentukan kode antara. Setiap aturan semantik dideskripsikan dalam bentuk pseudocode.
A. Definisi metoda dalam kelas
Produksi methodCode → = expr
methodCode → = …
for index=number of arguments downto 1 do
put POPA argumentindex
endfor
if (method is not class method) put POPCTX
endif put KEEP … expr put RET
Produksi methodCode → begin exprList end
methodCode → begin …
for index=number of arguments downto 1 do
put POPA argumentindex
if (method is not class method) put POPCTX endif put KEEP … exprList end put PUSHN put RET B. Ekspresi
Baik expr, term, object, sendMsg maupun literal memiliki atribut-atribut sebagai berikut:
• class untuk menyatakan tipe yang dikembalikan oleh nonterminal-nonterminal tersebut.
• instance untuk menyatakan apakah nonterminal adalah kelas atau instance.
Sedangkan method memiliki atribut instruction yang adalah instruksi yang diwakili oleh metoda yang bersangkutan secara langsung.
Produksi expr → expr nextExprList
expr → expr … put FLUSH … nextExprList
Produksi expr → term methodName expr
if (term.class has method w/signature methodName(expr)) then
if (method is instruction) then
put method.instruction
else
put CALL(
term.class,
index of method in term.class)
endif
else
if (method is class method) then
if (method is instruction) then
put method.instruction
else
put CALL(
term.class,
index of method in term.class)
endif
else
Error Message: Not class method. endif
endif else
Error Message: method not found.
Endif
Produksi object → objectName
if (objectName in localList) then
put PUSHL (index of objectName in localList) object.class=class of objectName
object.instance=true
elseif (objectName in argList) then
put PUSHA (index of objectName in argList) object.class=class of objectName
elseif (objectName in fieldList) then
put PUSHO (index of objectName in fieldList) object.class=class of objectName
object.instance=true
elseif (objectName is className) then
object.class=class of objectName
object.instance=false
else
Error Message: objectName undeclared.
Endif
Produksi object → integer
put PUSHI integer.value Produksi object → floatingPoint
put PUSHF floatingPoint.value Produksi object → boolean
put PUSHB boolean.value Produksi object → string
put PUSHS string.value Produksi object → code
Produksi sendMsg → term . methodName (sendArgList)
if (term.class has method w/signature
methodName(sendArgList)) then
if (term.instance = true) then if (method is instruction) then
put method.instruction
else
put CALL(
term.class,
index of method in term.class)
endif
else
if (method is class method) then
if (method is instruction) then
put method.instruction
else
put CALL(
term.class,
index of method in term.class)
endif
else
Error Message: Not class method. endif
endif else
Error Message: method not found.
Endif
Produksi sendMsg → methodName (sendArgList) dan sendMsg → . methodName (sendArgList)
if (current.class has method w/signature
if (method is not class method) then put SELF
endif
if (method is instruction) then
put method.instruction
else
put CALL(
current.class,
index of method in current.class)
endif
else
Error Message: method not found.
Endif
Produksi sendMsg → operatorName object
if (object.class has method w/signature operatorName()) then
if (method is instruction) then
put method.instruction
else
put CALL(
object.class,
index of method in object.class)
endif
else
Error Message: method not found.
Endif C. Literal code
Produksi code → begin exprList end
push current address to address stack put PUSHC (current address+4)
put JMP (-1) … exprList end put FLUSH put PUSHN put RETC
addr = pop address stack
replace code at addr+3 with current address
Produksi code → [ expr ]
code → begin …
push current address to address stack put PUSHC (current address+4)
put JMP (-1) … exprList end put RETC
addr = pop address stack
replace code at addr+3 with current address
3.3 Perancangan DOGIVM (DOGI Virtual Machine)
3.3.1 Instruksi-instruksi dasar DOGIVM
Instruksi-instruksi yang terdapat pada DOGIVM diperlihatkan pada Tabel 3.14. Panjang instruksi menyatakan panjang instruksi dalam satuan doubleword (32 bit), jumlah pop menyatakan banyaknya anggota stack yang diambil oleh instruksi tersebut, dan return menyatakan banyaknya objek yang didorong oleh instruksi tersebut ke dalam stack.
instruksi panjang (double
word)
jumlah
pop return deskripsi NOP 1 tidak ada operasi
PUSH o 2 1 dorong objek o ke dalam stack PUSHL l 2 1 dorong objek lokal l ke dalam stack PUSHA a 2 1 dorong objek argumen a ke dalam stack PUSHI i 2 1 dorong objek integer bernilai i ke dalam stack PUSHF f 2 1 dorong objek real bernilai f ke dalam stack PUSHB b 2 1 dorong objek boolean bernilai b ke dalam stack PUSHS s 2 1 dorong objek string bernilai s ke dalam stack
PUSHC a 2 1 dorong objek code yang menunjuk alamat a ke dalam stack
PUSHN 1 1 dorong objek null ke dalam stack
POP o 2 1 ambil objek dari stack dan asosiasikan ke objek o POPL l 2 1 ambil objek dari stack dan asosiasikan ke objek lokal
l
POPA a 2 1 ambil objek dari stack dan asosiasikan ke objek argumen a
POPCTX 1 1 ambil objek dari stack dan asosiasikan ke objek konteks
JMP a 2 lompat ke alamat a
IFENTRY 1 1 1 buat suatu instance _if berdasarkan kondisi yang diberikan objek pada puncak stack
IFT 1 2 1 jalankan kode pada puncak stack jika benar IFTE 1 2 1 pilih kode yang akan dijalankan dari array pada
puncak stack
LOOP 1 1 buat suatu instance _loop
LOOPW 1 1 1 buat suatu instance _loop berdasarkan yang diberikan objek pada puncak stack
LOOPI 1 1 1 buat suatu instance _loop berdasarkan jumlah yang diberikan objek pada puncak stack
LOOPA 1 2 1 buat suatu instance _loop berdasarkan array yang diberikan objek pada puncak stack, dan objek di bawahnya untuk menampung elemen array LOOPF 1 3 1 buat suatu instance _loop berdasarkan batas yang
diberikan objek pada puncak stack dan objek di bawahnya
LOOPDO 1 2 1 eksekusi kode yang ada pada puncak stack CALL c m 3 memanggil metoda m dari kelas c
CALLC a 2 mengeksekusi kode pada alamat a
NEW c m 3 1 membuat instance dari kelas c dengan konstruktor m KILL 1 1 1 mendealokasikan objek pada puncak stack
RET 1 kembali pada alamat pemanggil (CALL) RETC 1 kembail pada alamat pemanggil (CALLC) ENDX 1 menandai akhir dari kode
END 1 menandai akhir dari kode KEEP 1 1 menandai stack dengan pembatas
FLUSH 1 * menghapus isi stack dari puncak hingga pembatas yang dibuat dengan KEEP
DISCONST 1 1 1 mengembalikan #true jika objek pada puncak stack dibuat dari literal
pada puncak stack
SUB 1 2 1 mengembalikan hasil pengurangan dari dua objek pada puncak stack
MUL 1 2 1 mengembalikan hasil perkalian dari dua objek pada puncak stack
DIV 1 2 1 mengembalikan hasil pembagian dari dua objek pada puncak stack
NEG 1 1 1 mengembalikan negasi dari objek pada puncak stack (bilangan)
POS 1 1 1 tidak ada operasi
AND 1 2 1 mengembalikan hasil operasi and dari dua objek pada puncak stack
OR 1 2 1 mengembalikan hasil operasi or dari dua objek pada puncak stack
NOT 1 1 1 mengembalikan negasi dari objek pada puncak stack (boolean)
ASSIGN 1 2 1 mengkopi dua objek pada puncak stack REFTO 1 2 1 mereferensikan nama objek pada objek lain ADDREF 1 1 1 menambah reference count
RELEASE 1 1 1 mengurangi reference count REFCOUNT 1 1 1 mengembalikan reference count BASE 1 1 1 mendorong instance ke dalam stack SELF 1 1 1 mendorong instance ke dalam stack
ALTER 1 2 1 mendorong array berisi dua objek pada puncak stack CMPE 1 2 1 membandingkan dua objek pada puncak stack, dan
mengembalikan #true jika keduanya sama, dan #false jika sebaliknya
CMPNE 1 2 1 membandingkan dua objek pada puncak stack, dan mengembalikan #true jika keduanya tidak sama, dan #false jika sebaliknya
CMPG 1 2 1 membandingkan dua objek pada puncak stack, dan mengembalikan #true jika nilai objek pertama > nilai objek kedua, dan #false jika sebaliknya CMPL 1 2 1 membandingkan dua objek pada puncak stack, dan
mengembalikan #true jika nilai objek pertama < nilai objek kedua, dan #false jika sebaliknya CMPGE 1 2 1 membandingkan dua objek pada puncak stack, dan
mengembalikan #true jika nilai objek pertama ≥ nilai objek kedua, dan #false jika sebaliknya CMPLE 1 2 1 membandingkan dua objek pada puncak stack, dan
mengembalikan #true jika nilai objek pertama ≤ nilai objek kedua, dan #false jika sebaliknya SLEN 1 1 1 mengembalikan panjang string pada puncak stack ARRSCNT 1 2 1 mengeset jumlah elemen array pada puncak stack ARRGCNT 1 1 1 mengembalikan jumlah elemen array pada puncak
stack
ARRSITEM 1 3 1 mengeset elemen array pada puncak stack ARRGITEM 1 2 1 mengembalikan elemen array pada puncak stack CONOUT 1 1 1 mencetak representasi dari objek pada puncak stack CONIN 1 1 1 membaca representasi objek dari console dan
mendorongnya ke dalam stack
CONOUTN 1 1 1 mencetak representasi dari objek pada puncak stack (+newline)
CONINN 1 1 1 membaca representasi objek dari console dan mendorongnya ke dalam stack
CDEXEC 1 1 1 mengeksekusi kode yang terdapat pada puncak stack CDVAL 1 1 1 mengembalikan nilai yang dihasilkan oleh kode CDELSE 1 2 1 membentuk array berisi dua objek pada puncak stack CDQT 1 2 1 mengembalikan objek pada puncak stack jika
bernilai benar
CDQTE 1 2 1 mengembalikan objek pertama pada array pada puncak stack jika bernilai benar
Tabel 3.14 Daftar instruksi DOGIVM
3.3.2 Siklus eksekusi instruksi
Siklus eksekusi kode antara DOGI diperlihatkan dalam Gambar 3.21. Instruksi CALL
• Dorong state konteks ke dalam state stack • Kosongkan state konteks,
• Set posisi pada state konteks pada alamat metoda Instruksi RET
• Pop state konteks dari state stack 3.3.3 State
Suatu state dalam DOGIVM terdiri dari:
• Sebuah daftar semua objek yang diinstansiasikan sejak program berjalan, • Sebuah state konteks – yaitu informasi mengenai posisi eksekusi, instance
yang sedang aktif, semua field yang terdapat pada instance tersebut, argumen-argumen metoda yang sedang dieksekusi, dan objek-objek lokal metoda tersebut,
• Sebuah state stack yang menyimpan state konteks ketika ada pemanggilan suatu metoda,
• Sebuah stack evaluasi, yang berisi objek-objek untuk digunakan dalam evaluasi, dan objek hasil evaluasi suatu ekspresi.
Ambil instruksi Eksekusi instruksi Majukan posisi pembacaan Stack kosong? Tidak Ya Reset posisi &
kosongkan stack
start
selesai