2012-03-07 12 views
5

Öğrenme deneyimi için sıfırdan bir C# yorumlayıcısı yazıyorum ve şimdiye kadar her şey sorunsuz geçti. Tamamen işlevsel bir C# lexer'ım var, her türlü jetonu ayrıştırıcıya gönderir. Jetonları nasıl ayrıştıracağımı biliyorum ama AST'yi (soyut sözdizimi ağacı) nasıl yapılandırmam gerektiğinden emin değilim.Bir Özet Sözdizimi Ağacının parçaları nasıl tasarlanır?

Örneğin, basit bir kod parçası varsa:

using System.Xml; 

ağaç ayrıştırılan zaman nasıl bir şey olurdu?

Bunu beğendiniz mi?

UsingDirective 
    Identifier(System) 
     Identifier(Xml) 

veya benzeri mi?

UsingDirective 
    Identifier(System) 
    Identifier(Xml) 

ben/else/else ifadeleri, bir açıklamada kombine değişken ifadesi/atama (int i eğer ben onlardan noktalarla tanımlayıcıları gibi şeyler yapısı nasıl bazı öneri ve/veya örnekleri alabilirsem = 0;), yardımcı olacak fonksiyon tanımları vb. Ağacın nasıl yapılacağına dair daha iyi bir fikre ihtiyacım var ve gerisini kendim çözebilirim. Teşekkürler.

+0

Bu uzun bir öğrenme deneyimi olacak, eğer tüm C# :-) uygulamak istiyorsanız – svick

+0

Eh, sınıf kütüphanesinin çoğunluğunu bırakıyorum. Temel olarak sadece temel sınıf/fonksiyon tanımları, değişken oluşturma/kullanım ve işlev çağrıları için neyin uygulanması gerektiğini uyguluyorum. –

cevap

2

Geçmişte ayrıştırıcıları birkaç yazdım, ben genelde böyle bir şey için giderdim: ben tercih

UsingDirective 
    IdentifierList 
    Identifier (LeftNode) (System) 
    Identifier (RightNode) (Xml) 

Roslyn aksine bu using System.Collections.Generic

UsingDirective 
    IdentifierList 
     IdentifierList (LeftNode) 
      Identifier (LeftNode) (System) 
      Identifier (RightNode) (Collections) 
     Identifier (RightNode) (Generic) 

durumunda AST'leri ışık tutmak, derleyicinin bunlara gerek duymamasından dolayı, yarı-kolon, using anahtar kelime gibi simgeleri dahil etmeyerek.

IDE'ler için özel olarak yazdığım ayrıştırıcılar farklı görünüyorlar - bu ekstra şeyleri satır ve sütun numaraları gibi daha fazla bilgi ile birlikte taşırlar.

+0

Neden "IdentifierList" inizin sadece iki çocuğu var? Neden tek bir 'IdentifierList '' kadar çok sayıda çocuğa ihtiyaç duyulmuyor? – svick

+0

Evet, sınırsız çocuklar için tek bir IdentifierList daha iyi olurdu. Her durumda, cevabınız için teşekkürler xbonez. –

+0

Bunun da işe yarayacağına eminim. Şahsen, bu şekilde (özyinelemeli olarak), sadece bir hakaret listesi olmasından daha kolay geçmeyi daha kolay buluyorum. 'TraverIdentList': 'if (identlist.leftnode identlistnode) {traverseIdentList (leftnode) işlevi; } else {traverseident (leftnode); traverseident (rightnode); – xbonez

2

Microsoft'un bunu Roslyn ile nasıl yaptığına bakabilirsiniz. Orada C# (ve VB.NET) için sözdizimi ağaçları nasıl bildirdiler ve belki bunları yazmadan önce tercümanınızın bölümleri yerine kullanabilirsiniz.

Özellikle, using yönergesi için Roslyn sözdizimi ağacı gibidir: İkinci sürümüne benzer, fakat daha detaylı Yani

UsingDirective 
    UsingKeyword 
    QualifiedName 
     IdentifierName (System) 
     DotToken 
     IdentifierName (Xml) 
    SemicolonToken 

.

Bence ilk versiyonunuz çok anlamlı değil. Xml, sözdizimsel düzeydeki System numaralı bir çocuk değildir (daha sonra semantik düzeyde bir “üst isim alanı” kavramına sahip olsanız bile).

+0

Ama bu soyut bir sözdizimi ağacı değil, nokta ve noktalı virgül gibi kaynak kodunun bölümlerini içerdiğinden, somut bir sözdizimi ağacıdır. –

+0

Evet, haklısın. Ama sanırım AST'nizi buna dayanabilirsin. – svick

+0

Evet, cevabınız için teşekkürler! Bu yardımcı oldu. –