Bir Kod Parçasının Lexical Analizi (3)

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:

lexer10

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.

lexer11

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.

lexer12

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.

“Bir Kod Parçasının Lexical Analizi (3)” için bir yanıt

ömer için bir cevap yazın Cevabı iptal et

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

This site uses Akismet to reduce spam. Learn how your comment data is processed.