4. ANALISIS LEKSIKAL - Teknik Kompilasi.zip

4. ANALISIS LEKSIKAL

  • Analisis leksikal (scanner) sering juga disebut sebagai analisis linier atau pembacaan sekilas (scanning).
  • Analisis leksikal bekerja dengan cara membaca program sumber setiap karakter demi karakter.
  • Dalam proses ini deretan karakter pada program sumber dibaca dari kiri ke kanan dan dikelompokkan menjadi token yaitu barisan karakter yang dalam suatu kesatuan mempunyai arti tersendiri.
  • Scanner merupakan antarmuka antara program sumber dan analisis sintaktik (parser). Scanner melakukan pemeriksaan karakter per karakter pada teks masukan, memecah program sumber menjadi bagian- bagian terkecil yang disebut Token.
  • Scanner mengerjakan pengelompokan karakter untuk menghasilkan suatu Token Leksikal menjadi beberapa komponen pokok, yaitu:
    • identifier,
    • simbol-simbol operator,
    • angka,
    • keyword,
    • noise word,
    • blank,
    • komentar, - dan seterusnya.

  • Model dasar untuk membentuk suatu Analisis Leksikal adalah Finite- State Automata atau Automata Hingga.
  • 2 aspek penting pembuatan Analisis Leksikal adalah: ∗ Menentukan token-token bahasa. ∗ Mengenali token-token bahasa dari program sumber.
  • Analisis Leksikal 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, konstanta, literal dan numerik ke tabel simbol.

  • Scanner merupakan komponen kompilasi independen yang berkomunikasi dengan parser lewat antarmuka yang terdefinisi, sehingga perubahan-perubahan pada scanner tidak berdampak pada pengubahan kompilator secara keseluruhan.
  • Pada analisis leksikal yang dituntun tabel (table-driven lexical analyzer), maka satu-satunya yang berubah adalah tabel itu sendiri.
  • Interaksi analisis leksikal dan analisis sintaktik lebih kompleks. Analisis leksikal harus dapat menganggap string sebagai token bertipe, bukan identifier.
  • Scanner dapat memasukkan string ke tabel simbol, mengidentifikasi sebagai Type atau typedef, sehingga analisis leksikal dapat memeriksa tabel simbol untuk menentukan apakah lexeme adalah token.
  • 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 berhubungan langsung dengan kode sumber, maka analisis leksikal juga bertindak sebagai benteng untuk komponen lain di kompilator dalam mengatasi keanehan-keanehan sistem masukkan/ keluaran, sistem operasi dan sistem komputer.

  • Optimasi perlu dilakukan agar analisis leksikal membaca karakter dengan 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 baris komentar dan whitespace (tab, spasi, dll.).

  Tindakan housekeeping dilakukan scanner sehingga mengisolasikan dari parser dan komponen-komponen kompilator lain.

  Scanner juga mencatat nomor baris saat itu, sehingga penanganan kesalahan 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. Karena itu membatasi analisis leksikal hanya untuk melakukan tugas pengenalan pola token (ditambah membuang komentar) adalah untuk mempermudah pemeliharaan. Tahap Pelaksanaan Analisis Leksikal ¾ Pada single one pass

  Terjadi interaksi antara scanner dan parser. Scanner 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 o Scanner harus dapat mengenali token o Terlebih dahulu dideskripsikan token-token yang harus dikenali

  2. Pendeskripsian Token o Menggunakan reguler grammar. Menspesifikasikan aturan-aturan pembangkit token-token dengan kelemahan reguler grammar menspesifikasikan token berbentuk pembangkit, sedang scanner perlu bentuk pengenalan. o Menggunakan ekspresi grammar. Menspesifikasikan token-token dengan ekspresi reguler. o Model matematis yang dapat memodelkan pengenalan adalah finite- state acceptor (FSA) atau finite automata.

  3. Implementasi Analisis Leksikal sebagai Finite Automata Pada model analisis leksikal sebagai pengenal yang menerapkan finite automata, analisis leksikal tidak hanya mengatakan YA atau TIDAK.

  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. Alternatif pemulihan tersebut adalah: o "Panic mode" dengan menghapus karakter-karakter berikutnya sampai analisis leksikal menemukan token yang terdefinisi bagus o Menyisipkan karakter yang hilang o Mengganti karakter yang salah dengan karakter yang benar o Mentransposisikan 2 karakter yang bersebelahan. Salah satu cara untuk menemukan kesalahan pada 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.

  C ara umum untuk membentuk suatu penganalisis leksikal adalah

  • dengan membuat suatu diagram yang menggambarkan struktur token dari suatu bahasa sumber, dan
  • kemudian menerjemahkan diagram tersebut secara manual ke dalam program untuk mencari token tersebut.

