July 16, 2012

Alıntı (Salih Dinçer):

>

Bence DustMite yerine Aziz Köksal'ın dil projesine bakmalıyız:)

İncelemekte fayda var tabi, ama o kodların içinden aradığımızı bulmakta ayrı bir konu :)

Neyse ben dsplit üzerinde parseToWords() isimli bir metot buldum. Sanırım bu metot bizim işimizi görecek diye düşünüyorum. Ben algoritmayı anlamak ve kendi projeme entegre etmek için kodu aşagıdaki gibi yeniden düzenledim. Aslında orjinalinin aynı sadece değişken isimleri değişti.

import std.stdio;
import std.ascii;

void main()
{
	string birMetot = "bool isAlphaNum(dchar c) @safe pure nothrow";

	string[] atomListesi = MetniAtomlaraAyir(birMetot);

	writefln("Atom Listesi : %s", atomListesi);
}

bool BaslangicKarakteriMi(char c)
{
	return isAlphaNum(c) || c=='_' || c=='@';
}

string[] MetniAtomlaraAyir(string metin)
{
	string[] sonuc;
	uint i, karakterBasi, karakterSonu;

	for (i = 1; i <= metin.length; ++i)
	{
		if (i == metin.length || (!BaslangicKarakteriMi(metin[i-1]) && BaslangicKarakteriMi(metin[i])))
		{
			if (karakterBasi != i)
			{
				sonuc ~= metin[karakterBasi..karakterSonu];
			}

			karakterBasi = karakterSonu = i;

		}
		else if ((BaslangicKarakteriMi(metin[i-1]) && !BaslangicKarakteriMi(metin[i])))
		{
			karakterSonu = i;
		}
	}

	return sonuc;
}

Alıntı:

>

E:\Proje - D\Phobos> .\main.exe
Atom Listesi : ["bool", "isAlphaNum", "dchar", "c", "@safe", "pure", ""]

Buradaki sorun çıktıya dikkat ederseniz örnek metnimizin sonunda bulunan nothrow anahtar kelimesinin olmaması, orjinal kod biraz daha farklı çalıştığı için böyle bir sorun olup olmadığını bilmiyorum. Ancak büyük ihtimal ben kodu değiştirince bu sorun oluştu.

Diğer sıkıntı ise metindeki () parantezleride ayraç olarak algılayıp parametre listesinide parçalaması, şimdilik bunu istemiyoruz. Neyse neticede sanırım bu kod üzerinden ilerleyebiliriz.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 16, 2012

Evet, bu üzerinden kalkabileceğimiz basitlikte bir işlev. Sanırım biz bu işi yapacağız...:)

