• Tidak ada hasil yang ditemukan

Derleyici Tasarımı - D Programlama Diline İlişkin Derleyici Tasarımı

N/A
N/A
Protected

Academic year: 2021

Membagikan "Derleyici Tasarımı - D Programlama Diline İlişkin Derleyici Tasarımı"

Copied!
12
0
0

Teks penuh

(1)

Derleyici Tasarımı – Dönem Ödevi

D Programlama Diline İlişkin Derleyici Tasarımı

Proje’nin amacı D programlama dilinde verilen program kodunun derlenip çalıştırılmasını sağlayan bir derleyici tasarlamaktır. Derleyici yapılırken programalama dili olarak C++, geliştirme ortamı olarak ise Windows işletim sisteminde çalışan Visual Studio kullanılmıştır. Ortaya çıkan çalıştırılabilir dosyanın gereksinimleri ise Windows işletim sistemi olan bir bilgisayardır.

Program 3 farklı yapıya sahiptir;

 Tarayıcı  Ayrıştırıcı  Yorumlayıcı

1) Tarayıcı

Tarayıcı işlev olarak gelen kaynak kodunu sözcüklere indirger. Karakter karakter taradığı kaynak kodunu, dilin tanımlı sözcüklerine çevirir ve bunları bir sözcük dizisi olarak tutar. Dilde tanımlı olmayan bir karakter geldiğinde hata verir. Bu işlemi gerçekleştirmek için öncelikli olarak dilin tanımlı sözcükleri bir NFA oluşturacak şekilde kullanılır;

Örneğin “var” kelimesi;

V a r

Görüldüğü üzere girişten v-a-r karakterleriyle son duruma giden bu NFA gibi diğer sözcüklerin de NFA’ları yaratılır ve hepsi tek bir başlangıç konumunda birleştirilir. Oluşturulan bu NFA daha sonra DFA’ya çevrilir. Bütün bu işlemlerin gerçekleştirildiği kısmın kaynak kodu ve sınıfları aşağıda gösterilmiştir;

class

Otomat

{

Durum *eskiDurumListe; //NFA aĢamasındaki durum listesi

Durum *dfaDurumListe; //DFA'ya dönüĢürken yeni oluĢan

durumların eklendiği liste

int dfaDurumSayi; //DFA durum sayısını tutan değiĢken char *tumKarakterler[1000]; //GeçiĢ için kullanılan tüm

karakterlerin listesi public:

(2)

Durum & nfa2dfa(); //NFA DFA dönüĢümünü yapan metod void dfaGecisYarat( Durum *); //Verilen sözcüklere göre DFA

geçiĢlerini yaratır

bool ayniDfaDurumVarmi(int *); //NFA - DFA dönüĢümü sırasında oluĢan yeni durumların daha önce oluĢturudu mu diye kontrol eder

void dfaYarat(int *altDurumList);//DFA için durum yaratır

Durum & dfaDurumBul(int*); //DFA listesindeki durumlar içinde

arama yapar

bool kontrolEdilmemisVarMi(); //DFA oluĢtururken tüm karakterlere geçiĢleri kontrol edilmemiĢ durum var mı diye bakar

};

class

