ANALISIS SEMANTIK
Analisis Semantik
adalah proses setelah melewati proses scanning dan parsing. Pada tahap ini
dilakukan pengecekan pada struktur akhir yang telah diperoleh dan diperiksa
kesesuaiannya dengan komponen program yang ada. Secara global, fungsi dari semantic analyzer adalah untuk menentukan makna
dari serangkaian instruksi yang terdapat dalam program sumber.
Contoh
: A := (A + B)*(C + D)
maka penganalisis semantik harus mampu menentukan aksi apa yang akan
dilakukan oleh operator-operator tersebut. Dalam sebuah proses kompilasi,
andaikata parser menjumpai ekspresi seperti diatas, parser hanya akan mengenali
simbol-simbol ':=' , '+'
, dan '*'. Parser tidak tahu makna apa yang
tersimpan dibalik simbol simbol tersebut. Untuk mengenalinya, kompiler akan
memanggil rutin semantik yang akan memeriksa :
l Apakah variabel-variabel yang ada telah didefinisikan sebelumnya?
l Apakah variabel-variabel tersebut tipenya sama?
l Apakah operand yang akan dioperasikan tersebut ada nilainya?, dan
seterusnya.
Fungsi ini terkait dengan tabel simbol.
Pengecekan yang dilakukan oleh analisis semantik adalah sebagai berikut :
a)
Memeriksa keberlakuan nama-nama
meliputi pemeriksaan berikut.
Duplikasi : pada tahap ini
dilakukan pengecekan apakah sebuah nama terjadi pendefinisian lebih dari dua
kali. Pengecekan dilakukan pada bagian pengelola blok.
Terdefinisi : Melakukan
pengecekan apakah sebuah nama yang dipakai pada tubuh program sudah terdefinisi
atau belum. Pengecekan dilakukan pada semua tempat kecuali blok.
b)
Memeriksa tipe. Melakukan
pemeriksaan terhadap kesesuaian tipe dalam statement-statement yang ada.
Misalkan bila terdapat suatu operasi, diperiksa tipe operand. Contohnya bila
ekspresi yang mengikuti instruksi IF berarti tipenya boolean, akan diperiksa
tipe identifier dan tipe ekspresi. Bila ada operasi antara dua operand, maka
tipe operand pertama harus bisa dioperasikan dengan operand kedua.
Analisa semantik
sering juga digabungkan pada pembangkitan kode antara yang menghasilkan Output
intermediate code, yang nantinya akan digunakan pada proses kompilasi
berikutnya.
KODE ANTARA
Kode antara/Intermediate code merupakan hasil
dari tahapan analisis, yang dibuat oleh kompilator pada saat mentranslasikan
program dari bahasa tingkat tinggi. Kegunaan dari kode antara sebagai berikut:
l untuk memperkecil usaha dalam membangun kompilator dari sejumlah
bahasa ke sejumlah mesin. Dengan adanya kode antara yang lebih machine independent maka kode antara yang
dihasilkan dapat digunakan lagi pada mesin lainnya.
l Proses optimasi masih lebih mudah. Beberapa strategi optimisasi
lebih mudah dilakukan pada kode antara daripada pada program sumber atau pada
kode assembly dan kode mesin.
l Bisa melihat program internal yang mudah dimengerti. Kode antara ini
akan lebih mudah dipahami dari pada kode assembly atau kode mesin.
Terdapat dua macam kode antara, yaitu Notasi
Postfix dan N-Tuple
NOTASI POSTFIX
Sehari-hari kita biasa menggunakan operasi dalam notasi infix (letak
operator di tengah). Pada notasi Postfix operator diletakkan paling akhir maka
disebut juga dengan notasi Sufix atau Reverse Polish.
Sintaks notasi Postfix :
Misalkan ekspresi :
(a + b)*(c + d)
kalau kita nyatakan dalam postfix :
ab + cd + *
Kita dapat mengubah instruksi kontrol program yang ada ke dalam
notasi Postfix. Misal :
IFTHENELSE
diubah ke dalam Postfix
label1 label2
Keterangan :
BZ = branch if zero (zero = salah) {bercabang/meloncat
jika kondisi yang dites salah}
BR = branch {bercabang/meloncat
tanpa ada kondisi yang dites}
Arti dari notasi Postfix di atas adalah sebagai berikut.
“Jika kondisi ekspresi salah, maka instruksi akan
meloncat ke Label1dan menjalankan statement2. Bila kondisi ekspresi benar, maka
statement1 akan dijalankan lalu meloncat ke Label2. Label1 dan Label1 dan
Label2 sendiri menunjukan posisi tujuan loncatan, untuk Label1 posisinya tepat
sebelum statement2, dan Label2 setelah statement2”
Dalam implementasi ke kode antara, label bisa berupa nomor baris
instruksi. Untuk lebih jelasnya bisa dilihat contoh berikut.
IF a > b THEN
c
:= d
ELSE
c
:= e
Bila diubah ke salam Postfix
11.
a
12.
b
13.
>
14.
22 {menunjuk label1}
15.
BZ
16.
c
17.
d
18.
:=
19.
20.
25 {menunjuk label2}
21.
BR
22.
c
23.
e
24.
:=
25.
Notasi Postfix di atas bisa dipahami sebagai berikut.
Bila ekspresi (a > b) salah, maka loncat ke instruksi no.22
Bila ekspresi (a > b) benar, tidak terjadi loncatan, instruksi
berlanjut ke 16 sampai 18, lalu loncat ke 25.
Contoh lain :
WHILEDO
diubah ke postfix
label1 label2
Contoh, instruksi
a := 1
WHILE a<5
DO
a
:= a + 1
diubah ke notasi postfix menjadi sebagai berikut :
10.
a
11.
1
12.
:=
13.
a
14.
5
15.
<
16.
26 {menunjuk label1}
17.
BZ
18.
a
19.
a
20.
1
21.
+
22.
:=
23.
24.
13 {menunjuk label2}
25.
BR
NOTASI N-TUPLE
Bila pada Postfix
setiap baris instruksi hanya terdiri dari satu tupel, pada notasi N-tuple
setiap baris terdiri dari beberapa tupel. Format umum dari Notasi N-Tuple ada
sebagai berikut:
operator......(N-1) operand
selanjutnya akan dibahas notasi 3 tupel dan 4 tupel.
TRIPLE NOTATION
Notasi tripel memiliki format sebagai berikut :
contoh, instuksi :
A := D * C + B / E
Kode antara tripel :
1.
*, D,C
2.
/, B, E
3.
+, (1), (2)
4.
:=, A, (3)
operasi perkalian/pembagian lebih prioritas dibandingkan
penjumlahan/pengurangan
contoh lain:
IF x > y THEN
x:=
a – b
ELSE
x:=
a + b
kode antara tripelnya :
1.
>,x,y
2.
BZ,(1),(6) {bila kondisi (1)
salah satu loncat ke no (6)}
3.
–,a,b
4.
:=,x,(3)
5.
BR, ,(8)
6.
+,a,b
7.
:=,x,(6)
Kekurangan dari notasi tripel adalah sulit pada saat melakukan
optimasi, maka dikembangkan Indirect triples yang memiliki dua list
(senarai), yaitu list instruksi yang berisi notasi tripel dan list eksekusi
yang berisi urutan eksekusinya.
Contoh :
A:= B+C*D/E
F:=
C*D
List Instruksinya:
1.
*, C, D
2.
/, (1), E
3.
+, B, (2)
4.
:=, A, (3)
5.
:=, F, (1)
List Eksekusinya :
1.
1
2.
2
3.
3
4.
4
5.
1
6.
5
QUADRUPLES NOTATION
Format notasi kuadrupel :
hasil adalah temporary variable yang bisa ditempatkan pada memory
atau register. Masalah yang ada bagaimana mengelola temporary variable
(hasil) seminimal mungkin.
Contoh instruksi :
A := D * C + B / E
bila dibuat dalam kode antara :
1.
*, D,C, T1
2.
/, B, E, T2
3.
+, T1, T2, A
PEMBANGKITAN KODE
Hasil dari tahapan analisis akan diterima oleh bagian pembangkitan
kode (code generator). Disini
kode antara dari program biasanya ditranslasikan ke bahasa assembly atau bahasa
mesin.
Contoh :
(A+B)*(C+D)
Notasi Kuadrupel :
1.
+, A, B, T1
2.
+, C, D, T2
3.
*, T1, T2,
T3
Dapat ditranslasikan ke dalam bahasa Assembly dengan akumulator
tunggal :
LDA A {Muat isi A ke akumulator}
ADD
B {Tambahkan
isi akumulator dengan B}
STO
T1 {Simpan
isi akumulator ke T1}
LDA
C
ADD D
STO T2
LDA
T1
MUL T2
STO T3
Keluaran dari code generator akan diterima oleh code optimizer.
Misalkan untuk kode assembly diatas bisa dioptimasi menjadi :
LDA A
ADD B
STO T1
LDA C
ADD D
MUL T1
STO T2
Notes :
l Perintah LDA : Memuat isi dari
register/memory ke akumulator (load to accumulator)
l Perintah STO : Menyimpan isi
akumulator ke register/memory (store from
accumulator)
CARA PENANGANAN KESALAHAN
Kesalahan Program bisa merupakan :
- Kesalahan Leksikal : THEN ditulis TEN
- Kesalahan Sintaks : A:=X+(B*(C+D) {jumlah kurungnya kurang}
- Kesalahan Semantik :
Tipe data yang salah.
Contoh
: Var
Siswa : Integer
Siswa
:= 'Yanuar' {tipe
string}
Variabel belum didefinisikan.
Contoh
: B := B
+ 1 {B belum didefinisikan}
Langkah-langkah Penanganan Kesalahan adalah sebagai berikut :
l Mendeteksi Kesalahan
l Melaporkan Kesalahan
l Tindak lanjut pemulihan/perbaikan
sebuah kompilator yang menemukan kesalahan akan melakukan pelaporan
kesalahan, yang biasanya meliputi :
l Kode kesalahan
l Pesan kesalahan dalam bahasa natural
l Nama dan atribut identifier
l Tipe-tipe yang terkait bila type checking
Contoh : Error Massage: Error 162 Jumlah :=
unknown identifier
artinya :
è kode kesalahan = 162
è pesan kesalahan = unknown identifier
è nama identifier = Jumlah
Adanya pesan kesalahan tersebut akan memudahkan pemrogram dalam
mencari dan mengoreksi sumber dari kesalahan.
REAKSI KOMPILATOR PADA KESALAHAN
Terdapat beberapa tingkatan reaksi yang dilakukan oleh kompilator
saat menemukan kesalahan, yaitu :
- Reaksi-reaksi yang tidak dapat diterima (tidak melaporkan error);
Kompilator crash: berhenti atau hang.
Looping: kompilator masih berjalan tapi tidak pernah berakhir karena
looping tak berhingga (indefinite/onbounded loop)
Menghasilkan program objek yang salah: kompilator melanjutkan proses
sampai selesai tapi program objek yang dihasilkan salah. Ini berbahaya bila
tidak diketahui pemrogram, karena baru akan muncul saat program dieksekusi.
- Reaksi yang benar tapi kurang dapat diterima dan kurang bermanfaat. Kompilator menemukan kesalahan pertama, melaporkannya, lalu berhenti (halt). Ini bisa muncul bila pembuat kompilator menganggap jarang terjadi kemunculan error dalam program sehingga kemampuan kompilator untuk mendeteksi dan melaporkan kesalahan hanya satu untuk setiap kali kompilasi. Pemrogram akan membuang waktu untuk melakukan pengulangan kompilasi setiap kali terdapat sebuah error.
- Reaksi-reaksi yang dapat diterima:
Reaksi yang sudah dapat dilakukan, yaitu kompilator melaporkan
error, dan selanjutnya melakukan :
■
Recovery/pemulihan, lalu melanjutkan mencari error lain bila masih ada.
■
Repair/perbaikan kesalahan, lalu melanjutkan proses translasi dan menghasilkan
program objek yang valid.
Kebanyakan kompilator dewasa
ini sudah memiliki kemampuan recovery dan repair.
Reaksi yang belum dapat dilakukan, yaitu kompilator mengkoreksi
kesalahan, lalu menghasilkan program objek sesuai dengan yang diinginkan
pemrogram. Disini komputernya sudah memiliki kecerdasan untuk mengetahui maksud
pemrogram. Tingkatan respon ini belum dapat diimplementasikan pada kompilator
yang ada dewasa ini.
ERROR RECOVERY
Pemulihan kesalahan bertujuan mengembalikan kondisi parser kekondisi
stabil (supaya bisa melanjutkan proses parsing keposisi selanjutnya). Strategi
untuk melakukan error recovery sebagai
berikut:
- Mekanisme Ad Hoc. Recovery yang dilakukan tergantung dari pembuat kompilator sendiri/spesifik dan tidak terikat pada suatu aturan tertentu. Cara ini bisa disebut juga sebagai special purpose error recovery.
- Syntax directed recovery. Melakukan recovery berdasarkan syntax. Contoh :
Begin
A:=A+1
B:=B+1;
C:=C+1
end;
kompilator akan mengenali sebagai (dalam notasi BNF):
begin?;end;
'?' akan
dikenali sebagai ';'
- Secondary Error Recovery berguna untuk melokalisir error, dengan cara sebagai berikut:
Panic Mode. Maju terus dan mengabaikan teks sampai bertemu delimiter
(';'). contoh,
IF A:=1
Kondisi := true;
Pada teks diatas tidak
terdapat instuksi THEN, kompilator akan maju terus/skip sampai bertemu titik
koma.
Unit Deletion. Menghapus keseluruhan suatu unit sintaktik (misal:
, , ). Efeknya mirip dengan panic mode
tetapi unit deletion memelihara kebenaran sintaksis dari source program dan
mempermudah untuk melakukan error repairing lebih lanjut.
- Context Sensitive Recovery. Berkaitan dengan semantik, misal bila terdapat variabel yang belum dideklarasikan (Undefined Variable) maka diasumsikan tipenya berdasarkan kemunculannya. Contoh :
B:= 'nama'
sementara diawal
program variabel B belum dideklarasikan, maka
berdasarkan kemunculannya diasumsikan variabel B bertipe string.
ERROR REPAIRING
Perbaikan kesalahan bertujuan memodifikasi source program dari kesalahan
dan membuatnya valid sehingga memungkinkan kompilator untuk melakukan translasi
program yang mana akan dialirkan ketahapan selanjutnya pada proses kompilasi.
Mekanismenya sebagai berikut :
- Mekanisme Ad Hoc. Tergantung dari pembuat kompilator sendiri/spesifik.
- Syntax Directed Repar. Menyisipkan simbol terminal yang dianggap hilang atau membuang terminal penyebab kesalahan. Contoh :algoritma berikut kurang instruksi DO
WHILE
A < 1
I:=I+1;
Kompilator akan
menyisipkan DO
contoh lain :
Procedure
Increment;
begin
x:=x+1;
end;
end;
terdapat kelebihan
simbol end, yang menyebabkan kesalahan maka kompilator akan membuangnya.
- Context Sensitive Repair. Perbaikan dilakukan pada kesalahan berikut.
Tipe Identifier. Diatasi dengan membangkitkan identifier dummy,
contoh:
Var A:string;
begin
A:=0;
end;
kompilator akan
memperbaiki kesalahan dengan membangkitkan identifier baru, misal B yang
bertipe integer.
Tipe Konstanta diatasi dengan
membangkitkan konstanta baru dengan tipe yang tepat.
- Spelling Repair. Memperbaiki kesalahan pengetikan pada identifier, misal:
WHILLE
A=1 DO
identifier yang salah
tersebut akan diperbaiki menjadi WHILE.
aslam, mi, follow blog ku jg ya..
BalasHapus