Söz dizimiyle çalışmak

Söz dizimi ağacı, derleyici API'leri tarafından kullanıma sunulan temel bir sabit veri yapısıdır. Bu ağaçlar kaynak kodun sözcük temelli ve söz dizimsel yapısını temsil eden. İki önemli amaca hizmet ederler:

  • Bir kullanıcının projesinde kaynak kodun söz dizimsel yapısını görmek ve işlemek için IDE, eklentiler, kod çözümleme araçları ve yeniden düzenlemeler gibi araçlara izin vermek için.
  • Yeniden düzenleme ve IDE gibi araçları, metinleri doğrudan düzenlemeye gerek kalmadan kaynak kodunu doğal bir şekilde oluşturmak, değiştirmek ve yeniden düzenlemek için etkinleştirmek. Ağaçlar oluşturup işleyerek araçlar kolayca kaynak kodu oluşturabilir ve yeniden düzenleyebilir.

Sözdizim ağacı

Söz dizimi ağaçları derleme, kod analizi, bağlama, yeniden düzenleme, IDE özellikleri ve kod oluşturma için kullanılan birincil yapıdır. Kaynak kodun hiçbir bölümü, önce tanımlanmadan ve iyi bilinen birçok yapısal dil öğesinden birinde kategorilere ayrılmadan anlaşılamaz.

Uyarı

RoslynQuoter , bir programın söz dizimi ağacını oluşturmak için kullanılan söz dizimi fabrika API'si çağrılarını gösteren açık kaynak bir araçtır. Canlı olarak denemek için bkz http://roslynquoter.azurewebsites.net. .

Söz dizimi ağaçlarının üç temel özniteliği vardır:

  • Tüm kaynak bilgileri eksiksiz olarak tutar. Tam uygunluk, söz dizimi ağacının kaynak metinde bulunan her bilgi parçasını, her dil bilgisi yapısını, her sözcük belirtecini ve boşluk, açıklamalar ve önişlemci yönergeleri dahil olmak üzere aradaki diğer her şeyi içerdiği anlamına gelir. Örneğin, kaynakta bahsedilen her değişmez değer tam olarak yazıldığı gibi gösterilir. Söz dizimi ağaçları, atlanan veya eksik belirteçleri temsil ederek program eksik veya hatalı biçimlendirilmiş olduğunda da kaynak kodundaki hataları yakalar.
  • Ayrıştırıldıkları metni tam olarak üretebilirler. Herhangi bir söz dizimi düğümünden, kökü bu düğümde olan alt ağacın metin gösterimini elde etmek mümkündür. Bu özellik, söz dizimi ağaçlarının kaynak metni oluşturmanın ve düzenlemenin bir yolu olarak kullanılabileceğini gösterir. Bir ağacı oluşturarak, bunun sonucunda eşdeğer metni oluşturdunuz ve var olan bir ağaçta yapılan değişikliklerden yeni bir ağaç oluşturarak metni etkili bir şekilde düzenlemişsinizdir.
  • Onlar değişmez ve iş parçacığı açısından güvenlidir. Bir ağaç elde edildikten sonra kodun geçerli durumunun anlık görüntüsü olur ve hiçbir zaman değişmez. Bu, birden çok kullanıcının kilitleme veya yineleme olmadan farklı iş parçacıklarında aynı söz dizimi ağacıyla aynı anda etkileşim kurmasına olanak tanır. Ağaçlar sabit olduğundan ve doğrudan bir ağaçta değişiklik yapılamadığı için, fabrika yöntemleri ağacın ek anlık görüntülerini oluşturarak söz dizimi ağaçlarının oluşturulmasına ve değiştirilmesine yardımcı olur. Ağaçlar, temel düğümleri yeniden kullanmaları açısından verimlidir, bu nedenle yeni bir sürüm hızlı ve çok az bellekle yeniden oluşturulabilir.

Söz dizimi ağacı, tam anlamıyla bir ağaç veri yapısıdır; burada terminal olmayan yapısal öğeler, diğer öğelerin üst öğesi konumundadır. Her söz dizimi ağacı düğümlerden, belirteçlerden ve trivia'lardan oluşur.

Söz dizimi düğümleri

Söz dizimi düğümleri söz dizimi ağaçlarının birincil öğelerinden biridir. Bu düğümler bildirimler, deyimler, yan tümceler ve ifadeler gibi söz dizimsel yapıları temsil eder. Söz dizimi düğümlerinin her kategorisi, Microsoft.CodeAnalysis.SyntaxNode öğesinden türetilen ayrı bir sınıfla temsil edilir. Düğüm sınıfları kümesi genişletilebilir değildir.