Ancak yine de ileride tıkanmamak için dil/src/dil/parser/ImportParser dosyasına ısrarcıyım. Olayı case'ler ile halletmiş ama lexer dizin içindeki her yapıya göre ayrı tasarlanmış sınıflar ile birlikte çalışıyor. Yani sandığımdan kapsamlıymış bu iş! Örneğin sadece olayın başladığı kısımın kodu şöyle:

 void parseDeclarationDefinition(Protection prot)
 {
   switch (token.kind)
   {
   case T.Align:
     nT();
     if (token.kind == T.LParen)
       nT(), nT(), nT(); // ( Integer )
     parseDeclarationsBlock(prot);
     break;
   case T.Pragma:
     nT();
     skipToTokenAfterClosingParen();
     parseDeclarationsBlock(prot);
     break;
   case T.Export,
        T.Private,
        T.Package,
        T.Protected,
        T.Public:
     parseProtectionAttribute();
     break;
   // Storage classes
   case T.Extern:
     nT();
     token.kind == T.LParen && skipToTokenAfterClosingParen();
     parseDeclarationsBlock(prot);
     break;
   case T.Const:
   version(D2)
   {
     if (peekNext() == T.LParen)
       goto case_Declaration;
   }
   case T.Override,
        T.Deprecated,
        T.Abstract,
        T.Synchronized,
        // T.Static,
        T.Final,
        T.Auto,
        T.Scope:
   case_StaticAttribute:
   case_InvariantAttribute:
     nT();
     parseDeclarationsBlock(prot);
     break;
   // End of storage classes.
   case T.Alias, T.Typedef:
     nT();
     goto case_Declaration;
   case T.Static:
     switch (peekNext())
     {
     case T.Import:
       goto case_Import;
     case T.This:
       nT(), nT(); // static this
       skipToTokenAfterClosingParen();
       parseFunctionBody();
       break;
     case T.Tilde:
       nT(), nT(), nT(), nT(), nT(); // static ~ this ( )
       parseFunctionBody();
       break;
     case T.If:
       nT(), nT();
       skipToTokenAfterClosingParen();
       parseDeclarationsBlock(prot);
       if (token.kind == T.Else)
         nT(), parseDeclarationsBlock(prot);
       break;
     case T.Assert:
       nT(), nT(); // static assert
       skipToTokenAfterClosingParen();
       skip(T.Semicolon);
       break;
     default:
       goto case_StaticAttribute;
     }
     break;
   case T.Import:
   case_Import:
     auto decl = parseImportDecl();
     decl.setProtection(prot); // Set the protection attribute.
     imports ~= decl.to!(ImportDecl);
     break;
   case T.Enum:
     nT();
     token.kind == T.Identifier && nT();
     if (token.kind == T.Colon)
     {
       nT();
       while (token.kind != T.LBrace && token.kind != T.EOF)
         nT();
     }
     if (token.kind == T.Semicolon)
       nT();
     else
       skipToTokenAfterClosingBrace();
     break;
   case T.Class:
   case T.Interface:
     nT(), skip(T.Identifier); // class Identifier
     token.kind == T.LParen && skipToTokenAfterClosingParen(); // Skip template params.
     if (token.kind == T.Colon)
     { // BaseClasses
       nT();
       while (token.kind != T.LBrace && token.kind != T.EOF)
         if (token.kind == T.LParen) // Skip ( tokens... )
           skipToTokenAfterClosingParen();
         else
           nT();
     }
     if (token.kind == T.Semicolon)
       nT();
     else
       parseDeclarationDefinitionsBlock(Protection.None);
     break;
   case T.Struct, T.Union:
     nT(); skip(T.Identifier);
     token.kind == T.LParen && skipToTokenAfterClosingParen();
     if (token.kind == T.Semicolon)
       nT();
     else
       parseDeclarationDefinitionsBlock(Protection.None);
     break;
   case T.Tilde:
     nT(); // ~
   case T.This:
     nT(); nT(); nT(); // this ( )
     parseFunctionBody();
     break;
   case T.Invariant:
   version(D2)
   {
     auto next = token;
     if (peekAfter(next) == T.LParen)
     {
       if (peekAfter(next) != T.RParen)
         goto case_Declaration;
     }
     else
       goto case_InvariantAttribute;
   }
     nT();
     token.kind == T.LParen && skipToTokenAfterClosingParen();
     parseFunctionBody();
     break;
   case T.Unittest:
     nT();
     parseFunctionBody();
     break;
   case T.Debug:
     nT();
     if (token.kind == T.Equal)
     {
       nT(), nT(), nT(); // = Condition ;
       break;
     }
     if (token.kind == T.LParen)
       nT(), nT(), nT(); // ( Condition )
     parseDeclarationsBlock(prot);
     if (token.kind == T.Else)
       nT(), parseDeclarationsBlock(prot);
     break;
   case T.Version:
     nT();
     if (token.kind == T.Equal)
     {
       nT(), nT(), nT(); // = Condition ;
       break;
     }
     nT(), nT(), nT(); // ( Condition )
     parseDeclarationsBlock(prot);
     if (token.kind == T.Else)
       nT(), parseDeclarationsBlock(prot);
     break;
   case T.Template:
     nT();
     skip(T.Identifier);
     skipToTokenAfterClosingParen();
     parseDeclarationDefinitionsBlock(Protection.None);
     break;
   case T.New:
     nT();
     skipToTokenAfterClosingParen();
     parseFunctionBody();
     break;
   case T.Delete:
     nT();
     skipToTokenAfterClosingParen();
     parseFunctionBody();
     break;
   case T.Mixin:
     while (token.kind != T.Semicolon && token.kind != T.EOF)
       if (token.kind == T.LParen)
         skipToTokenAfterClosingParen();
       else
         nT();
     skip(T.Semicolon);
     break;
   case T.Semicolon:
     nT();
     break;
   // Declaration
   case T.Identifier, T.Dot, T.Typeof:
   case_Declaration:
     while (token.kind != T.Semicolon && token.kind != T.EOF)
       if (token.kind == T.LParen)
         skipToTokenAfterClosingParen();
       else if (token.kind == T.LBrace)
         skipToTokenAfterClosingBrace();
       else
         nT();
     skip(T.Semicolon);
     break;
   default:
     if (token.isIntegralType)
       goto case_Declaration;
     nT();
   }
 }

 FuncBodyStmt parseFunctionBody()
 {
   while (1)
   {
     switch (token.kind)
     {
     case T.LBrace:
       skipToTokenAfterClosingBrace();
       break;
     case T.Semicolon:
       nT();
       break;
     case T.In:
       nT();
       skipToTokenAfterClosingBrace();
       continue;
     case T.Out:
       nT();
       if (token.kind == T.LParen)
         nT(), nT(), nT(); // ( Identifier )
       skipToTokenAfterClosingBrace();
       continue;
     case T.Body:
       nT();
       goto case T.LBrace;
     default:
     }
     break; // Exit loop.
   }
   return null;
 }
}

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 16, 2012

