Matakuliah Tahun Versi : T0522 / Teknik Kompilasi : 2005 : 1/6 Pertemuan 2 Lexical Analyzer 1 Learning Outcomes Pada akhir pertemuan ini, diharapkan mahasiswa akan mampu : • Mahasiswa dapat menjelaskan lexical analysis dan peranannya dalam teknik kompilasi (C2) • Mahasiswa dapat menjelaskan pengertian token, attribute, dan lexeme dan penggunaan regular expression (RE) dalam lexical analysis (C2) • Mahasiswa dapat mendemonstrasikan pengenalan token dengan menggunakan transisi diagram dan RE (C3) 2 Outline Materi • • • • • • • • • • • Peranan Lexical Analysis Input buffering Symbol table Regular Expression Regular Definition Pengenalan token, attribute dan lexeme Diagram Transisi Finite Automata Konversi dari RE ke NFA Konversi dari RE ke DFA Minimisasi DFA 3 Peranan Lexical Analyzer (Scanner) • Membaca Source program (input characters) & menghasilkan output berupa rangkaian token. • Scanner biasanya diimplementasikan dalam bentuk subroutine dari program Parser. Source Program Lexical Analyzer Token Parser Get Token Symbol Table • Hal lain yang juga biasa dilakukan oleh scanner : – Membuang comment &white space (blank, tab, dan newline character). – Menghasilkan error messages. 4 Beberapa Isu pada Lexical Analysis • Alasan mengapa Lexical Analysis dipisahkan dari Syntax Analysis : – Desain kompiler menjadi lebih sederhana – Efisiensi kompiler meningkat – Portabilitas kompiler meningkat • Token, Pattern dan Lexeme – Token: bagian terkecil dari suatu bahasa program yang mempunyai suatu arti/fungsi. – Lexeme: Rangkaian karakter pada source program yang sama (“matched”) dengan pola (“pattern”) suatu token. – Pattern: Suatu pola/ rule/ aturan yang menggambarkan struktur suatu token. 5 Contoh Token, Lexeme dan Pattern Token Contoh Lexeme Contoh Pattern const_sym if_sym relation const if <,<=,=,<>,>,>= id pi, count, d2 num 3.14, 0, 6.0E10 literal “Hallo” const if < atau <= atau = atau <> atau > atau >= Letter diikuti oleh letters atau digits Sembarang konstanta angka Sembarang karakter “diantara“ dan “kecuali “ • Token selalu merupakan “terminal symbol” pada grammar suatu bahasa • Umumnya pada bahasa pemrograman bentuk-bentuk berikut diperlakukan sebagai token : keyword, operator, identifier, konstanta, string literal, simbol-simbol pungtuasi. 6 Atribut-atribut Token • • • • Informasi tentang token Menentukan pada saat penerjemahan token Disimpan dalam symbol table Pada prakteknya, token mempunyai single attribute, berupa pointer ke lokasi (entry) pada symbol table dimana informasi lain tentang token disimpan. • Biasa dituliskan sebagai : < token, attribut, value > • Contoh: E := M * C + 2 – Token - tokennya akan dihasilkan sbb: • • • • • • • < id, pointer to symbol table untuk E > < assign_op, > < id, pointer to symbol table untuk M > < mult_op, > < id, pointer to symbol table untuk C > < add_op, > < num, integer value 2 > 7 Input Buffering • Fungsi : menyimpan hasil scanning untuk menemukan token • Untuk menemukan 2 token digunakan 2 pointer : – Pointer forward: menunjuk akhir token – Pointer lexeme_beginning: menunjuk awal token E = M * C * * 2 eof forward lexeme-beginning • Buffer hanya menampung satu baris perintah 8 Lexical Error Handling • Hanya sedikit kesalahan yang dapat dideteksi pada tahap lexical analysis • Jenis kesalahan yang dapat dideteksi, yaitu bila scanner menemukan invalid character yang bukan merupakan bagian atau menyalahi pattern suatu token. • Strategi Error-Recovery : – Paling sederhana: “Panic mode”, yaitu menghapus karakter tersebut dan karakter – karakter berikut hingga ditemukan suatu token. – Menghapus sebuah karakter ekstra. – Menyisipkan sebuah karakter yang hilang. – Mengganti sebuah karakter yang salah dengan sebuah karakter yang benar. – Menukarkan dua karakter yang berdampingan. 9 Symbol Table • Symbol table adalah suatu struktur data yang digunakan untuk menyimpan informasi tentang komponen (token) suatu source program. • Informasi yang dimaksud : – Lexeme – Type of identifier – Kegunaan identifier (procedure,variable,label) • Informasi dikumpulkan saat tahap analysis, dan akan digunakan pada saat tahap synthesis. 10 Symbol Table Interface • Dua operasi utama : – insert (s,t) : menghasilkan indeks lokasi dimana string s disimpan, token t. – lookup (s) : menghasilkan indeks lokasi dimana s berada, atau 0 bila s tak ditemukan. • Penanganan Reserved Keywords – Biasanya reserved keywords disimpan di symbol table pada saat awal operasi kompiler Symbol table diinitialisasi Contoh : insert (“begin”, begin_sym) insert (“end”, end_sym) Sehingga bila dilakukan lookup(“begin”) akan menghasilkan token begin_sym. begin tidak bisa digunakan sebagai identifier. 11 String dan Languages • Alphabet atau character class adalah suatu himpunan terbatas dari simbol-simbol. – Contoh simbol: huruf-huruf dan karakter-karakter – Himpunan {0,1} adalah binary alphabet • String adalah rangkaian terbatas simbol-simbol yang terbentuk dari alphabet – Panjang suatu string s, biasa dituliskan |s|, adalah banyaknya simbol dalam string s – Contoh : Alphabet A = {a,b,c} string2 : a, abc |a| = 1 b, abca |abc| = 3 c, bc || = 0 Empty string 12 Istilah-istilah bagian dari suatu string • • • • • • • • • • • • • • • • prefix proper prefix suffix proper suffix substring proper substring subsequence Contoh : Bila s = abc, maka: prefix s : , a, ab, abc proper prefix s : a, ab suffix s : abc, bc, c, proper suffix s : bc, c substring s : prefix s suffix s b : , a, ab, abc, bc, c, b proper substring s : substring s- abc - subsequence s : substring s ac 13 Operasi pada String • Bila x dan y adalah string, maka concatenation x dan y, dituliskan xy adalah gabungan antara string x dan y (string y ditambahkan ke string x) • Contoh : bila x = dog, y = house, maka xy = doghouse, yx = housedog • = concatenation identity • x = x = x • Eksponensiasi string : s0 = s1 = s s2 = ss s3 = sss untuk i > 0, maka si = si-1s • Contoh s3 = s2s = sss • Language adalah suatu himpunan string-string yang berasal dari suatu alphabet tertentu. 14 Beberapa operasi terhadap language • Union () • Concatenation • Closure : - Kleene Closure (*) - Positive Closure (+) • Bila L dan M adalah Language, maka: – L M = { s | s is in L or s is in M } – LM = { st | s is in L and t is in M } – L* = Li – L+ = Li 15 Regular Expression (RE) • RE adalah suatu notasi yang bisa digunakan untuk mendefinisikan suatu himpunan (set) secara tepat. • RE pada teknik kompilasi digunakan untuk mendefinisikan token-token dari suatu language • Contoh : Token identifier pada Pascal, bisa ditulis sebagai : letter ( letter | digit )* dimana : | berarti “atau” ( ) digunakan untuk mengelompokkan subexpression * berarti “nol atau lebih” • Suatu RE dapat terdiri dari beberapa RE yang lebih sederhana sesuai dengan aturan RE yang telah didefinisikan sebelumnya. 16 Beberapa aturan definisi RE • • • adalah regular expression, yang mendefinisikan {} Bila a adalah simbol pada alphabet , maka a adalah RE yang menyatakan {a} Bila r dan s adalah RE untuk language L(r) dan L(s) maka : 1. 2. 3. 4. – (r)|(s) adalah RE untuk L(r) L(s) (r)(s) adalah RE untuk L(r)L(s) (r)* adalah RE untuk (L(r))* (r)2 adalah RE untuk L(r)2 Language yang didefinisikan oleh suatu RE disebut “regular set” (Himpunan regular) 17 Contoh RE Untuk alphabet = {a, b} 1. 2. 3. 4. 5. RE a | b menyatakan himpunan {a,b} RE (a | b)(a | b) menyatakan {aa,ab,ba,bb} RE a* menyatakan {,a,aa,aaa,...} RE a+ menyatakan {a,aa,aaa,...} RE (a | b)* menyatakan himpunan semua string yang terdiri dari nol atau lebih a atau b. 6. RE a|a*b menyatakan himpunan yang berisi semua string yang terdiri dari nol atau lebih a, diikuti oleh sebuah b. – Bila dua buah RE r dan s menyatakan language yang sama, maka r dan s disebut equivalent, dituliskan r = s Contoh : (a | b) = (b | a) 18 Regular Definition (RD) • RD adalah suatu sekuens/rangkaian definisi dalam bentuk : d1 r1 d2 r2 …….. dimana : di nama yang unik ri adalah RE yang terdiri dari simbolsimbol dalam {d1,d2,...dI-1} dn rn Contoh : • regular definition untuk identifier pada Pascal : – letter A|B|...|Z||a|b|...|z – digit 0|1|...|9 – id letter(leter|digit)* • RD untuk unsigned numbers: – – – – – digit 0|1|...|9 digits digit digit* Optional_fraction . digits | optional_exponent ( E (+|-|) digits ) | num digits optional_fraction optional_exponent 19 PENGENAL TOKEN • Perhatikan potongan tata bahasa berikut ini : stmt if expr then stmt | if expr then stmt else stmt | expr term relop term | term term id | num • dimana terminal if, then, else, relop, id dan num membentuk himpunan dari rangkaian yang diberikan oleh RD berikut : if if then then else else relop <|<=|=|<>|>|>= id letter (letter | digit )* num digit+(.digit+)?(E(+|-)? digit+)? 20 Translation table • Tujuan kita adalah menghasilkan lexical analyzer yang mengisolasi lexeme token-token berikutnya dari input buffer dan menghasilkan output berupa pasangan token dan nilai atributnya yang sesuai. • Untuk melaksanakan hal ini maka diperlukan translation table seperti di bawah ini. Regular Expression Token Nilai Atribut ws if if then then else else id id pointer pada entri tabel num num pointer pada entri tabel < relop LT <= relop LE = relop EQ <> relop NE > relop GT >= relop GE 21 TRANSITION DIAGRAM • Menyimpan informasi dari karakter yang terbaca oleh pointer forward saat sedang membaca input. Hal ini dilakukan dengan cara berpindah-pindah dari posisi satu ke lainnya saat membaca karakter. • Transition Diagram Bersifat Deterministik, dengan ketentuan: – Salah satu state diberi label state awal (posisi) dengan bentuk lingkaran sebagai awal bagan peralihan proses pengenalan token. – Bila ada sisi (tanda panah) dari state cocok dengan karakter input maka kendali akan pergi ke state yang ditunjuk oleh sisi. Jika tidak, pengenalan gagal. – Hanya satu simbol yang keluar dari state yang sama dan kemungkinan lebih dari satu sisi yang keluar dari state yang sama. 22 Contoh Transisi diagram • Transisi diagram untuk pola >= dan > : start > 0 = 6 7 * others 8 • Transisi diagram identifier dan keywords : letter or digit letter start 9 other 10 11 return (gettoken(), install_id()) gettoken() dan install_id() untuk memperoleh Token dan nilai atribut. Prosedur install_id() berguna untuk akses ke input buffer dimana lexeme diketemukan dan mengembalikan pointer pada entry Tabel Simbol. 23 Contoh Transisi diagram start 0 < = 1 return (relop, LE) 2 * > other = > 5 6 3 return (relop, NE) 4 return (relop, LT) * return (relop, EQ) = 7 return (relop, GE) * other 8 return (relop, GT) 24 FINITE AUTOMATA 1. OTOMATA BERHINGGA NON-DETERMINISTIK (NonDeterministic Finite Automata / NFA) : Model Matematika terdiri dari : – – – – – 2. Himpunan state dinyatakan dengan S. Himpunan simbol input (alfabet) dinyatakan dengan Fungsi transisi pindah move, memetakan pasangan state-simbol ke himpunan state. State S0 yang disebut sebagai state awal. Himpunan state F yang disebut sebagai state penerima (accepting state). OTOMATA BERHINGGA DETERMINISTIK (Deterministic Finite Automata / DFA) – – Tidak ada peralihan atas input Setiap state S & simbol input a, paling banyak satu sisi dengan label a yang meninggalkan S. 25 Contoh DFA b 0 a 1 b b 2 a 3 a a • Contoh di atas adalah graf peralihan (DFA) yang menerima bahasa (a | b)*abb • Keuntungan / Kerugian : – DFA lebih cepat menghasilkan pengenal – Ukuran DFA jauh lebih besar dari NFA untuk mengenal RE yang sama 26 Contoh NFA • Contoh graf transisi NFA : a 0 a 1 b 2 b 3 b • • • • S = { 0,1,2,3} adalah Himpunan State = {a,b} adalah alfabet simbol input S0= {0} ; F = {3} Implementasi fungsi peralihan NFA digunakan Tabel Peralihan (Translation Table) Input Symbol State a b 0 {0,1} {0} 1 {2} 2 {3} 27 KONVERSI DARI RE KE NFA • Merupakan salah satu strategi untuk membentuk sebuah recognizer (pengenal) dari sebuah RE. Algoritma THOMSON’S CONSTRUCTION : • – – – Input : RE r pada alfabet Output : NFA N yang menerima L(r) Metode: • • – Menguraikan r menjadi subexpression Gunakan aturan (1) & (2) berikut untuk membentuk NFA untuk setiap simbol dasar dari r (merupakan simbol alfabet atau ) Aturan : 1. Untuk , dibentuk NFA : start i f Dimana : i : start state yang baru f : accepting state yang baru NFA ini mengenal {} 28 Konversi RE ke NFA 2. Untuk a di dalam , bentuk NFA : start i a f Dimana: i : start state yang baru f : accepting state yang baru NFA ini mengenal {a} 3. Misalkan N(s) dan N(t) adalah NFA untuk regular expression s dan t a) Untuk RE s|t, bentuk NFA gabungan N(s|t): start N(s) f i N(t) Dimana: i : start state yang baru f : accepting state yang baru NFA yang terbentuk akan mengenali L(s) L(t) 29 Konversi RE ke NFA b) Untuk RE st, bentuk NFA gabungan N(st) start i N(s) N(t) f Dimana: Start state N(s) menjadi start state NFA gabungan Accepting state N(t) menjadi accepting state dari NFA gabungan NFA yang terbentuk mengenali L(s)L(t) c) Untuk RE s*, bentuk NFA gabungan N(s)* Start Dimana: i : start state yang baru f : accepting state yang baru NFA ini mengenali (L(s))* d) i N(s) f Untuk RE didalam kurung: (s), gunakan N(s) itu sendiri sebagai NFA yang baru. 30 Sifat-sifat NFA (thomson) • Algoritma diatas menghasilkan sebuah NFA N(r) yang memiliki sifat-sifat sebagai berikut : – N(r) mempunyai state paling banyak dua kali jumlah simbol dan operator di dalam r. – N(r) mempunyai tepat satu start state dan satu accepting state. Accepting state tidak memiliki transisi ke luar. – Setiap state di N(r) mempunyai satu transisi keluar untuk sebuah simbol di dalam atau paling banyak dua transisi keluar untuk simbol (transisi - ). • Contoh: berdasarkan algoritma tersebut bentuk NFA N(r) dari RE: r = (a | b)* abb 31 konversi RE ke DFA Algoritma konversi : Input : Sebuah regular expression r Output :DFA D yang mengenal L(r ). Method : 1. 2. 3. Buatkan syntax tree untuk augmented regular expression (r)#, di mana # adalah simbol unik yang ditambahkan pada akhir (r ). Tentukan nullable, firstpos, lastpos, dan followpos. Buat Dstates, himpunan state D, dan Dtran, transition table untuk D, dengan procedure berikut : Initially, unmarked state pada Dstates adalah firstpos(root), Di mana root adalah root dari syntax tree (r)#; while ada sebuah unmarked state T pada Dstates do begin mark T; for setiap input symbol a, do begin Misalkan U adalah himpunan posisi yang ada dalam followpos(p) untuk posisi-posisi p dalam T, sedemikian hingga symbol pada posisi p adalah a; if U not empty dan tidak dalam Dstates then tambahkan U sebagai unmarked state ke Dstates; Dtran[T, a] := U end end 32 Converting Regular Expressions Directly to DFAs • We may convert a regular expression into a DFA (without creating a NFA first). • First we augment the given regular expression by concatenating it with a special symbol #. r (r)# augmented regular expression • Then, we create a syntax tree for this augmented regular expression. • In this syntax tree, all alphabet symbols (plus # and the empty string) in the augmented regular expression will be on the leaves, and all inner nodes will be the operators in that augmented regular expression. • Then each alphabet symbol (plus #) will be numbered (position numbers). 33 Regular Expression DFA (cont.) (a|b) * a (a|b) * a # * a 1 b 2 Syntax tree of (a|b) * a # # 4 a 3 | augmented regular expression • each symbol is numbered (positions) • each symbol is at a leave • inner nodes are operators 34 followpos Then we define the function followpos for the positions (positions assigned to leaves). followpos(i) -- is the set of positions which can follow the position i in the strings generated by the augmented regular expression. For example, ( a | b) * a # 1 2 3 4 followpos(1) = {1,2,3} followpos(2) = {1,2,3} followpos(3) = {4} followpos(4) = {} followpos is just defined for leaves, it is not defined for inner nodes. 35 firstpos, lastpos, nullable • To evaluate followpos, we need three more functions to be defined for the nodes (not just for leaves) of the syntax tree. • firstpos(n) -- the set of the positions of the first symbols of strings generated by the sub-expression rooted by n. • lastpos(n) -- the set of the positions of the last symbols of strings generated by the sub-expression rooted by n. • nullable(n) -- true if the empty string is a member of strings generated by the sub-expression rooted by n false otherwise 36 How to evaluate firstpos, lastpos, nullable n nullable(n) firstpos(n) lastpos(n) leaf labeled true leaf labeled with position i false {i} {i} | c1 c2 c1 c2 * c1 nullable(c1) or nullable(c2) firstpos(c1) firstpos(c2) lastpos(c1) lastpos(c2) nullable(c1) and nullable(c2) if (nullable(c1)) if (nullable(c2)) true firstpos(c1) firstpos(c2) lastpos(c1) lastpos(c2) else firstpos(c1) else lastpos(c2) firstpos(c1) lastpos(c1) 37 How to evaluate followpos • Two-rules define the function followpos: 1. If n is concatenation-node with left child c1 and right child c2, and i is a position in lastpos(c1), then all positions in firstpos(c2) are in followpos(i). 2. If n is a star-node, and i is a position in lastpos(n), then all positions in firstpos(n) are in followpos(i). • If firstpos and lastpos have been computed for each node, followpos of each position can be computed by making one depth-first traversal of the syntax tree. 38 Example -- ( a | b) * a # {1,2,3} {4} {1,2,3} {3} {4}# {4} 4 {1,2}*{1,2}{3}a{3} 3 {1,2} {1,2} | {1} a {1} {2}b {2} 2 1 green – firstpos blue – lastpos Then we can calculate followpos followpos(1) = {1,2,3} followpos(2) = {1,2,3} followpos(3) = {4} followpos(4) = {} • After we calculate follow positions, we are ready to create DFA for the regular expression. 39 Algorithm (RE DFA) • • • • Create the syntax tree of (r) # Calculate the functions: followpos, firstpos, lastpos, nullable Put firstpos(root) into the states of DFA as an unmarked state. while (there is an unmarked state S in the states of DFA) do – mark S – for each input symbol a do • let s1,...,sn are positions in S and symbols in those positions are a • S’ followpos(s1) ... followpos(sn) • move(S,a) S’ • if (S’ is not empty and not in the states of DFA) – put S’ into the states of DFA as an unmarked state. • the start state of DFA is firstpos(root) • the accepting states of DFA are all states containing the position of # 40 Example -- ( a | b) * a # 1 followpos(1)={1,2,3} followpos(4)={} followpos(2)={1,2,3} 2 3 4 followpos(3)={4} S1=firstpos(root)={1,2,3} mark S1 a: followpos(1) followpos(3)={1,2,3,4}=S2 b: followpos(2)={1,2,3}=S1 mark S2 a: followpos(1) followpos(3)={1,2,3,4}=S2 b: followpos(2)={1,2,3}=S1 move(S1,a)=S2 move(S1,b)=S1 move(S2,a)=S2 move(S2,b)=S1 b start state: S1 accepting states: {S2} S1 a a S2 b 41 Example -- ( a | ) b c* # 1 followpos(1)={2} followpos(2)={3,4} followpos(4)={} 2 3 4 followpos(3)={3,4} S1=firstpos(root)={1,2} mark S1 a: followpos(1)={2}=S2 move(S1,a)=S2 b: followpos(2)={3,4}=S3 move(S1,b)=S3 mark S2 b: followpos(2)={3,4}=S3 move(S2,b)=S3 mark S3 c: followpos(3)={3,4}=S3 start state: S1 accepting states: {S3} S2 a move(S3,c)=S3 b S1 b S3 c 42 Minimizing Number of States of a DFA • partition the set of states into two groups: – G1 : set of accepting states – G2 : set of non-accepting states • For each new group G – partition G into subgroups such that states s1 and s2 are in the same group iff for all input symbols a, states s1 and s2 have transitions to states in the same group. • Start state of the minimized DFA is the group containing the start state of the original DFA. • Accepting states of the minimized DFA are the groups containing the accepting states of the original DFA. 43 Minimizing DFA - Example a a 1 G1 = {2} G2 = {1,3} 2 b b a G2 cannot be partitioned because 3 move(1,a)=2 move(3,a)=2 b move(1,b)=3 move(2,b)=3 So, the minimized DFA (with minimum states) b {1,3} a a {2} b 44 Minimizing DFA – Another Example a a 1 2 a Groups: 4 b a b 3 {1,2,3} {1,2} b {3} no more partitioning b So, the minimized DFA {4} a b 1->2 2->2 3->4 1->3 2->3 3->3 b a {3} b a {1,2} a b {4} 45 Some Other Issues in Lexical Analyzer • The lexical analyzer has to recognize the longest possible string. – Ex: identifier newval -- n ne new newv newva newval • What is the end of a token? Is there any character which marks the end of a token? – It is normally not defined. – If the number of characters in a token is fixed, in that case no problem: + – But < < or <> (in Pascal) – The end of an identifier : the characters cannot be in an identifier can mark the end of token. – We may need a lookhead • In Prolog: p :- X is 1. p :- X is 1.5. The dot followed by a white space character can mark the end of a number. But if that is not the case, the dot must be treated as a part of the number. 46 Some Other Issues in Lexical Analyzer (cont.) • Skipping comments – Normally we don’t return a comment as a token. – We skip a comment, and return the next token (which is not a comment) to the parser. – So, the comments are only processed by the lexical analyzer, and the don’t complicate the syntax of the language. • Symbol table interface – symbol table holds information about tokens (at least lexeme of identifiers) – how to implement the symbol table, and what kind of operations. • hash table – open addressing, chaining • putting into the hash table, finding the position of a token from its lexeme. • Positions of the tokens in the file (for the error handling). 47