PERAN PENGANALISIS LEKSIKAL

  • P enganalisis leksikal merupakan fase pertama pada sebuah kompilator.

  Fungsi penganalisis leksikal adalah : ™ membaca program sumber karakter demi karakter, menerjemahkannya menjadi deretan token sebagaimana dispesifikasikan dalam spesifikasi leksikal bahasa sumber. ™ melakukan pembuangan baris-baris komentar, ruang kosong seperti karakter spasi, tabulasi dan baris baru dari program sumber. ™ menghubungkan antara pesan-pesan kesalahan (error messages) yang diperoleh oleh kompilator dengan program sumber.

  Dengan kata lain, tugas penganalisis leksikal adalah membaca karakter input dan memproduksi barisan dari token yang digunakan oleh suatu pengurai untuk melakukan analisis sintaks.

  Interaksi antara penganalisis leksikal dengan penganalisis sintaks ditunjukkan pada gambar berikut. token

  Source Lexical parser program analyzer get next token

  Symbol table Secara umum tugas penganalisis leksikal dapat dibagi menjadi tiga kelompok tugas sebagai berikut :

  • membaca program dan membaginya ke dalam token,
  • membuang dari program sumber semua komentar, ruang kosong seperti karakter spasi, tabulasi dan baris baru,
  • menghubungkan antara pesan-pesan kesalahan yang diperoleh oleh kompilator dengan program sumber.

  Ada beberapa istilah yang perlu dipahami dalam penganalisis leksikal;

  • token,
  • pola, dan • lexeme.

  

Token adalah satuan terkecil dari bahasa sumber yaitu deretan karakter

terpendek yang mengandung arti.

  Token dikelompokkan menjadi beberapa jenis sbb.:

  • identifier
  • keyword
  • label
  • operator aritmetika dan assignment
  • operator relasional - tanda baca, dan sebagainya.

  Masing-masing token diberikan nomor penyajian internal atau sering disebut nomor token, misalnya sebagai berikut : nama variabel

  1 konstanta 2 label

  3 keyword 4 operator penambahan

  5 operator pemberian (assignment) 6 operator pengurangan

  7 operator perkalian 8 operator pembagian 9 tanda baca koma

  10 tanda baca : 11 tanda baca ; 12 dan lain-lain.

  

Pola dari suatu token adalah aturan yang menerangkan sejumlah lexeme

yang dapat menyatakan suatu token dalam suatu program sumber.

  Pola tersebut akan cocok dengan setiap rangkaian karakter dalam himpunan karakter tersebut.

  

Lexeme adalah barisan karakter dalam program sumber yang dicocokkan

