2010-04-26 17 views
8

ile başarısız.ANTLR AST kuralları basit bir gramere sahip RewriteEmptyStreamException

assignment 
    : IDENT ':=' expr ';' -> ^(':=' IDENT expr) 
    ; 
expr  
    : factor ('*' factor)* -> ^('*' factor+) 
    ; 
factor 
    : primary ('+' primary)* -> ^('+' primary+) 
    ; 
primary 
    : NUM 
    | '(' expr ')' -> ^(expr) 
    ; 

Ama çalışmıyor: Ben çevrimiçi ve Dil Kalıpları kitapta okuduğum kadarıyla, böyle dilbilgisi değiştirmek gerekir. Tamamlayıcı olsa da, ayrıştırıcıyı çalıştırdığımda bir RewriteEmptyStreamException hatası alıyorum. İşte işler tuhaflaşıyor.

ADD ve MULT sözdizimi belirteçleri ve bunları ağaç düğümleri yerine kullanacak olursak, hata olmadan çalışır. Ben düğüm eki gösterimini kullanırsanız

tokens { ADD; MULT; } 

expr  
    : factor ('*' factor)* -> ^(MULT factor+) 
    ; 
factor 
    : primary ('+' primary)* -> ^(ADD primary+) 
    ; 

Alternatif olarak, aynı zamanda sorunsuz görünen:

expr  
    : factor ('*'^ factor)* 
    ; 
factor 
    : primary ('+'^ primary)* 
    ; 

davranışındaki bu tutarsızlık bir hata mı?

cevap

10

Hayır, bir hata değil, AFAIK. Örneğin sizin expr kuralını atın: * beri

expr  
    : factor ('*' factor)* -> ^('*' factor+) 
    ; 

mevcut olmayabilir, aynı zamanda AST yeniden yazma kuralında olmamalıdır. Yani, yukarıda yanlış ve ANTLR bu konuda şikayetçi doğru.

Şimdi yerine MULT gibi hayali bir belirteç eklerseniz: Kural hep bir veya daha fazla factor 's üretecek beri

expr  
    : factor ('*' factor)* -> ^(MULT factor+) 
    ; 

tüm tamamdır. Ağaç İnşaatThe Definitive ANTLR Reference den:

expr  
    : (factor -> factor) ('*' f=factor -> ^('*' $expr $f))* 
    ; 

Ayrıca bölüm 7 bkz: muhtemelen yapmaya ne kast

böyle bir şeydir. Özellikle Paragraf (sayfa 173) ve Paragrafları Yeniden Düzenleme Kuralları Kurallar (sayfa 174/175) 'de yer alan Önceki Kural AST'leri. Aynı düzeydeki tüm çocuklarla '*' operatör için bir N-li ağacı oluşturmak istiyorsanız

7

bunu yapabilirsiniz: Burada

expr 
    : (s=factor -> factor) (('*' factor)+ -> ^('*' $s factor+))? 
    ; 

bu dönecektir bazı örnekler şunlardır:

Tokens: AST 
factor: factor 
factor '*' factor: ^('*' factor factor) 
factor '*' factor '*' factor: ^('*' factor factor factor) 

Bart'ın yukarıdaki üçüncü örnek böyle iki çocuklu bir düğüm, her ardışık yineleme için $ expr sonucu beri, iç içe geçmiş bir ağaç üretecektir:

factor * factor * factor: ^('*' factor ^('*' factor factor)) 
Çarpma değişebilir olduğundan muhtemelen ihtiyaç duymadığınız

.

+0

Teşekkürler bir ton @JoelPM. Tam olarak aradığım şey bu. Değerlendirirken derin iç içe ağaç ve yığın taşmaları ile ilgili bir sorun yaşadık.Bu bize bir N-ary ağacı üretme şansı verir ve ağacın derinliğini büyük ölçüde azaltır. –