Durum{

Gecis *gecisListe; //Tüm geçiĢlerin listelendiği dizi

int id; //Durum id'sini tutar

int gecisSayi; //Sahip olduğu geçiĢlerin sayısını tutar bool baslangic; //BaĢlangıç durumu olup olmadığını tutar bool son; //Son durum olup olmadığını tutar

bool dfa; //DFA'ya ait olup olmadığını tutar, false ise bir NFA dahilindedir

int *altDurumListe; //DFA dahilinde bir durumsa, dönüĢüm sırasında temsil ettiği NFA durumlarının listesi vardır

bool dfaGecisKontrol; //DFA dönüĢümü sırasında tüm geçiĢlere karĢılığı bulunmuĢ mu onu belirtir. FALSE ise iĢlem yapılmamıĢtır

char * sozcukTip; //Eğer son durum ise hangi sözcüğün son durumu olduğu bilgisini tutar

public:

Durum(int,char*,char*); //Constructor

Durum(); //Default constructor

void yeniGecis(Durum&,char* ); //Bu durumdan yeni bir geçiĢ yaratır (baĢka duruma)

void setId(int); //Id atar

int getId(); //Id döndürür

void baslangicYap(); //baĢlangıç durumu yapar

void sonYap(); //Son durum yapar

bool baslangicKontrol(); //BaĢlangıç durumu olup olmadığını döndürür

bool sonKontrol(); //Son durum olup olmadığını döndürür

void ayarlaDfa(); //DFA durumu yapar

void sifirlaDfaGecisKontrol(); //DFA gecis durumunu false yapar void ayarlaDfaGecisKontrol(); //DFA gecis durumunu true yapar

bool alDfaGecisKontrol(); //DFA gecis durumunu döndürür int * closureIdAl(); //Closure kümesini döndürür (id) void altDurumListeEkle(int *); //Alt durumlarına liste ekler (DFA dönüĢümü sırasında)

int * gecisAl(char*); //GeçiĢlerin listesini döndürür int gecisIdAl(char*); //istenen geçiĢin id'sini döndürür

Durum & sonrakiDurumAl(char *); //Belirtilen geçiĢ için sonraki

durumu verir

int * altDurumListeAl(); //DFA dönüĢümü sırasında temsil ettiği durumların listesini ver,r

char * alSozcukTip(); //Sozcuk tipini döndürür void degistirSozcukTip(char *); //Sozcuk dipini değiĢtirir };

(3)

class

Gecis{

Durum *sonraki; //Bu geçiĢin iĢaret ettiği sonraki

durumun iĢaretçisi

char* gecisKatar; //GeçiĢin hangi katarla yapıldığı public:

Gecis(Durum &, char*); Gecis();

bool operator==(Gecis const &) const; //Operatör overload, eĢit mi?

char* gecisKatarAl() const; //GeçiĢ katarını döndürür

Durum & sonrakiDurumAl(); //Sonraki durumu

döndürür

};

Yukardaki sınıf tanımları NFA – DFA dönüşümü için kullanılmıştır. Yarattığım Otomat objesinin içinde bir durum listesi bulunmaktadır. Bu durumlar da bir birleriyle geçiş objeleri sayesinde bağlıdır. Her durumda bir geçiş listesi bulunmaktadır. Bu geçişler bir sonraki duruma ait bir işaretçi taşır. Her geçişin hangi karakter için olduğu da yine bu geçiş objelerinde saklanmaktadır. Bu sayede bir NFA bilgisayarda simüle edilebilir. Öncelikle tüm sözcük tipleri NFA olarak otomata yerleştirirlir. Daha sonra otomat bu NFA’ları tek bir başlangıç durumuyla birleştirir. Oluşan bu yeni NFA üzerinde DFA dönüşümü yapılır. Boş katar olarak “#” kullanılmıştır. Otomat daha sonra sahip olduğu bu DFA ile programı sözcüklere ayırabilmektedir.

DFA oluşturulduktan sonra oluşturulan Tarayici objesine bu DFA’nın ilk durumu eklenir (işaretçisi) Tarayıcı sınıfının yapısı aşağıdaki gibidir;

class

Tarayici

{ public:

Sozcuk *sozcukListe; //Son durumda oluĢacak sözcük listesi

int sozcukSayi; //Sözcük listesindeki sözcük sayısı

char *girilenKod; //DOsyadan okunan ve taranacak kod

Durum *dfaIlkDurum; //DFA'nın ilk durumu

char * tumKarakterler[1000];//Dildeki olası tüm karakterlerin listesi

DegiskenTablosu degiskenTablo; //DeğiĢken tablosu

bool islemIzin; //DeğiĢken tablosunda iĢlem izni Tarayici(Durum &);

void SozcukListeYarat(); //Sözcük listesi oluĢturur bool tekSozcukCek(); //Koddan tek bir sözcük tarar void dosyadanOku(); //Dosyadan okur

(4)

class

Sozcuk{

public:

char *icerik; //Sozcugun içeriği (x,y,val, ifzero vs.) char * tur; //Sozcuğun turu (id,num vs)

int *val; //Sözcük num ise, sahip olduğu int değeri Sozcuk();

Sozcuk(char * ,char * );

void print(); //yazdırır };

DFA’ya sahip olan tarayıcı objesi, dosyadan (kod.txt) ilgili kodu okur. Daha sonra bu kodu,

otomata sokarak, çıkan son durumlara göre sözcük listesine sözcükleri ekler. Böylece girilen

kod sözcüklere ayrılmış bir şekilde eklenir. Üzerinde çalıştığımız D programlama dilinde

girilen tek karakterler değişken olarak algılandığından Tarayıcının kodda hata bulması

mümkün değildir. Çünkü hatalı olan tüm a-z karakterleri değişken olarak kaydedilmektedir.

Fakat beklenmeyen bir karakter geldiğinde ( mesela ! ) tarayıcı işlemi iptal edip, bu karakteri

tanımadığını belirtir. Yine D programlama dilinde değişkenler

Var a;

Şeklinde tanımlanmaktadır. Bu durumda tarayıcı değişkeni DegiskenTablosu tipindeki

tablosuna ekler. Bu sınıfın yapısı aşağıda incelenmiştir.

class

DegiskenTablosu{

public:

Degisken *liste; //DeğiĢkenlerin tutulduğu liste

int degiskenSayi; //değiĢken listesindeki obje sayısı int sonDerinlik; //Son kullanılan derinlik

DegiskenTablosu();

void yeniDegiskenEkle(string yeniIsim); //Yeni değiĢken ekler

Degisken & degiskenBul(string yeniIsim); //EklenmiĢ değiĢkenlerden

isme göre tarama yapıp iĢaretçisini döndürür };

class

Degisken{

public:

int deger; //DeğiĢkenin tuttuğu int tipinden değer

string isim; //DeğiĢkenin tanımlanmıĢ ismi

int derinlik; //Sahip olduğu derinlik Degisken();

Degisken(int yeniDeger,string yeniIsim,int yeniDerinlik); };

Değişken tablosu bir değişken dizisi ihtiva eder. Ayrıca tabloda sonDerinlik isimli bir int değeri

vardır. Bu değer {block} durumlarında değişkenlerin ayırt edilmesini sağlar;

(5)

{ var x y; // x derinliği=0, y derinliği=0 set x = 1 + (3 - 2) ; // x derinliği = 0

{ var x ; // yeni bir x derinliği 1

set y = x + ( 2 + y) ; //derinliği 1 olan x ile derinliği

0 olan y iĢlemde

} }

Yani her { geldiğinde derinlik 1 arttırılır, her } geldiğinde derinlik 1 azaltılır. Bu çözüm sanırım

derste kullandığımızla aynı değildi ama ben 3. Ödeve gelene kadar kurduğum yapıya daha

uygun bir çözüm bulamadım. Yorumlama sırasında bu yöntem bana büyük kolaylık sağladı.

Değişken tablosunda liste halinde bulunan Değişken objeleri ise değişken hakkında gerekli

bilgileri tutar.

Özet olarak, tarayıcı gelen katar dizisini bir sözcük dizisine çevirir ve değişkenleri değişken

tablosuna kaydeder. Bundan sonraki aşama ayrıştırıcının işidir.

2) Ayrıştırıcı

Ayrıştırıcının gerçeklenmesi için verilen gramer kurallarının uygun bir şekilde kodlanması gerekmektedir. Bu yapı için aşağıdaki sınıfları yarattım;

class Sembol{ public:

string isim; //Sembolün ismi, burada program, exp, term vs

birer semboldür

bool terminal; //terminal/nonterminal belirtir

string *ilk; //Ġlk kümesi oluĢturulduktan sonra bu liste

kullanılacak

int ilkSayi; //ilk kümesi için liste eleman sayısı

string *izle; //Ġzle kümesi oluĢturulduktan sonra burada

tutulacak

int izleSayi; //izle kümesi için liste elemen sayısı Sembol();

Sembol(string yeniIsim,bool terminalMi);

string isimAl(); //isim döndürür

bool esitKontrol(string kontrolIsim); //Verilen sözcükle aynı olup olmadığını döndürür

};

class Kural{ public:

Sembol solTaraf; //Gramer kuralının sol tarafındaki sembol ü

tutar

Sembol * sagTaraf; //Sağ taraftaki sembol veya sembol

listesini tutar

(6)

Kural();

Kural(Sembol & yeniSolTaraf);

void sagTarafEkle(Sembol & yeniSembol); //Yeni bir kural yaratılırken sağ taraf listesine sembol ekler

Sembol & solTarafAl(); //Sol tarafı

döndürür

};

class Gramer{ public:

Kural *kuralListe; //TÜm kuralların

listelendiği dizi

int kuralSayi; //toplam kural sayısı

Sembol * sembolListe; //kullanılan tüm sembollerin

listelendiği dizi

int sembolSayi; //Toplam sembol sayısı

string girisKatar; //GiriĢ sözcüğü

Hucre * tablo; //AYrıĢtırma tablosunu

oluĢturan hücreler

int tabloSayi; //Hücre sayısı

Gramer(Sembol * yeniSembolListe, int yeniSembolSayi,string yeniGirisKatar );

Kural & yeniKural(string yeniIsim); //Yeni kural ekler

Sembol & sembolBul(string araIsim); //Verilen isimdeki sembolü

döndürür

void ilkOlustur(string yisim); //ĠStenen sembolün ilk kümesini oluĢturur

string * ilkAl(string yisim); //Ġstenen sembolün ilk kümesinin

iĢaretçisini döndürür

void izleOlustur(Kural & gKural); //Ġstenen sembolün izle kümesini oluĢturur

void tabloYarat(); //AyrıĢtırma tablosu

yaratır

void ilkKumeleriniOlustur(); //Tüm ilk kümelerini oluĢturur void izleKumeleriniOlustur(); //Tüm izle kümelerini oluĢturur

Hucre * tablodanCek(Sembol satir, string sutun); //Tablodu ilgili

satırın sütundaki karĢılığı döndürürlür };

Yukarıda görüldüğü üzere Gramer tipinden bir sınıfım var ve bu sınıfta kurallardan ve sembollerden oluşan bir liste var. Temel olarak bir Gramer objesi bir Kurallar listesi barındırıyor. Kuralların her biri de “sol” ve “sağ” olmak üzere 2 Sembol objesi tutuyor. Tabi ki sağ taraftaki sembol objesi aslında bir sembol dizisi.

Exp → set ID = exp

Şeklindeki bir kural, gramer’e aşağıdaki kodla eklenebiliyor; temp=&yeniGramer.yeniKural("exp");

temp->sagTarafEkle(yeniGramer.sembolBul("set")); temp->sagTarafEkle(yeniGramer.sembolBul("id")); temp->sagTarafEkle(yeniGramer.sembolBul("=")); temp->sagTarafEkle(yeniGramer.sembolBul("exp"));

(7)

Burada dikkat etmemiz gereken nokta, yeni kural eklerken kullandığımız isimlerin bir önceki aşamada ( tarayıcı) kullandığımız sözcüklerle aynı olması. Bu sayede tarayıcının hazırladığı sözcük dizisinin bu gramere uygun olup olmadığını kontrol edeceğiz.

Gramer kurallarını yukarıda bahsettiğim şekilde programa yerleştirdikten sonra yapmamız gereken İlk ve İzle kümlerini bulmak ve daha sonra Ayrıştırma Tablosunu oluşturmak.

Verilen gramerin sol rekürsif olmasından dolayı öncelikle bu sorunu ortadan kaldırmamız gerekiyor. Rekürsif bir ayrıştırıcı da sol rekürsif özelliklerin bulunması sonsuz döngüye sebebiyet vermektedir. Sol rekürsif ve factoring özellikleri giderildikten sonra oluşan gramerin ilk ve izle tabloları program kendisi yaratmaktadır. Ödevin 2. Tesliminde ekrana yazılan fakat son aşamada ekrana yazdırma gereği duymadığım ilk ve izle kümeleri aşağıdaki gibi verilmektedir.

Ilk kumeleri

Sembol Küme (boşlukla ayrılmış)

var var set set ifzero ifzero then then else else + + - - = = { { } } ( ( ) ) ; ; id id num num

program id num ( { set ifzero exp id num ( { set ifzero exp2 + - #

term id num ( {

block var id num ( { set ifzero

vars id

vars2 # id

exps id num ( { set ifzero

exps2 # ;

Izle kumeleri

Sembol Küme (boşlukla ayrılmış) program $

exp $ then else ) ; } exp2 $ then else ) ; } term + - $ then else ) ; }

block }

vars ;

vars2 ;

exps }

(8)

Bu kümeler şu şekilde listelenmiştir, sol tarafta kimin kümesi olduğu, sağ tarafta küme elemanları. Yani program sembolünün izle kümesinde sadece $ karakteri vardır. Oluşturulan bu kümelere göre ayrıştırma tablosu aşağıdaki gibidir;

Satır Sütun Sonuç Program id exp Program num exp program ( exp program { exp program set exp program ifzero exp exp id termexp2 exp num termexp2 exp ( termexp2 exp { termexp2 exp set setid=exp

exp ifzero ifzeroexpthenexpelseexp exp2 + +term exp2 - -term exp2 $ # exp2 then # exp2 else # exp2 ) # exp2 ; # exp2 } # term id id term num num term ( (exp) term { {block} block var varvars;exps block id exps

block num exps block ( exps block { exps block set exps block ifzero exps vars id idvars2 vars2 ; # vars2 id vars exps id expexps2 exps num expexps2 exps ( expexps2 exps { expexps2 exps set expexps2 exps ifzero expexps2 exps2 } #

exps2 ; ;exps

Yukarıdaki gösterim aslında tablonun değişik bir halidir. Derste gördüğümüz tabloyu kullanırken nasıl bir mantık izliyorsak program da aynı mantığı izlemektedir. Yığından gelen sembolü satır üzerinden seçiyor, sözcük dizisinden aldığını sütun kısmından ve sonucu alıyor. Kodda belirttiğim üzere aslında

(9)

Tablo Hücre objelerinden oluşmuş bir liste barındırıyor ve bu dizi içinde satır&sütun bilgileri girilerek yapılan bir arama sonucunu veriyor.

Yazmış olduğum kod esnek bir yapı barındırmaktadır. Yani dilenirse kolayca başka bir gramer girilip ayrıştırma tablosu otomatik olarak çıkartılabilir. Tek yapılması gereken gramer kurallarının girildiği kod parçasını yeni gramer e göre oluşturmaktır. Ayrıştırma tablosu tamamen kod çalışırken

oluşturulduğundan ayrıştırma fonksiyonlarını da elle yazmama gerek kalmamıştır. Tablodaki verilere göre ayrıştırma işlemini yapan Genel Fonksiyonum Yorumlayıcı kısmında ayrıntılı olarak işlenecektir. Ayrıştırma işleminin yapısına geri dönmek gerekirse, öncelikle bir yığın yaratır ve giriş sözcüğüyle $ karakterini bu yığına ekler. Sözcük listesine de $ karakterini ekledikten sonra yığından ve sözcük listesinden çektiği elemanları kullanarak tablodan yeni bir sembol alır. Bu sembolü yığına ekleyerek devam eder. Yığındaki $ karakterine karşılık sözcük listesinde $ karakterini görünce girilen kodun belirtilen gramere uygun olduğuna karar verir. Yığın sınıfı aşağıdaki gibidir;

class Yigin {

public:

Sembol * yiginListe; //Yığındaki sembollerin tutulduğu dizi

int yiginListeSayi; //Sembol dizisinin eleman sayısı Yigin();

Sembol & cek(); //Yığının en üstündeki sembolü

geri döndürüp yığından siler

void ekle(Sembol * yeni,int yeniSayi); //Yığına yeni sembol ekler

};

3) Yorumlayıcı

Yorumlayıcının görevi, dilin sözel olarak belirtilmiş anlamsal özelliklerini işlemek ve bir sonuç döndürmektir. Derleyicinin bu kısmı için daha önce belirttiklerim dışında bir sınıf yaratmama gerek kalmamıştır. Rekürsif ayrıştırıcının gerçeklendiği metod dahilinde, her ayrıştırma işlemi sırasında değişkenlerin değerlerini belirtilen kurallara göre değiştirmem yeterli olmuştur. Ayrıştırıcının bu kısmının genel yapısı özet olarak aşağıdaki gibidir;

int rekursifAyristir(int &girisSayi, Yigin & yeniYigin, Tarayici & yeniTarayici, Gramer & yeniGramer)

{ int sonuc=-1; Sembol yiginSonCek=yeniYigin.cek(); Sozcuk giris=yeniTarayici.sozcukListe[girisSayi]; string karsGiris; string karsYigin=yiginSonCek.isim;

if( (strcmp( giris.tur , "id" )==0) || (strcmp( giris.tur , "num" )==0) )

karsGiris=string(giris.tur); else

karsGiris=string(giris.icerik);

if(karsYigin=="$" && karsGiris=="$") {

(10)

system("pause"); exit(0);

}

if(karsYigin=="$" && girisSayi!=yeniTarayici.sozcukSayi) {

cout << "\nHATA: Islem basarisiz!\n\n\n\n" << endl; system("pause");

exit(-1); }

if(yiginSonCek.terminal==true && karsYigin==karsGiris) { girisSayi++; //rekursifAyristir(girisSayi,yeniYigin,yeniTarayici,yeniGramer); } else {

Hucre *temp=new Hucre(); try{

temp=yeniGramer.tablodanCek(yiginSonCek,karsGiris); }catch(string hata)

{

cout << "\nHATA: Islem basarisiz!\nBeklenmeyen karakter : \"" << karsGiris<< "\"\n\n\n" << endl;

system("pause"); exit(-1);

}

yeniYigin.ekle(temp->sonuc,temp->sonucSayi); //ANLAMSAL ĠġLEMLERĠN OLDUĞU KISIM

//Çok yer kapladığından

//buraya aktarılmamıĢtır, derleyici.cpp dosyasından //tamamı incelenebilir

} }

}

Kodu açıklamam gerekirse şu aşamalardan oluşmaktadır;  Yığından bir sembol çek

 Sözcük listesinden bir sözcük al  Sözcük tipini belirle

 Yığından çekilen sembol = $ ve sözcük =$ ise işlemi sonlandır (başarılı)  Yığından çekilen sembol = $ ve sözcükler bitmediyse işlemi sonlandır (başarısız)  Yığından çekilen sembol bir terminalse ve sözcükle aynıysa bir sonraki sözcüğe geç  Yığından son çekilen sembol nonterminalse tablodan karşılığını al ve bunu tabloya ekle  Tablodan alınan bu gramer kuralının gerektirdiği anlamsal işlemi yerine getir

Yukarıda görüldüğü gibi anlamsal işlemler yığından çekilen sembolün tablodan alınan bilgiye göre başka bir sembol/sembollere dönüşmesi esnasından gerçekleşmektedir. Sözel olarak verilen bu anlamsal işlemlerden birini ilgili kod üzerinden anlatacağım;

(11)

Gramer kuralı: exp → set id = exp

Yapılacak anlamsal işlem: değişkenin değerini exp sonucuna değiştir Kod: if(yiginSonCek.isim=="exp" ) { if(temp->sonuc->isim=="set") { rekursifAyristir(girisSayi,yeniYigin,yeniTarayici,yeniGramer); int *temp; temp=&(yeniTarayici.degiskenTablo.degiskenBul(yeniTarayici.sozc ukListe[girisSayi].icerik).deger); rekursifAyristir(girisSayi,yeniYigin,yeniTarayici,yeniGramer); rekursifAyristir(girisSayi,yeniYigin,yeniTarayici,yeniGramer); if(yeniTarayici.islemIzin==true) { temp=rekursifAyristir(girisSayi,yeniYigin,yeniTarayici,yeniGram er); return *temp; }else { rekursifAyristir(girisSayi,yeniYigin,yeniTarayici,yeniGramer); return -1; } } }

Burada exp sembolünden set sembolüne geçiş yapılmışsa yapılması gereken işlemi görmektesiniz. Öncelikli olarak set kısmının işlenmesi için fonksiyon rekürsif olarak tekrar çağırılır. Daha sonra hangi değişkenin değeri değiştirilecekse o değişkenin değerini tutan int tipindeki değişkenin işaretçisi alınır. İd = kısımları da rekürsif fonksiyon sayesinde işlendikten sonra, exp kısmı işlemeye gönderilir ve değeri temp işaretçisine atanır.

Burada dikkat edilmesi gereken işlem izni olup olmadığıdır. Diyelimki yukarıda ki kod aşağıdaki şekilde yazılmış olsun

İfzero (2-2) then set x = 12 else set y = 13

Bu kodda y değişkeninin üzerinde işlem yapan son kısmın ayrıştırıcı tarafından ayrıştırılması

gerekmektedir. Fakat koşul sağlanmadığından y değişkeninin değerinin değiştirilmemesi lazım. Bunu engellemek için “ifzero exp then exp else exp” kalıbı ayrıştırılırken koşula göre ilk ya da ikinci kısmı ayrıştırmadan önce işlem izni kapatılır daha sonra tekrar açılır.

(12)

Çalışan Örnekler:

{ var a b c; set b = a + 23; set a = b + 1 } Sonuç : 24 { var a b; set a = 4+((4+2)-3) ; ifzero a-12 then set a = b + 7 else set b = 4 - a ; set b = a + 1 ; (set b = b + 10) + { var b c ; set b = a + ( 2 + b) ;

set c = ifzero b then 8 else b; b + c } } Sonuç : 36 Çalışmayan Örnekler: { var a b c; set b = a + 23; set a = b + 1 set

Sonuç: HATA: Islem basarisiz! Beklenmeyen karakter : "set"

{ var a ;

set b = a + 23; set a = b + 1 }

Sonuç: HATA: "b" isimli degisken bulunamadi, daha once tanimlamamis olabilirsiniz

{ var a ?;

set b = a + 23; set a = b + 1 }

Sonuç: Tarayici bir hata buldu! Bilinmeyen karakter: ?

Referensi

Dokumen terkait

2) Bu tören aynicem gibi fazla ayrıtılı değildir. Daha çok basit bir kut­ samadan oluşur... Bu derviş derecesiyle bazan birarada giden, fakat dördüncü bir derece

Goodman bir başka yazıda &#34;maymunun yapıtı rastgele yazmış oluşu bir şeyi değiştirmeyecektir. Metnin aynıdır, bu nedenle özgün metne ilişkin yorumlar bu kopyaya

TDM, zaman bölmeli çoklama denilen ve sayısal olan bir yöntemdir.Bir sayısal sinyal düşünelim, bu sinyalin bir hızı vardır ve bu hız varsayalım 64kb/sn ( bir telefon

Daha kısa bir şekilde açıklamak gerekirse bu kab­ losuz verici, tüm enerji ile karşılaştırıldığında Hertz dalgası ışıması tamamen önemsiz bir miktardır

Jung tarafından psişik fonksiyona tatbik edildiği şekilde , prensip şunu ifade eder; eğer özel bir değer zayıflar veya gözden kaybolursa, değerle belirtilen

çok keskin bir kokusu vardır. Yıldırımlı havalarda, atmosferin yere yakın kısımlarında az miktarda ozon meydana gelir. Yere yakın hava katmanlarında ozon, yok

Kont Sforza'nın ayrıca Dictateurs et dictatures de l'apres - guerre ./ Savaş sonrası diktatörleri ve diktatörlükleri adlı başka bir yapıtı daha vardır

Halbuki biz ya kendi kendimizde ya da zorunlu olarak var olan başka bir varlıkta varız; çünkü (aksiyom 1) var olan her şey ya kendi başına ya da bir başkasıyla vardır ve