LR ayrıştırıcıları tasarım gereği belirsiz dilbilgisi kurallarını kullanamazlar. (Fikirlerin çalışıldığı 1970'lerde teoriyi daha kolay hale getirdi).
C ve C ++ aşağıdaki ifadelere izin verir:
x * y ;
İki farklı ayrımı vardır:
- X türüne işaretçi olarak y'nin bildirimi olabilir.
- Cevabı atmak, x ve y çarpımı olabilir.
Şimdi, ikincisinin aptal olduğunu ve göz ardı edilmesi gerektiğini düşünebilirsiniz. Çoğu sizinle aynı fikirde; ancak, bunun bir yan etkisi olabileceği durumlar vardır (örneğin, çarpma aşırı yüklenmişse). ama mesele bu değil. Nokta var olan iki farklı ayrıştırır ve bu nedenle bir program bu şekline bağlı olarak farklı anlamlara gelebilir gerektiğini çözümlenir edilmiştir.
Derleyici uygun koşullar altında uygun olanı kabul etmelidir ve başka herhangi bir bilginin yokluğunda (örneğin, x türü bilgisi) daha sonra ne yapılacağına karar vermek için her ikisini de toplamalıdır. Dolayısıyla bir dilbilgisi buna izin vermelidir. Bu da dilbilgisini belirsiz kılar.
Bu nedenle saf LR ayrıştırma bunu başaramaz. Antlr, JavaCC, YACC veya geleneksel Bison gibi yaygın olarak bulunan diğer ayrıştırıcı jeneratörler ve hatta "saf" bir şekilde kullanılan PEG tarzı ayrıştırıcılar da olamaz.
Çok daha karmaşık durumlar vardır (şablonun sözdizimi ayrıştırılması keyfi bir önden okuma gerektirirken, LALR (k) çoğu k jetonunu ileriye bakabilir), ancak saf LR (veya diğerleri) ayrıştırmasını vurmak için yalnızca bir karşı örnek alır .
Çoğu gerçek C / C ++ ayrıştırıcısı bu örneği, fazladan bir saldırı ile bir tür deterministik ayrıştırıcı kullanarak işler: sembol tablosu koleksiyonu ile ayrıştırmayı iç içe geçirirler ... böylece "x" ile karşılaşıldığında, ayrıştırıcı x'in bir tür ya da değil ve böylece iki potansiyel çözüm arasında seçim yapabilir. Ancak bunu yapan bir ayrıştırıcı bağlamdan bağımsız değildir ve LR ayrıştırıcıları (saf olanlar, vs.) bağlamdan bağımsızdır.
Bu dezavantajı yapmak için LR ayrıştırıcılarına hile ve kural başına azaltma süresi semantik kontrolleri eklenebilir. (Bu kod genellikle basit değildir). Diğer ayrıştırıcı türlerinin çoğunda, ayrıştırma işleminin çeşitli noktalarına anlamsal denetimler eklemek için bazı araçlar vardır, bunlar bunu yapmak için kullanılabilir.
Yeterince hile yaparsanız, LR ayrıştırıcılarının C ve C ++ için çalışmasını sağlayabilirsiniz. GCC adamları bir süre yaptılar, ancak elle kodlanmış ayrıştırma için vazgeçtiler, bence daha iyi hata teşhisi istediler.
Yine de, güzel ve temiz olan ve C ve C ++ 'ı herhangi bir sembol tablosu korsanlığı olmadan gayet iyi ayrıştıran başka bir yaklaşım var: GLR ayrıştırıcılar . Bunlar tam bağlamsız ayrıştırıcılardır (etkili bir şekilde sonsuz görünüme sahip). GLR ayrıştırıcıları, her iki ayrışmayı da kabul ederek belirsiz ayrışmayı temsil eden bir "ağaç" (aslında çoğunlukla ağaç gibi yönlendirilmiş asiklik bir grafik) üretir. Ayrıştırma sonrası geçiş belirsizlikleri çözebilir.
Bu tekniği DMS Software Reengineering Tookit için C ve C ++ ön uçlarında kullanıyoruz (Haziran 2017 itibariyle bunlar MS ve GNU lehçelerinde tam C ++ 17'yi ele alıyor). Milyonlarca satır büyük C ve C ++ sistemlerini işlemek için kullanılmıştır, tam, kesin ayrıştırmalar, kaynak kodunun tüm ayrıntılarını içeren AST'ler üretmektedir. ( C ++ 'ın en sinir bozucu ayrışması için AST'ye bakınız. )