Evet, asıl sıfır noktasını buldum. Lexer dizini içinde Lexer.d ismindeki dosya. Ancak daha fazla kod ile burayı karıştırmayıp 'scan()' işlevini adresini vereyim: http://goo.gl/mkfVW

Bu tür kodları görünce insana şevk geliyor. Bizim daha geniş projeler yapmamız lazım. Burada kullanılan D olanakları bir harika...:)

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 16, 2012

Alıntı (Salih Dinçer):

>

Evet, bu üzerinden kalkabileceğimiz basitlikte bir işlev. Sanırım biz bu işi yapacağız...:)

Elbette yapacağız Salih, bu konuyu ilk açtığımda elindekinin ne olduğunun bile bilmiyordum. Hatta o kadar ki goole'da arama kriteri olarak ne yazacağımı bile bilemedim. Ama yapabileceğimizi her zaman biliyordum :) Bu arada sitede güzel kod yazan ve kendini geliştiren arkadaşlar var. Ben inanıyorum ki bir gün ddili.org imzası ile phobos kütüphanesinde çalışan kodları yazan arkadaşlarda olacak.

Alıntı (Salih Dinçer):

>

Bu tür kodları görünce insana şevk geliyor. Bizim daha geniş projeler yapmamız lazım. Burada kullanılan D olanakları bir harika...:)

Sana kesinlikle katılıyorum. Dili öğrenme sürecinde bir takım komutların etrafında dönüp dursakta bu daireden çıkıp yol almak istiyorsak ya daha ileri düzey gereksinimleri olan programlar geliştirmeli ya da böyle bir imkan yoksa en azından bu tür program kodlarını incelemeli ve anlamaya çalışmalıyız diye düşünüyorum. Kod geliştirmek bir proje içinde yer almak insana çok farklı tecrübeler kazandırıyor.

Konuya dönersek, bu işlem projemin kalbini oluşturduğu için hiç acele etmeden tüm alternatifleri değerlendirip en iyisini uygulamak istiyorum. dil projesinin kodları dediğin gibi daha detaylı işlemler yapıyor. Aziz Köksal işaretçileri bol bol kullanmış, ben bu konuda çok iyi olmadığım için işaretçileri takip etmem zor oluyor. Eğer sende benim gibi bizim ilgilendigimiz kısmı ana kodlardan ayırıp küçük bir uygulama yaparsan karşılaştırma imkanımız daha kolay olur.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 16, 2012

Alıntı (zafer):

>

Eğer sende benim gibi bizim ilgilendigimiz kısmı ana kodlardan ayırıp küçük bir uygulama yaparsan karşılaştırma imkanımız daha kolay olur.
Bu kod parçaları kapsamlı bir derleyiciye ait olduğu için ayırma işlemi yazmak çok vakit alabilir. Onun yerine bu kodlar model teşkil edebilir. Özellikle işlev gövdesi (parseFunctionBody) ne kadar hoş değil mi? Ancak kapsamlı çünkü ileride kısıtlama olmayacak şekilde geniş geniş imkanlar ile yazılmış.

Senin projeni ve amacını bilmiyorum (paylaşırsan sevinirim) ama eğer benzer büyüklükte ise adım adım düşünmeli. Yoksa yukarıda denediğin o küçük işlev an gelir yetersiz kalır. Neyse ki tam da istediğin gibi bir model var elimizde. Hatta hiç isimleri (LBrace, Semicolon, DeclarationsBlock, ClosingBrace vb.) değiştirmeyip olduğu gibi kullanırsak zaman kazanırız. Örneğin bunları hemen bir enum ile belirleyebiliriz...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 16, 2012

