Analisis leksikal adalah sebuah proses yang mendahului parsing sebuah rangkaian karakter. Ia menerima masukan serangkaian karakter (seperti dalam dokumen plain-text atau source code) dan menghasilkan deretan simbol yang masing-masing dinamakan token; proses parsing akan lebih mudah dilakukan bila inputnya sudah berupa token.
Analisis leksikal terdiri dari dua tahap. Tahap pertama adalah pemindaian (scanning); scanner biasanya dibuat berdasarkan prinsip Finite State Machine ("mesin dengan jumlah keadaan terbatas"). Pada tahap ini, scanner akan membaca input karakter-ke-karakter, mengubah keadaannya sendiri berdasarkan karakter yang tengah dibaca. Setiap kondisi final (input dianggap valid) akan dicatat, bersama dengan lokasi input. Pada akhirnya scanner akan menemui keadaan penolakan, yang tidak akan berubah dengan input karakter apapun. Deteksi rekursi semacam ini akan mengakhiri proses pemindaian dan memindahkan keadaan scanner ke keadaan final terakhir, dan karenanya menyimpan informasi jenis dan besar lexeme valid yang terpanjang di dalam input.
Namun lexeme tersebut belum punya nilai semantik apapun; pemberian nilai semantik pada setiap unit leksikal adalah tugas dari evaluator yang memeriksa semua karakter setiap lexeme dan memberinya nilai tertentu. Saat sebuah lexeme telah memiliki informasi mengenai tipe dan nilainya, ia dapat secara valid disebut sebagai token.
Analisis leksikal membuat pekerjaan membuat sebuah parser jadi lebih mudah; ketimbang membangun nama setiap fungsi dan variabel dari karakter-karakter yang menyusunnya, dengan analisis leksikal parser cukup hanya berurusan dengan sekumpulan token dan nilai sintaksis masing-masing. Terlepas dari efisiensi pemrograman yang dapat dicapai dengan penggunaannya, proses kerja analisis leksikal yang membaca lebih dari sekali setiap karakter dari input yang diberikan menjadikan penganalisa leksikal sebagai sub-sistem yang paling intensif melakukan komputasi, terutama bila digunakan dalam sebuah kompilator.
Analisis Leksikal atau scanner bertugas mengidentifikasi semua besaran pembangun bahasa(leksikal) yang ada pada kode sumber (source code)
Scanner
menerima masukan kode sumber berupa serangkaian karakter kemudian
memilah-milahnya kedalam satuan leksikal yaitu token.
Token-token
ini akan menjadi masukan bagi analisis leksikal selanjutnya yaitu analisis
sintaksis.
Dari fungsi
scanner secara umum seperti telah disebutkan diatas, maka tugas scanner secara
rinci adalah:
1. Membaca serangkaian karakter dari kode sumber
2. Mengenali kedalam satuan leksikal
3. Mengubah menjadi token dan menentukan jenis tokennua
4. Mengirimkan token ke proses analisis selanjutnya,
yaitu analisis sintaksis
5. Mengabaikan karakter white space (spasi, enter, ganti baris, penanda akhir file) dan
komenter (remark) apabila ada didalam
kode sumber
6. Menangani kesalahan
7.
Menangani table
symbol.
` Analisis
Leksikal merupakan antarmuka antara kode program sumber dan analisis sintaktik
(parser). Scanner melakukan pemeriksaan karakter per karakter pada teks
masukan, memecah sumber program menjadi bagian-bagian disebut Token.
Analisis
Leksikal mengerjakan pengelompokkan urutan-urutan karakter ke dalam komponen
pokok: identifier, delimeter, simbol-simbol operator, angka, keyword, noise
word, blank, komentar, dan seterusnya menghasilkan suatu Token Leksikal yang
akan digunakan pada Analisis Sintaktik.
Model dasar
untuk membentuk suatu Analisis Leksikal adalah Finite-State Automata.
2. aspek
penting pembuatan Analisis Leksikal adalah:
- Menentukan
token-token bahasa.
- Mengenali
token-token bahasa dari program sumber.
Token-token
dihasilkan dengan cara memisahkan program sumber tersebut dilewatkan ke parser
Analisis
Leksikal harus mengirim token ke parser. Untuk mengirim token, scanner harus
mengisolasi barisan karakter pada teks sumber yang merupakan 1 token valid.
Scanner juga menyingkirkan informasi seperti komentar, blank, batas-batas baris
dan lain-lain yang tidak penting (tidak mempunyai arti) bagi parsing dan Code
Generator.
Scanner juga
harus dapat mengidentifikasi token secara lengkap dan membedakan keyword dan
identifier. Untuk itu scanner memerlukan tabel simbol. Scanner memasukkan
identifier ke tabel simbol, memasukkan konstanta literal dan numerik ke tabel
simbol sendiri setelah konversi menjadi bentuk internal.
Analisis
Leksikal merupakan komponen kompilasi independen yang berkomunikasi dengan
parser lewat antarmuka yang terdefinisi bagus dan sederhana sehingga
pemeliharaan analisis leksikal menjadi lebih mudah dimana perubahan-perubahan
terhadap analisis leksikal tidak berdampak pada pengubahan kompilator secara
keseluruhan.
Agar dapat
memperoleh fitur ini, maka antarmuka harus tidak berubah. Kebanyakan kode yang
menyusun analisis leksikal adalah sama untuk seluruh kompilator, tidak peduli
bahasa.
Pada
analisis leksikal yang dituntun tabel (table-driven lexical analyzer), maka
satu-satunya yang berubah adalah tabel itu sendiri.
Kadang
diperlukan interaksi analisis leksikal dan analisis sintaktik yang lebih
kompleks. Sehingga analisis leksikal harus dapat menganggap string sebagai token
bertipe, bukan identifier.
Untuk itu
perlu komunikasi tingkat lebih tinggi yang biasanya dilakukan suatu struktur
data dipakai bersama seperti tabel simbol.
Analisis
Sintaktik dapat memasukkan string ke tabel simbol, mengidentifikasi sebagai
Type atau typedef, sehingga analisis leksikal dapat memeriksa tabel simbol
untuk menentukan apakah lexeme adalah tipe token atau identifier.
Tugas-tugas
Analisis leksikal
1. Konversi
Program Sumber Menjadi Barisan Token
Mengubah
program sumber yang dipandang sebagai barisan byte/karakter menjadi token
2. Menangani
Kerumitan Sistem Masukkan/Keluaran
Karena
analisis leksikal biasanya berhubungan langsung dengan kode sumber yang
diwadahi file, maka analisis leksikal juga bertindak sebagai benteng untuk
komponen-komponen lain di kompilator dalam mengatasi keanehan-keanehan sistem
masukkan/keluaran sistem operasi dan sistem komputer.
Optimasi
perlu dilakukan agar analisis leksikal membaca karakter degan sekaligus membaca
sejumlah besar bagian file.
Perangkat
masukkan/keluaran benar-benar diisolasi agar tidak terlihat oleh parser dan
komponen-komponen kompilator yang lain.
Tugas-tugas
tambahan Analisis Leksikal
1.
Penghilangan komentar dan whitespace (tab,spasi,karakter lainnya)
Tindakan
housekeeping dilakukan scanner sehingga mengisolasikan dari parser dan
komponen-komponen kompilator lain.
Peran ini
menyederhanakan perancangan parser (dan grammar bahasa pemrograman).
Scanner juga
mencatat nomor baris saat itu sehingga penanganan kesalahan yang cerdas dapat
mengirim pesan kesalahan dengan lebih akurat.
2. Konversi
literal/konstanta numerik menjadi tipe data tertentu
Analisis
leksikal dapat mengirim token, dan nilainya. Nilai ini biasa disebut atribut.
Namun
demikian, bila analisis leksikal ditambahin dengan tugas-tugas tambahan yang
terlalu banyak juga akan menjadi tidak baik. Karena itu membatasi analisis
leksikal hanya untuk melakukan tugas pengenalan pola token (ditambah membuang
komentar) adalah mempermudah pemeliharaan.
Tahap
Pelaksanaan Analisis Leksikal
- Pada
single one pass
Terjadi
interaksi antara scanner dan parser. Sacnner dipanggil saat parser memerlukan
token berikutnya. Pendekatan ini lebih baik karena bentuk internal program
sumber yang lengkap tidak perlu dibangun dan disimpan di memori sebelum parsing
dimulai.
- Pada
separate pass
Scanner
memproses secara terpisah, dilakukan sebelum parsing. Hasil scanner disimpan
dalam file. Dari file tersebut, parsing melakukan kegiatannya.
Scanner
mengirim nilai-nilai integer yang mempresentasikan bentuk internal token, bukan
nilai-nilai string.
Keunggulan
cara ini adalah ukurannya kecil dan tetap. Parser sangat lebih efisien bekerja
dengan nilai integer yang mempresentasikan simbol daripada string nyata dengan
panjang variabel.
Implementasi
Analisis Leksikal
1.
Pengenalan Token
Scanner harus dapat mengenali token
- Terlebih
dahulu dideskripsikan token-token yang harus dikenali
2.
Pendeskripsian Token
-
Menggunakan reguler grammar. Menspesifikasikan aturan-aturan pembangkit
token-token dengan kelemahan reguler grammar menspesifikasikan token berbentuk
pembangkit, sedang scanner perlu bentuk pengenalan.
-
Menggunakan ekspresi grammar. Menspesifikasikan token-token dengan ekspresi
reguler.
- Model
matematis yang dapat memodelkan pengenalan adalah finite-state acceptor (FSA)
atau finite automata.
3.
Implementasi Analisis Leksikal sebagai Finite Automata
Pada
pemodelan analisis leksikal sebagai pengenal yang menerapkan finite automata,
analisis leksikal tidak cuma hanya melakukan mengatakan YA atau TIDAK. Dengan
demikian selain pengenal, maka analisis leksikal juga melakukan aksi-aksi
tambahan yang diasosiasikan dengan string yangsedang diolah.
Analisis
leksikal dapat dibangun dengan menumpangkan pada konsep pengenal yang berupa
finite automata dengan cara menspesifikasikan rutin-rutin (aksi-aksi) tertentu
terhadap string yang sedang dikenali.
4.
Penanganan Kesalahan di Analisis Leksikal
Hanya
sedikit kesalahan yang diidentifikasi di analisis leksikal secara mandiri
karena analisis leksikal benar-benar merupakan pandangan sangat lokal terhadap
program sumber.
Bila ditemui
situasi dimana analisis leksikal tidak mampu melanjutkan proses karena tidak
ada pola token yang cocok, maka terdapat beragam alternatif pemulihan. yaitu:
-
"Panic mode" dengan menghapus karakter-karakter berikutnya sampai
analisis leksikal menemukan token yang terdefinisi bagus
-
Menyisipkan karakter yang hilang
- Mengganti
karakter yang salah dengan karakter yang benar
-
Mentransposisikan 2 karakter yang bersebelahan.
Salah satu
cara untuk menemukan kesalahan-kesalahan di program adalah menghitung jumlah
transformasi kesalahan minimum yang diperlukan untuk mentransformasikan program
yang salah menjadi program yag secara sintaks benar.
Input
Buffering
Perancangan
analisis leksikal seharusnya dapat membuat buffering masukkan yang membantu
mempercepat proses pembacaan dari file serta mempunyai fleksibelitas yang
tinggi agar analisis leksikal tidak bergantung platform sehingga mempunyai
portabilitas yang tinggi.