Tüm söz dizimi düğümleri söz dizimi ağacında terminal olmayan düğümlerdir; bu da her zaman alt öğe olarak başka düğümlere ve belirteçlere sahip oldukları anlamına gelir. Başka bir düğümün alt öğesi olarak, her düğümün, SyntaxNode.Parent özelliği aracılığıyla erişilebilen bir üst düğümü vardır. Düğümler ve ağaçlar değişmez olduğundan, bir düğümün ebeveyni hiçbir zaman değişmez. Ağacın kökünde null üst öğe var.

Her düğümün, kaynak metindeki konumlarına göre sıralı olarak alt düğümlerin listesini döndüren bir SyntaxNode.ChildNodes() yöntemi vardır. Bu liste belirteç içermiyor. Her düğümün, bu düğüm tarafından köklenen alt ağaçta bulunan tüm düğümlerin, belirteçlerin veya trivia değerlerinin listesini temsil eden DescendantNodes, DescendantTokens veya DescendantTrivia gibi Alt Öğeleri inceleme yöntemleri de vardır.

Ayrıca, her sözdizim düğümü alt sınıfı, güçlü bir şekilde tanımlanmış özellikler aracılığıyla aynı tüm alt öğeleri kullanıma sunar. Örneğin, düğüm BinaryExpressionSyntax sınıfının ikili işleçlere özgü üç ek özelliği vardır: Left, OperatorTokenve Right. Left ve Right türü ExpressionSyntax, ve OperatorToken türü SyntaxToken şeklindedir.

Bazı söz dizimi düğümlerinin isteğe bağlı çocukları vardır. Örneğin, bir IfStatementSyntax isteğe bağlı bir ElseClauseSyntax vardır. Çocuk mevcut değilse, özellik null değer döndürüyor.

Söz dizimi belirteçleri

Söz dizimi belirteçleri, kodun en küçük söz dizimi parçalarını temsil eden dil dil bilgisi terminalleridir. Bunlar hiçbir zaman diğer düğümlerin veya belirteçlerin ebeveyni değildir. Söz dizimi belirteçleri anahtar sözcüklerden, tanımlayıcılardan, değişmez değerlerden ve noktalama işaretlerinden oluşur.

Verimlilik amacıyla, SyntaxToken türü bir CLR değer türüdür. Bu nedenle, söz dizimi düğümlerinden farklı olarak, temsil edilen belirtecin türüne bağlı olarak anlamı olan özelliklerin karışımına sahip her tür belirteç için yalnızca bir yapı vardır.

Örneğin, bir tamsayı sabit belirteci sayısal bir değeri temsil eder. Belirtecin yayıldığı ham kaynak metne ek olarak, değişmez değer belirteci tam kod çözülen tamsayı değerini belirten bir Value özelliğe sahiptir. Bu özellik, birçok ilkel türden biri olabileceğinden olarak Object yazıldı.

ValueText özelliği size özelliğiyle Value aynı bilgileri söyler; ancak bu özellik her zaman olarak Stringyazılır. C# kaynak metnindeki bir tanımlayıcı Unicode kaçış karakterleri içerebilir, ancak kaçış dizisinin söz dizimi tanımlayıcı adının bir parçası olarak kabul edilmez. Bu nedenle belirtecin yaydığı ham metin kaçış dizisini içerse de, ValueText özelliği içermez. Bunun yerine, kaçış tarafından tanımlanan Unicode karakterlerini içerir. Örneğin, kaynak metin \u03C0 olarak yazılmış bir tanımlayıcı içeriyorsa, o zaman bu belirteç için ValueText özelliği π döndürür.

Söz Dizimi Hakkında İlginç Bilgiler

Kodun normal anlaşılırlığı için büyük ölçüde önemsiz olan kaynak metnin, boşluklar, açıklamalar ve ön işleyici yönergeleri gibi bölümlerini temsil eden syntax trivia terimleri. Söz dizimi belirteçleri gibi, trivia da değer türleridir. Tek Microsoft.CodeAnalysis.SyntaxTrivia tür, her türlü triviayı tanımlamak için kullanılır.

Trivia, normal dil söz diziminin bir parçası olmadığından ve iki belirteç arasında herhangi bir yerde görünebildiğinden, söz dizimi ağacına bir düğümün alt öğesi olarak eklenmez. Ancak, yeniden düzenleme gibi bir özelliği uygularken ve kaynak metinle tam uygunluğu korumak için önemli olduklarından söz dizimi ağacının bir parçası olarak var olurlar.