oleh pola untuk menentukan suatu token.

  Contoh token, lexeme dan pola dapat digambarkan sebagai berikut :

  Token Sample Lexemes Informal Description of Pattern const

  const const

  if

  if if

  relation <, <=, =, <>, >, >= < or <= or = or <> or > or >= id pi, count, D2 letter followed by letters and digits num 3.1416, 0, 6.02E23 any numeric constant literal "core dumped" any characters between " and " except "

  Misalkan perintah Pascal berikut ini:

  Const pi = 3.1416; rangkaian karakter bagian dari pi adalah lexeme untuk token identifier. Atribut untuk token

  • Bila lebih dari satu pola cocok dengan suatu lexeme, maka penganalisis leksikal harus memberikan informasi tambahan mengenai lexeme tersebut yang sesuai dengan fase berikutnya dari kompilator.
  • Suatu token biasanya hanya mempunyai satu atribut saja, yaitu petunjuk pada entri tabel simbol di mana informasi dari token tersebut disimpan.
  • Petunjuk (pointer) menjadi satu-satunya atribut dari token. Contoh: Token dan nilai atribut yang diperoleh untuk perintah FORTRAN berikut;

  E = M * C ** 2 dituliskan dalam barisan pasangan berikut ini: <id, pointer pada entri tabel simbol untuk E> <assign_op> <id, pointer pada entri tabel simbol untuk M> <mult_op> <id, pointer pada entri tabel simbol untuk C> <exp_op> <num, bilangan bernilai 2>

  Kesalahan pada tingkat penganalisis leksikal

  Sebagai contoh kalimat program berikut fi ( a = f(x)) .......... Penganalisis leksikal tidak dapat mengatakan apakah fi ini merupakan kesalahan penulisan dari kata-kunci if atau suatu identifier yang belum didefinisikan. Hal lain yang juga mungkin terjadi adalah suatu keadaan di mana penganalisis leksikal tidak dapat melanjutkan proses karena tidak satupun pola untuk token yang cocok dengan bagian awal input yang berikutnya. "Kemungkinan" untuk mengembalikan proses dari suatu kesalahan adalah:

  1. Menghapus karakter yang berlebihan

  2. Memasukkan karakter yang hilang

  3. Mengganti karakter yang salah dengan karakter yang benar 4. Menukar letak dari dua karakter yang berdekatan. Contoh program dengan bahasa C untuk menerjemahkan ekspresi infix ke dalam postfix.

  • include <ctype.h> /* loads file with predicate is digit */ int lookahead; main()

  { lookahead = getchar(); expr(); putchar('\n'); /* adds trailing newline

  }

PENYANGGA INPUT

  

A da tiga cara pendekatan umum yang dapat digunakan untuk

  mengimplementasikan suatu penganalisis leksikal:

  1. Menggunakan perangkat bantu pembentuk penganalisis leksikal. Misal, LEX yang merupakan bagian dari sistem operasi UNIX.

  Perangkat ini dapat digunakan untuk membentuk suatu penganalisis leksikal berdasarkan suatu ekspresi-beraturan yang diberikan.

  2. Menuliskan program untuk penganalisis leksikal dengan menggunakan suatu bahasa pemrograman yang biasa digunakan dengan memanfaatkan I/O dari bahasa tersebut untuk membaca input

PENGENALAN TOKEN

  Salah satu untuk mengenali sebuah token, yaitu dengan metode

  

Automata Hingga (Finite Automata) atau Finite State Acceptor yang

  disajikan berupa diagram atau graf berarah yang disebut Diagram Transisi atau Graf Transisi atau Digraph. utomata Hingga dapat dibayangkan sebagai sebuah Mesin yang terdiri

  A

  ¾ dari Kepala Baca (Read Head), dan Kotak Kontrol Stata Hingga. ¾ Mesin ini membaca sebuah pita (tape), satu persatu karakter, dari kiri ke kanan, seperti gambar berikut:

  

R E A D N O T R E A D

READ HEAD FINITE – STATE ACCEPTOR

  ¾ Pada saat Automata Hingga mulai membaca pita, ia harus selalu mulai dari stata yang ditunjuk sebagai Stata Awal. ¾ Perpindahan atau transisi stata terjadi bila suatu karakter pita selesai dibaca.

  ¾ Beberapa stata dapat ditunjuk sebagai Stata Akhir, atau Stata Penerima. ¾ Bila pembacaan dimulai dari Stata Awal, dan berjalan sesuai dengan jalur hingga ke Stata Akhir, maka untai (deretan karakter) yang dibaca pada pita tersebut dikatakan diterima oleh Automata Hingga. ¾ Diagram Automata Hingga atau Diagram Transisi berbentuk Graf Berarah (tanda anak panah), dengan tambahan beberapa notasi khusus.

  Sebagai contoh adalah diagram berikut: digit digit

  Start digit S A B

  ¾ Digraf Automata Hingga pada gambar tersebut menerima bilangan Real, yang mempunyai paling sedikit satu digit sesudah titik desimal.

  Simpul dari Digraph tersebut menyatakan stata dari Automata Hingga. ¾ Stata pada Automata tersebut adalah Stata S, A dan B. Busur Digraph menghubungkan satu stata ke stata lain, karakter yang tertera di atas atau di samping busur tersebut menunjukkan simbol/label input (simbol dari karakter input) yang menyebabkan terjadinya transisi stata.

  ¾ Jika terdapat busur mengarah dari Simpul P ke Simpul Q, dengan label

  a, berarti bahwa terjadi transisi Stata P ke Stata Q bila terbaca a pada karakter pita (apabila memperoleh input karakter a). ¾ Anak panah berlabel "start" mengarah ke suatu Stata, menandakan bahwa Stata tersebut merupakan Stata Awal. Dalam gambar di atas

  

Stata Awal adalah S, Stata Peralihan adalah A dan Stata Akhir adalah B

yang disajikan berupa lingkaran ganda.

  ∗ Misalkan pita berisikan untaian karakter 112.75 (seratus dua belas koma tuju lima). Automata Hingga mulai bekerja dari Stata S, yakni Stata Awal, dan tetap berada di Stata S ini saat bilangan di depan titik desimal dibaca. Ketika tanda titik (titik desimal) dibaca, Stata berpindah ke Stata A, dan kemudian berpindah lagi ke Stata B ketika digit pertama sesudah titik desimal (dalam contoh ini adalah digit 7) dibaca. Automata Hingga kemudian membaca digit berikutnya, yakni 5, dan tetap berada di Stata

  B. Sekarang akhir dari pembacaan Pita sudah tercapai. Penelusuran token berakhir di Stata B, yang adalah Stata Penerima atau Stata Akhir. Ini berarti Automata Hingga menerima bilangan desimal yang diberikan, yakni 112.75, sebagai sebuah token.

  ∗ Jika penelusuran tidak sampai pada Stata B saat sesudah untai selesai dibaca seluruhnya, maka untai tersebut ditolak. Misalnya untai 112, untai ini termasuk kasus yang ditolak karena tidak mencapai ke Stata Penerima (Stata Akhir). Penolakan dapat pula terjadi apabila Transisi Stata tidak dapat dilakukan untuk suatu karakter yang dibaca. Misalnya di antara digit tersebut terdapat huruf. Sebagai contoh untai yang ditolak adalah sbb.: X15.25 ataupun 112.H75. ∗ Automata Hingga yang digunakan dalam contoh di atas disebut

  Deterministic Finite State Acceptor, atau Deterministic Finite State Automata, atau Automata Hingga Deterministik (AHD).

  Berikut ini adalah contoh sebuah Automata Hingga Deterministik dengan 2 (dua) simbol input dan 3 (tiga) Stata. V = (a,b), himpunan simbol input

  T

  K = (q , q , q ) himpunan Stata

  1

  2 Z = (q , q ), himpunan Stata penerima atau Stata akhir

  1 Stata Awal adalah q

  Fungsi next-state f : K x V Î K,

  T

  didefinisikan sebagai tabel berikut : f a b q q q

  1

  q q q

  1

  2

  q q q

  2

  2

2 Stata Awal q . Stata Akhir disajikan dengan lingkaran ganda.

  Bila f(q , a ) = q , maka terdapat busur/anak panah dari q ke q

  i j k i k dengan label a.

  Perlu dicatat bahwa Stata Awal dapat merangkap sebagai simpul penerima. Digraph pada contoh tersebut adalah sebagai berikut : Misalkan, w = a , a ,..., a adalah untai simbol input dari Automata M. Kita

  1 2 n

  dapatkan barisan Stata S , S , ....., S dengan S adalah Stata Awal, dan S =

  1 n i f(S , a ) untuk i > 0.

i-1 i

  Automata M dikatakan dapat menerima atau mengenal untai w tersebut, jika Stata terakhir S merupakan Stata Penerima. Himpunan semua untai

  n yang dapat diterima oleh Automata M kita notasikan dengan L(M). Sebagai contoh, Automata di atas dapat menerima untai aabababa, aaa, baab dan lain-lain untai lagi. Sedangkan untai yang ditolak adalah untai yang mengandung 2 buah b berturutan sbb.: bbaaaaaa, aabaabb, babbaa dan lain-lain.

  Sebagai contoh lain dari Automata Hingga adalah sbb.

  • Automata berisikan dua Stata, yakni Stata S dan A. Stata S adalah Stata Awal dan Stata A merupakan Stata Akhir. Di sini terlihat bahwa kita akan tetap berada di Stata A saat Automata membaca sesuatu karakter atau digit ataupun karakter khusus pada himpunan {#, @, $, _}.
  • Contoh lain yang lebih kompleks adalah pada gambar berikut. Contoh ini juga berbentuk Diagram Stata Hingga yang menggambarkan Diagram Transisi untuk sebuah Bahasa yang terdiri dari Token <, <=, =, >=, >, ( ), (, ), +, -, *, /, :=, identifier, ; , keyword, konstanta, literal (yang diapit oleh apostrof).
  • Komentar, yang dimulai dengan /* dan diakhiri dengan */, dan blank, diabaikan, dan diartikan semata-mata sebagai pemisah Token.
  • Busur berlabel "NOT" mendahului sebuah karakter, menunjukkan bahwa semua karakter input selain dari karakter tadi, akan mengikuti transisi. Busur berlabel "ERROR" menunjukkan bahwa suatu karakter adalah invalid (tidak berlaku), yang ditemukan dalam program sumber. Karakter ini bukan merupakan suatu Token yang manapun, kecuali jika ia terdapat di dalam komentar, atau dalam lateral.
  • Stata 5, 6, dan 7 digunakan untuk mengenali Token <, <=, dan <>. Jika bukan karakter = atau > mengikuti karakter <, maka Akseptor akan berakhir pada Stata Akhir 5, ini menunjukkan bahwa Token < telah terkenali. Dalam hal ini Token <= atau <> akan dikenali juga. Token <= bila Akseptor berakhir di Stata 6, atau Token <> bila berakhir di Stata 7.
  • Dengan cara yang sama, masing-masing Stata 2, 3, dan 4 digunakan untuk mengidentifikasi komentar dan Token /. Semua karakter sesudah tanda /* sampai dengan karakter yang diikuti oleh */ merupakan isi dari
komentar. Komentar tidak akan dikirim sebagai Token. Dan selanjutnya kembali ke Stata Awal.

  • Stata 19 dan 22 digunakan berturut-turut untuk mengenali identifier dan konstanta integer. Identifier dimulai dengan sebuah huruf dan diikuti sejumlah karakter alfanumerik. Konstanta merupakan sebarisan digit, yang dianggap satu Token sampai suatu karakter non numerik terbaca.
  • Stata 20 dan 21 mengidentifikasi untai literal. Literal dimulai dan diakhiri dengan tanda apostrof ( ' ), dengan Stata Akhir 21 menunjukkan akhir dari literal.
  • Dua tanda apostrof yang berturutan dapat digunakan untuk menyatakan sebuah karakter dalam untai. Bila hal ini terjadi maka transisi dari Stata 21 ke Stata 20 terjadi.

  Pertanyaan dan Soal Latihan

  1. Sebutkan tugas utama dari penganalisis leksikal, dan jelaskan interaksinya dengan bagian kompilasi yang lain.

  2. Apa yang dimaksudkan dengan Token, Pola dan Lexeme. Jelaskan dengan memberikan contoh.

  3. Penganalisis leksikal juga berfungsi untuk menghilangkan baris komentar yang ada dalam program. Jelaskan bagaimana mekanismenya.

  4. Tuliskan subprogram scanner dari Digraf Automata Hingga di atas ini untuk mengenali Token. Subprogram dapat berbentuk procedure ataupun function yang ditulis menggunakan bahasa pemrograman Pascal atau C. Token apa saja yang dikenal oleh Digraf tersebut.

  Misalkan a dan b adalah simbol input. Buatlah sebuah Automata 5. Hingga Deterministik M yang hanya dapat menerima untai yang mengandung sejumlah genap a. (Contohnya untai aababab atau aa dapat diterima, sedangkan untai ababa atau abbb tidak dapat diterima.)