Bana hafiften lexer yazacağız gibi geliyor, hadi hayırlısı. :)
Aslında bu proje için düşünürsek işimiz çok da zor olmayacak, zira bütün ayrıntıları almak yerine belirli bilgiler istiyoruz ve kesin kurallarımız var: Açma ve kapama parantezlerinin arasına parametreler gelir, parametrelerden önce işlev ismi gelir vs...
Tam anlamıyla bu durumu mu karşılıyor, bilemiyorum ama burada bir çift bağlı liste yapısı kullanabiliriz. Token'lara ayırdıktan sonra önceki token ve sonraki token'ın ne olduğunu bağlı olarak elde ettiğimiz verinin hangisi olduğuna(İşlev ismi, parametre, pure, nothrow, @property gibi özellikler, sarma derecesi...) karar verebiliriz.
Benim fikrim bu yönde, siz ne dersiniz?

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 16, 2012

Mantıklı, olay duality ile özetlenmiştir.

Arada kalanlar (separate) ekrana yazılır.

Belki de çok zor değildir ha...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 16, 2012

AST sanırım alınan kaynak kodun makine koduna çevrilmeden önce aldığı son haldi, yani derleyiciye kadar gitmeyeceksek AST oluşturmamıza gerek kalmaz gibi geliyor, yanlış mı düşünüyorum?

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 16, 2012

Son zamanlarda sıklıkla basit güzeldir diyorum ya, bunu mühendislikteki basit olanın daha az sorun çıkaracağına gönderme yaparak söylüyorum. Ancak lexer gibi bir şeyde dilin zenginliğine bağlı olarak tanımlamamız gereken çok şey var. Yani yaptığımız basit separate ile split işlemi değil ki? Kanun gibi belli kurallar gözetmeliyiz. Hatta belki programcı hatası (cinliği de olabilir!) durumları da gözetilmeli...:)

Neyse ki köşeli parantezi işlev başlangıcında ve sonunda mutlaka kullanmaktayız; ondan bir kaçış yok. Ancak fark edeceğiniz üzere bu iş basit bir şey değil. Bilmiyorum Zafer istediği bu ayıklamayı nerede kullanacak? Yani hedeflenen iş yüküne değer mi? Alternatifimiz var mı?

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 17, 2012

Sanırım öncelikle projeyi açıklarsam her şey daha net bir hale gelecek. Projemin adı 'Phobos Explorer', çıkış noktası ise Visual Studio ile severek kullandığım Object Browser (http://www.sapphiresteel.com/IMG/gif/amethyst-object-browser.gif) benzeri bir araç geliştirmek.

Phobos Explorer'ın temel amacı Phobos kütüphanesinin modülleri içindeki yapıları bir liste halinde sunarak kullanıcının bunlar üzerinde kolayca dolaşabilmesini sağlamak. Ayrıca görüyorum ki proje bir yan etki olarak lexer, belkide bir parser yazma sürecini tetiklediki bence bu projenin kendinden bile çok daha güzel bir olay.

Alıntı (Kadir Can):

>

Aslında bu proje için düşünürsek işimiz çok da zor olmayacak, zira bütün ayrıntıları almak yerine belirli bilgiler istiyoruz

Haklısın Kadir, temelde sadece yapıların başlık kısımlarını istiyoruz. Ayrıca bazı istisnalar dışında bunların ne olduğunu bilmemizde gerekmiyor. Sadece bir listeye eklemek yeterli. Projeyi anlattıgıma göre sanırım fikirler biraz daha somutlaşır diye düşünüyorum. Sizlerde fikirlerinizi paylaşın.

Alıntı (Salih Dinçer):

>

Bu kod parçaları kapsamlı bir derleyiciye ait olduğu için ayırma işlemi yazmak çok vakit alabilir.

Salih, haklısın ama eğer bu süreci işletmezsek iş bir noktadan sonra kopyala yapıştır olayına döner ki sanırım bunu hiçbirimiz istemeyiz. Benim amacım en basit kelimesine kadar ne amaçla oraya konduğunu bildiğim bir proje geliştirmek neticede ticari bir kaygımız olmadğına göre zaman sıkıntısı yaşayacağımızıda düşünmüyorum ;)

Kafamızdaki resmin netleşmesi için ayıklama motorunun çalışma kurallarını içeren bir mesaj hazırlamam sanırım hepimiz için iyi olacak.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]