Aşağıda, C ++ 'ın ayrıştırılmasının neden (muhtemelen) en sevdiğim gösterimi (muhtemelen) Turing-complete , çünkü yalnızca belirli bir tam sayı asal ise sözdizimsel olarak doğru bir program gösteriyor.
Bu yüzden iddia ediyorum C ++ 'ın ne bağlamsız ne de bağlam duyarlı .
Herhangi bir prodüksiyonun her iki tarafında rastgele sembol dizilerine izin verirseniz, Chomsky hiyerarşisinde bağlama duyarlı bir dilbilgisinden daha güçlü olan bir Type-0 dilbilgisi ("kısıtlamasız") üretirsiniz ; kısıtsız dilbilgisi Turing-complete'tur. Bağlama duyarlı (Tip-1) dilbilgisi, bir prodüksiyonun sol tarafında birden çok bağlam sembolüne izin verir, ancak aynı bağlam, prodüksiyonun sağ tarafında da görünmelidir (dolayısıyla "bağlama duyarlı" adı). [1] Bağlama duyarlı dilbilgisi doğrusal bağlı Turing makinelerine eşdeğerdir .
Örnek programda, birincil hesaplama doğrusal sınırlı bir Turing makinesi tarafından gerçekleştirilebilir, bu nedenle Turing denkliğini tam olarak kanıtlamaz, ancak önemli olan ayrıştırıcının sözdizimsel analiz yapmak için hesaplamayı yapması gerektiğidir. Bir şablon örneği olarak ifade edilebilir herhangi bir hesaplama olabilir ve C ++ şablon örneklemesinin Turing-complete olduğuna inanmak için her neden olabilir. Bkz. Örneğin, Todd L. Veldhuizen'in 2003 tarihli makalesi .
Ne olursa olsun, C ++ bir bilgisayar tarafından ayrıştırılabilir, bu nedenle bir Turing makinesi tarafından kesinlikle ayrıştırılabilir. Sonuç olarak, sınırsız bir dilbilgisi bunu tanıyabilir. Aslında böyle bir gramer yazmak pratik olmaz, bu yüzden standart bunu yapmaya çalışmaz. (Aşağıya bakınız.)
Belirli ifadelerin "belirsizliği" ile ilgili sorun çoğunlukla kırmızı bir ringa balığıdır. Başlangıç olarak, belirsizlik bir dil değil, belirli bir dilbilgisinin bir özelliğidir. Bir dilin belirgin gramerleri olmadığı kanıtlanabilse bile, bağlamsız bir gramer tarafından tanınabilirse, bağlam içermez. Benzer şekilde, bağlamdan bağımsız bir dilbilgisi tarafından tanınamıyor ancak bağlama duyarlı bir dilbilgisi tarafından tanınabiliyorsa, içeriğe duyarlıdır. Belirsizlik ilgili değildir.
Ancak, auto b = foo<IsPrime<234799>>::typen<1>();
aşağıdaki programdaki 21 numaralı satır (ör. ) Gibi her durumda, ifadeler hiç belirsiz değildir; bağlama göre farklı şekilde ayrıştırılırlar. Sorunun en basit ifadesinde, belirli tanımlayıcıların sözdizimsel kategorisi, nasıl bildirildiklerine bağlıdır (örneğin, türler ve işlevler), bu da resmi dilin iki keyfi uzunluklu dizenin aynı program aynıdır (beyan ve kullanım). Bu, aynı kelimenin ardışık iki tam kopyasını tanıyan dilbilgisi olan "kopya" dilbilgisi ile modellenebilir. Pompalama lemmasıyla kanıtlanması kolaydırbu dilin bağlamdan bağımsız olmadığı. Bu dil için bağlama duyarlı bir dilbilgisi mümkündür ve bu sorunun cevabında bir Tip-0 dilbilgisi sağlanmıştır: /math/163830/context-sensitive-grammar-for-the- kopyalama dili .
Eğer biri C ++ 'ı ayrıştırmak için bağlama duyarlı (veya kısıtlamasız) bir dilbilgisi yazmaya çalışacak olsaydı, büyük olasılıkla evreni karalamalarla doldururdu. C ++ 'ı ayrıştırmak için bir Turing makinesi yazmak da aynı derecede imkansız bir girişim olacaktır. Bir C ++ programı yazmak bile zordur ve bildiğim kadarıyla hiçbirinin doğru olmadığı kanıtlanmıştır. Bu nedenle standart tam bir resmi dilbilgisi sağlamaya çalışmaz ve ayrıştırma kurallarından bazılarını teknik İngilizce olarak yazmayı seçer.
C ++ standardında biçimsel bir dilbilgisi gibi görünen şey, C ++ dilinin sözdiziminin tam biçimsel tanımı değildir. Önişlemeden sonra dilin tam biçimsel tanımı bile değildir, biçimselleştirilmesi daha kolay olabilir. (Ancak bu dil olmazdı: standart tarafından tanımlanan C ++ dili ön işlemciyi içerir ve ön işlemcinin çalışması algoritmik olarak tanımlanır, çünkü herhangi bir dilbilgisel formalizmde tanımlanması son derece zor olacaktır. bir kereden fazla uygulanması gereken kurallar da dahil olmak üzere sözcüksel ayrışmanın açıklandığı standardın.)
Çeşitli gramerler (sözcüksel analiz için üst üste binen iki dilbilgisi, biri önişlemeden önce gerçekleşir, diğeri gerekirse daha sonra artı "sözdizimsel" dilbilgisi) bu önemli notla birlikte (vurgu eklenmiştir):
C ++ sözdiziminin bu özeti, kavramaya yardımcı olmak amacıyla hazırlanmıştır. Dilin kesin bir ifadesi değildir . Özellikle, burada açıklanan dilbilgisi , geçerli C ++ yapılarının bir üst kümesini kabul eder . İfadeleri deklarasyonlardan ayırmak için ayrımcılık kuralları (6.8, 7.1, 10.2) uygulanmalıdır. Ayrıca, sözdizimsel olarak geçerli ancak anlamsız yapıları ayıklamak için erişim kontrolü, belirsizlik ve tür kuralları kullanılmalıdır.
Son olarak, burada vaat edilen program. 21 numaralı hat, yalnızca N girişi IsPrime<N>
asal olduğunda sözdizimsel olarak doğrudur . Aksi takdirde, typen
bir şablon değil bir tamsayıdır, sözdizimsel olarak geçerli bir ifade olmadığı için sözdizimsel olarak yanlış olduğu typen<1>()
gibi ayrıştırılır .(typen<1)>()
()
template<bool V> struct answer { answer(int) {} bool operator()(){return V;}};
template<bool no, bool yes, int f, int p> struct IsPrimeHelper
: IsPrimeHelper<p % f == 0, f * f >= p, f + 2, p> {};
template<bool yes, int f, int p> struct IsPrimeHelper<true, yes, f, p> { using type = answer<false>; };
template<int f, int p> struct IsPrimeHelper<false, true, f, p> { using type = answer<true>; };
template<int I> using IsPrime = typename IsPrimeHelper<!(I&1), false, 3, I>::type;
template<int I>
struct X { static const int i = I; int a[i]; };
template<typename A> struct foo;
template<>struct foo<answer<true>>{
template<int I> using typen = X<I>;
};
template<> struct foo<answer<false>>{
static const int typen = 0;
};
int main() {
auto b = foo<IsPrime<234799>>::typen<1>(); // Syntax error if not prime
return 0;
}
[1] Daha teknik olarak ifade etmek gerekirse, bağlama duyarlı bir gramerdeki her üretim şu biçimde olmalıdır:
αAβ → αγβ
burada A
terminal olmayan bir ve α
, β
muhtemelen gramer sembollerin boş dizileridir ve γ
boş olmayan bir dizidir. (Dilbilgisi sembolleri terminal veya terminal olmayan olabilir).
Bu A → γ
sadece bağlamda olduğu gibi okunabilir [α, β]
. Bağlamdan bağımsız (Tip 2) bir dilbilgisinde α
ve β
boş olmalıdır.
Her bir üretimin formda olması gereken "tekdüze" kısıtlama ile gramerleri de kısıtlayabileceğiniz ortaya çıkıyor:
α → β
nerede |α| ≥ |β| > 0
( |α|
"uzunluğu" anlamına gelir α
)
Monotonik dilbilgileri tarafından tanınan dil kümesinin, içeriğe duyarlı dilbilgileri tarafından tanınan dil kümesiyle tam olarak aynı olduğunu kanıtlamak mümkündür ve çoğu zaman kanıtları monotonik dilbilgisi üzerine dayandırmak daha kolaydır. Sonuç olarak, "tekdüze" anlamına geldiği gibi "bağlama duyarlı" ifadesini görmek oldukça yaygındır.