2017-01-24 64 views
6

bağlam-bağımlı öncelik kuralları (her ikisi de here tarif edilmiştir) kullanan mutlu burada kodu normal öncelik kuralları kullanan bir, ve bir iki parçacıkları bulunmaktadır.mutlu bağlam-bağımlı Operatör Önceliği

Normal:

%left '+' 
%left '*' 
%% 

Exp :: { Exp } 
    : Exp '+' Exp { Plus $1 $3 } 
    | Exp '*' Exp { Times $1 $3 } 
    | var   { Var $1 } 

Bağlam bağımlı:

a * b + c * d 

Normal versiyonu verir:

Plus (Times (Var "a") (Var "b")) (Times (Var "c") (Var "d")) 
giriş Verilen

%left PLUS 
%left TIMES 
%% 

Exp :: { Exp } 
    : Exp '+' Exp %prec PLUS { Plus $1 $3 } 
    | Exp '*' Exp %prec TIMES { Times $1 $3 } 
    | var      { Var $1 } 

bağlam-bağımlı sürümü oysa

verir:

Times (Var "a") (Plus (Var "b") (Times (Var "c") (Var "c"))) 

bu ikisi de aynı çıktıyı vermek gerekmez mi? Ne yapıyorum ki burada farklı ayrıştırma ağaçları üretiyorlar?

cevap

4

"Bağlam bağımlı öncelik" bu özelliği açıklayan bir çok yanıltıcı bir yoldur. Önceki bölümdeki öncelik algoritmasının tarifi büyük ölçüde doğrudur. bu da anlaşılacağı gibi

, bir öncelik karşılaştırması (azaltılabilir) bir üretim ve (kaydırılabilir) bir terminali arasında olduğu. Bu basit gerçek, öncelikli olarak, terminalin sadece bir özelliği olduğu gibi öncelik beyanı sözdizimini tasarlama kararı ile karıştırılır.

yapımın öncelik %prec ile açık bir beyan olmadığı sürece üretiminde son terminalin öncelik kopyalayarak ayarlanır. Ya da başka bir şekilde ifade etmek gerekirse, üretimin ispatı, son belirtecin önceliğine göre varsayılan olarak %prec cümlesiyle ayarlanır. Her iki şekilde de, yalnızca üretimin önceliğini, bazı terminallerinkiyle aynı olduğunu söyleyerek tanımlayabilirsiniz. Bu her zaman uygun olmadığından, ayrıştırıcı oluşturucu size dilbilgisi sembolünün adı olmayan keyfi bir ad kullanma seçeneğini sunar. Uygulama bir terminal olarak adını tedavi ve aslında herhangi bir gramer kuralı hiçbir zaman kullanılmaz gerçeğini göz ardı etmek, ancak mantıksal olarak o belirli üretime tahsis edilecek bir öncelik seviyesine adıdır.

İlk örneğinizde, üretimlerin önceliklerini her bir üretimdeki son (aslında, yalnızca) terminale göre varsayılan olarak ayarlamanıza izin verdiniz. Fakat ikinci örneğinizde iki öncelikli öncelik seviyesi, PLUS ve TIMES'i tanımladınız ve bunları iki prodüksiyonun önceliğini ayarlamak için kullanıyorsunuz. Ancak herhangi bir terminalin önceliğini beyan etmiyorsunuz. ayrıştırıcı jeneratör azalabilir üretim ve kaydırılmış olabilir terminalin nispi öncelik kontrol çalıştığında Yani, o şeylerden yalnızca biri ilan öncelik olduğunu bulur. Ve bu durumda, daima değişiyor. Bu aptal soru ise daha önce mutlu hiç kullanmadım çünkü

+1

, beni affet. Bu, '% left' + 'anlamına geliyor mu? % left '*' '* * '+' ve' '*' 'için önceliği bildirir, ancak'% PLUS; % sol TIMES *, "PLUS" ve "TIMES" için önceliğe sahip değil mi? –

+0

@DanielWagner: Ne yazdığım hakkında net olmayan şey neydi? '% kaldı '+'; % left '*' '' + ''ve'' * ''ve'% left PLUS için öncelik beyan eder; % sol TIMES', "PLUS" ve "TIMES" için öncelik beyan eder. Ancak önceliklerin karşılaştırılması her zaman bir üretim ile bir terminal arasında ve% 'si de PLUS; % sol TIMES seçeneği, * '+' ve ''*'' için * önceliklerini bildirmez. Neden olsunVe eğer '' + '' ve '' * ''öncelikleri bildirmemişse,' PLUS 've' TIMES 'önceliklerini karşılaştırmak için hiçbir şey yoktur. – rici

+0

Teşekkürler, bu onu temizler! İkinci örnekteki '+ '' '' '' 'PLUS'un önceliğini karşılaştırmayı denemeyi başaramadım ve başarılı olamadım (çünkü sadece“ PLUS'un önceden bildirilmiş bir önceliği vardır). –