Bir belirtecin SyntaxToken.LeadingTrivia veya SyntaxToken.TrailingTrivia koleksiyonlarını inceleyerek trivia'ya erişebilirsiniz. Kaynak metin ayrıştırıldığında, trivia dizileri belirteçlerle ilişkilendirilir. Genel olarak, bir belirteç, aynı satırda bir sonraki belirtece kadar olan tüm trivia'lara sahip olur. Bu satırdan sonraki tüm önemsiz bilgiler aşağıdaki belirteçle ilişkilendirilir. Kaynak dosyadaki ilk belirteç tüm ön trivia'ları alır ve dosyadaki son trivia dizisi, sıfır genişliğe sahip olan dosya sonu belirtecine iliştirilir.

Söz dizimi düğümleri ve belirteçlerinin aksine, söz dizimi trivia'nın ebeveynleri yoktur. Ancak, bunlar ağacın bir parçası olduğundan ve her biri tek bir belirteçle ilişkilendirildiğinden, ilişkilendirildiği belirtece SyntaxTrivia.Token özelliği kullanılarak erişebilirsiniz.

Aralıklar

Her düğüm, belirteç veya trivia, kaynak metin içindeki konumunu ve içerdiği karakter sayısını bilir. Metin konumu, sıfır tabanlı char bir dizin olan 32 bitlik bir tamsayı olarak temsil edilir. TextSpan Nesne, başlangıç konumu ve her ikisi de tamsayı olarak gösterilen karakter sayısıdır. Uzunluğu sıfırsa TextSpan , iki karakter arasındaki bir konuma başvurur.

Her düğümün iki TextSpan özelliği vardır: Span ve FullSpan.

Span özelliği, düğümün alt ağacındaki ilk belirtecin başından son belirtecin sonuna kadar olan metin aralığıdır. Bu kapsam, başındaki veya sonundaki gereksiz bilgileri içermez.

FullSpan özelliği, düğümün normal aralığını ve baştaki veya sondaki tüm trivia'ların aralığını içeren metin aralığıdır.

Örneğin:

      if (x > 3)
      {
||        // this is bad
          |throw new Exception("Not right.");|  // better exception?||
      }

Bloğun içindeki deyim düğümü, tek dikey çubuklar (|) tarafından gösterilen bir yayılma alanı içerir. Bu throw new Exception("Not right."); karakterlerini içerir. Tam aralık, çift dikey çubukla (||) gösterilir. Span ile aynı karakterleri ve baştaki ve sondaki boşluklarla (trivia) ilişkili karakterleri içerir.

Her türlü

Her düğüm, belirteç veya trivia, temsil edilen tam söz dizimi öğesini tanımlayan SyntaxNode.RawKind türünde bir System.Int32 özelliğe sahiptir. Bu değer dile özgü bir numaralandırmaya atanabilir. C# veya Visual Basic dillerinden her birinin dil bilgisi içindeki tüm olası düğümleri, belirteçleri ve SyntaxKindtrivia öğelerini listeleyen tek Microsoft.CodeAnalysis.CSharp.SyntaxKind bir numaralandırması (Microsoft.CodeAnalysis.VisualBasic.SyntaxKind ve sırasıyla) vardır. Bu dönüştürme, CSharpExtensions.Kind veya VisualBasicExtensions.Kind uzantı yöntemlerine erişilerek otomatik olarak yapılabilir.

Bu RawKind özelliği, aynı düğüm sınıfını paylaşan söz dizimi düğüm türlerinin kolayca ayırt edilmesini sağlar. Belirteçler ve trivia için bu özellik, bir öğe türünü diğerinden ayırt etmenin tek yoludur.

Örneğin, tek bir BinaryExpressionSyntax sınıfı Left, OperatorToken ve Right alt öğeler olarak bulunur. Kind yöntemi, bunun bir AddExpression, SubtractExpressionveya MultiplyExpression tür söz dizimi düğümü olup olmadığını ayırt eder.

Tavsiye

Türleri IsKind (C# için) veya IsKind (VB için) uzantı yöntemlerini kullanarak denetlemenizi öneririz.

Hatalar

Kaynak metin söz dizimi hataları içerse bile, kaynağa gidiş dönüş kullanılabilen tam bir söz dizimi ağacı görüntülenir. Ayrıştırıcı, dilin tanımlı söz dizimine uymayan bir kodla karşılaştığında, söz dizimi ağacı oluşturmak için iki teknikten birini kullanır:

  • Ayrıştırıcı belirli bir belirteç türünü bekliyor ancak bulamıyorsa, belirtecin beklendiği konumdaki söz dizimi ağacına eksik bir belirteç ekleyebilir. Eksik belirteç beklenen gerçek belirteci temsil eder, ancak boş bir yayılma alanı vardır ve SyntaxNode.IsMissing özelliği döndürür true.

  • Ayrıştırıcı, ayrıştırma işlemine devam ettiği bir belirteç bulana kadar belirteçleri atlayabilir. Bu durumda, atlanan belirteçler türüne SkippedTokensTriviasahip bir trivia düğümü olarak eklenir.