Söz dizimi ile çalışma

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.
  • Kaynak kodu doğrudan metin düzenlemelerini kullanmak zorunda kalmadan doğal bir şekilde oluşturmak, değiştirmek ve yeniden düzenlemek için yeniden düzenlemeler ve IDE gibi araçları etkinleştirmek için. Ağaçlar oluşturup işleyerek araçlar kolayca kaynak kodu oluşturabilir ve yeniden düzenleyebilir.

Söz dizimi ağaçları

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.

Not

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 tam uygunlukta 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, alt ağacın metin gösterimini bu düğümde kök olarak almak 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.
  • Sabit ve iş parçacığı açısından güvenlidirler. 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ı, terminal dışı yapısal öğelerin diğer öğelerin üst öğesi olduğu bir ağaç veri yapısıdı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, öğesinden Microsoft.CodeAnalysis.SyntaxNodetü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 özelliği aracılığıyla SyntaxNode.Parent erişilebilen bir üst düğümü vardır. Düğümler ve ağaçlar sabit olduğundan, bir düğümün üst öğesi 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 ayrıca alt ağaçta bulunan ve bu düğüm tarafından köklenen tüm düğümlerin, belirteçlerin veya trivia değerlerinin listesini temsil eden , DescendantTokensDescendantTrivia veya gibi DescendantNodesAlt Öğeleri inceleme yöntemleri de vardır.

Ayrıca, her söz dizimi düğümü alt sınıfı, kesin olarak yazılan özellikler aracılığıyla tüm aynı 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. ve Right türüLeft, ExpressionSyntaxtürü ise OperatorToken şeklindedirSyntaxToken.

Bazı söz dizimi düğümlerinin isteğe bağlı alt öğeleri vardır. Örneğin, isteğe IfStatementSyntax bağlı ElseClauseSyntaxbir vardır. Alt öğe yoksa, özelliği null döndürür.

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 ana ailesi olmaz. 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çermese de özelliği ValueText içermez. Bunun yerine, kaçış tarafından tanımlanan Unicode karakterlerini içerir. Örneğin, kaynak metin olarak \u03C0ValueText yazılmış bir tanımlayıcı içeriyorsa, bu belirtecin özelliği döndürürπ.

Söz dizimi trivia

Söz dizimi trivia kodun normal anlaşılması için büyük ölçüde önemsiz olan kaynak metnin boşluk, açıklamalar ve önişlemci yönergeleri gibi bölümlerini temsil eder. 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 koleksiyonların inceleyerek trivia'ya SyntaxToken.TrailingTrivia erişebilirsiniz. Kaynak metin ayrıştırıldığında, trivia dizileri belirteçlerle ilişkilendirilir. Genel olarak, bir belirteç sonraki belirtecin aynı satırından sonra gelen 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 ilk trivia değerini alır ve dosyadaki son trivia dizisi, sıfır genişliğe sahip olan dosya sonu belirtecine eklenir.

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

Yayılan

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 yayılma alanı, baştaki veya sondaki herhangi bir trivia 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. karakterlerini throw new Exception("Not right.");içerir. Tam aralık, çift dikey çubukla (||) gösterilir. Span ile aynı karakterleri ve baştaki ve sondaki üçlemeyle ilişkili karakterleri içerir.

Her türlü

Her düğüm, belirteç veya trivia, tam olarak temsil edilen söz dizimi öğesini tanımlayan türünde System.Int32bir SyntaxNode.RawKind ö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 Microsoft.CodeAnalysis.VisualBasic.SyntaxKindtrivia öğelerini listeleyen tek SyntaxKind bir numaralandırması (Microsoft.CodeAnalysis.CSharp.SyntaxKind ve sırasıyla) vardır. Bu dönüştürme, veya VisualBasicExtensions.Kind uzantı yöntemlerine CSharpExtensions.Kind erişilerek otomatik olarak yapılabilir.

özelliği, RawKind aynı düğüm sınıfını paylaşan söz dizimi düğüm türlerinin kolayca kesinleştirmesini 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 BinaryExpressionSyntax bir sınıfta , OperatorTokenve Right alt öğe olarak bulunurLeft. Kind özelliği, bir , SubtractExpressionveya MultiplyExpression söz dizimi düğümü türünü ayırt ederAddExpression.

İpucu

(C#için) veya IsKind (VB için) uzantı yöntemlerini kullanarak IsKind türleri 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.