Lexer’in Kodlanması
Lexer’ı kodlamak için Qt4 çatısı altında c++ kullanıldı. Qt’nin kullanım nedeni arayüz bileşenlerinin kolay kullanılabilir olması ve işin C++ kullanılarak istenmesidir.
Arayüz aşağıdaki gibi oluşturuldu:
Qt arayüz oluştururken butonlar ve seçenekler için action’lar oluşturur. Bu action’lar istenirse bir fonksiyonla tetiklenebilir ve amaçlanan iş yaptırılabilir.
Qt4’ün Dosya Yapısı ve Kodlar
mainwindow.ui isimli bir xml dosyası bulunmaktadır. Bu xml dosyası Qt designer tarafından oluşturulur.
main.cpp dosyası ana dosyadır. İçerisinde aşağıdaki kod bulunmaktadır.
#include"mainwindow.h" #include<QApplication> intmain(intargc,char*argv[]) { QApplicationa(argc,argv); MainWindoww; w.show(); returna.exec(); }
Program buradan çalışmaya başlayacaktır. MainWindow isimli sınıftan w isimli bir pencere tanımlanmış ve show() metodu çalıştırılmıştır.
mainwindow.cpp pencere nesnesinin fonksiyonlarının kodlandığı yerdir. Mainwindow.h kütüphanesini kullanır.
mainwindow.h, MainWindow sınıfının türetildiği kütüphanedir. MainWindow sınıfı da görüldüğü üzere QmainWindow sınıfından türetilmiştir. QmainWindow, Qt çatısının sağladığı sınıflardandır.
mainwindow.h aşağıdaki gibidir:
#ifndefMAINWINDOW_H #defineMAINWINDOW_H #include<QMainWindow> #include<QtCore> #include<QtGui> //Tanınanacak final durumları sabitlere atanıyor. #defineD_PARANTEZ10 #defineD_FLOAT11 #defineD_WHILE12 #defineD_IF15 #defineD_ASIGN16 #defineD_COMMA17 #defineD_LESS_BIG18 #defineD_INT20 #defineD_ASSIGN_MP21 #defineD_COMPARE22 #defineD_PLUS_MINUS0 structtoken_t{ inttype;//yukarıdaverilentokenkodlarındanbiri union{ charstringValue[256];//eğerstringveyatanımlayıcıysaburadalexeme'itutar intintValue;//integeriselexemeburadatutulur floatfloatValue;//double'salexemeburadatutulur voidcleanstring(){ for(inti=0;i<256;i++){ stringValue[i]=''; } } }val; }; namespaceUi{ classMainWindow; } classMainWindow:publicQMainWindow { Q_OBJECT public: explicitMainWindow(QWidget*parent=0); ~MainWindow(); //Qt'nin yapısında yer alan slotların içine kendi fonksiyonlarımızı tanımlıyoruz. privateslots: voidon_actionNew_triggered(); voidon_actionA_triggered(); voidon_actionKaydet_triggered(); voidon_actionFarkl_Kaydet_triggered(); voidon_actionYap_t_r_triggered(); voidon_actionKopyala_triggered(); voidon_actionGeri_Al_triggered(); voidon_action_leri_Al_triggered(); voidon_actionLexical_Analiz_Yap_triggered(); voidon_actionGeli_tirici_triggered(); voidon_actionKes_triggered(); voidon_actionYazd_r_triggered(); voidon_action_kt_Penceresini_Temizle_triggered(); intscan(QChargrText); private: Ui::MainWindow*ui; QStringmFileName; }; #endif//MAINWINDOW_H
mainwindow.cpp dosyasında ise fonksiyonlar gerçekleştirilmektedir. Burada tüm fonksiyonlara değinilmeyecektir. Sadece “voidon_actionLexical_Analiz_Yap_triggered()” ve “scan” fonksiyonlarına bakılacaktır. Burada lexer için gerekli kodlar yazılmıştır. Açıklamaları satır içinde yapılmıştır. Daha önce bahsedilen temel algoritma burada aynen uygulanmaktadır.
intMainWindow::scan(QChargrText) { if(grText.isDigit())//gelen karakterin sayı olup olmadığı kontrol ediliyor return6; chartempChar=grText.toAscii();//qchar char dönüşümü gerçekleşiyor //Eğer qchar char dönüşümü gerçekleşmezse switch case yapısı kullanılamaz. printf("Gönderilenkarakter%cn",tempChar); switch(tempChar){ case'(': return0; break; case')': return1; break; case'{': return2; break; case'}': return3; break; ... } if(grText.isLetter()) return9; } voidMainWindow::on_actionLexical_Analiz_Yap_triggered() { structtoken_ttoken; intkTransitionTable[23][23]={{geçiş tablosu satır1} {geçiş tablosu satır2} .............. }; QStringkAcceptTable[23]={"TOKEN_+-","ID","ID","ID","ID","ID","ID","ID","ID","ID","TOKEN_BRACE_PAREN","TOKEN_FLOAT","TOKEN_WHILE","TOKEN_IDENTIFIER","DIGIT","TOKEN_IF","TOKEN_ASSIGN_MARK","TOKEN_COMMA","TOKEN_LESS_OR_BIGGER","ID","TOKEN_INT","TOKEN_MINUS_OR_PLUS","EMPTY_STRING"}; QStringstr=ui->textEdit->toPlainText(); QByteArrayba=str.toLatin1(); char*symbol=ba.data();//Tümmetindinamikchardeğişkenedönüştürülüyor. //QChar*inputText=ui->textEdit->toPlainText().data(); printf("symbol=%sn",symbol); QChartempText; intstate=9;//başlangıçdurumuayarlamaları ui->textBrowser->setText("");//textbrowserayarı intj=0; token.val.cleanstring();//char kalıntıları temizleniyor printf("stringboyutu%dn",str.size()); for(inti=0;i<str.size();i++){ //printf("symboltypeun",symbol[i]); printf("i=%dj=%dn",i,j); tempText=symbol[i]; if(state==9){ j=0; } token.val.stringValue[j]=symbol[i]; intresult=scan(tempText); printf("scan(tempText)type=%dn",result); printf("kTransitionTable[%d][%d]",state,result); state=kTransitionTable[state][result];//sırayla durum değişiyor printf("=%dnn",state); QStringtype=kAcceptTable[state]; //QStringqStr=QString::number(state); QStringt_value=token.val.stringValue; switch(state){ caseD_PARANTEZ: ui->textBrowser->insertHtml(t_value.append("-")); ui->textBrowser->insertHtml(type.append("<br/>")); j=0;//textbrowser'a yeni gelecek kelime için j sıfırlanır token.val.cleanstring(); state=9;//otomatta bahsedildiği gibi durum başa döner. İlk durum 9'dur break; caseD_FLOAT: ui->textBrowser->insertHtml(t_value.append("-")); ui->textBrowser->insertHtml(type.append("<br/>")); j=0; token.val.cleanstring(); state=9; i--; break; caseD_WHILE: ui->textBrowser->insertHtml(t_value.append("-")); ui->textBrowser->insertHtml(type.append("<br/>")); j=0; token.val.cleanstring(); state=9; break; ... default: j++;//eğer herhangi bir kelime tanınmamışsa artış gerçekleşir.break; } } }
Çıktılar
Program parantezleri, float sayıyı, while’ı, if’i, atama operatörünü, noktalı virgülü, küçüktür büyüktür işaretlerini, int anahtar kelimesini, karşılaştırma operatörünü, artı-eksi işaretlerini ve tanımlıyıcıları tanımaktadır.
while (y < z) {
int x = a+b;
y+=x;
}
Örneğinin analizini aşağıdaki gibi yapabilmektedir.
while if {} [ } ] + - a = b; ; a++; a<
gibi bir örnek yazıldığında analizini aşağıdaki şekilde yapmaktadır. Ayrıca yazılan metin kaydedilebilir. Kaydedilmiş bir metin açılarak lexical analizi yapılabilir.
Kodların tamamını incelemek ve indirmek için buraya tıklayınız.
Not: Burada tam bir lexer yazılmamıştır. Bu şekilde kodlama yapıldığında bazı tokenların tanınması mümkün olmamaktadır. Temel amaç otomatlarla lexer yazımı için yol göstermektir.
eyw