2010-04-26 13 views
8

के साथ विफल रहा एक सरल व्याकरण है:ANTLR AST नियम RewriteEmptyStreamException

grammar sample; 
options { output = AST; } 
assignment 
    : IDENT ':=' expr ';' 
    ; 
expr  
    : factor ('*' factor)* 
    ; 
factor 
    : primary ('+' primary)* 
    ; 
primary 
    : NUM 
    | '(' expr ')' 
    ; 
IDENT : ('a'..'z')+ ; 
NUM : ('0'..'9')+ ; 
WS : (' '|'\n'|'\t'|'\r')+ {$channel=HIDDEN;} ; 

अब मैं कुछ पुनर्लेखन नियम जोड़ने के लिए एक एएसटी उत्पन्न करना चाहते हैं। मैं ऑनलाइन और भाषा पैटर्न पुस्तक में क्या पढ़ा है से, मैं इस तरह व्याकरण को संशोधित करने में सक्षम होना चाहिए:

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

लेकिन यह काम नहीं करता। हालांकि यह ठीक से संकलित करता है, जब मैं पार्सर चलाता हूं तो मुझे एक रिवाइट EmptyStreamException त्रुटि मिलती है। यहां वह जगह है जहां चीजें अजीब होती हैं।

यदि मैं छद्म टोकन एडीडी और मल्टी को परिभाषित करता हूं और पेड़ नोड अक्षर के बजाय उनका उपयोग करता हूं, तो यह बिना त्रुटि के काम करता है।

tokens { ADD; MULT; } 

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

वैकल्पिक रूप से, अगर मैं नोड प्रत्यय संकेतन का उपयोग, यह भी ठीक से काम करने के लिए प्रकट होता है:

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

एक बग व्यवहार में इस विसंगति है?

उत्तर

10

नहीं, एक बग नहीं, AFAIK। उदाहरण के लिए अपने expr नियम लें:

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

* के बाद से उपस्थित नहीं हो सकता है, यह भी अपने एएसटी पुनर्लेखन नियम में नहीं होना चाहिए। तो, उपरोक्त गलत है और एएनटीएलआर इसके बारे में शिकायत कर रहा है सही है।

अब अगर आप MULT बजाय की तरह एक काल्पनिक टोकन सम्मिलित करें:

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

सब ठीक है के बाद से अपने नियम हमेशा एक या अधिक factor के उत्पादन करेगा। ट्री निर्माणThe Definitive ANTLR Reference से:

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

इसके अलावा अध्याय 7 देखें:

आप शायद करने के लिए मतलब क्या कुछ इस तरह है। विशेष रूप से पैराग्राफ सुब्रूल्स (पृष्ठ 173) और रिवाइट नियमों में पिछले नियम एएसटी संदर्भित (पृष्ठ 174/175) में अनुच्छेद नियम।

7

आप एक ही स्तर पर '*' सभी बच्चों के साथ ऑपरेटर के लिए एक एन-ary पेड़ उत्पन्न करने के लिए चाहते हैं तो आप ऐसा कर सकते हैं:

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

कुछ इस प्रकार वापस आ जाएगी के कुछ उदाहरण हैं:

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

बार्ट की तीसरी उपरोक्त उदाहरण एक नेस्टेड पेड़ का उत्पादन करेगा, प्रत्येक अगली यात्रा के लिए $ expr का परिणाम के बाद से दो बच्चों के साथ एक नोड, इस तरह है:

factor * factor * factor: ^('*' factor ^('*' factor factor)) 

जो आपको संभवतः गुणा के बाद की आवश्यकता नहीं है कम्यूटिव है।

+0

धन्यवाद एक टन @ जोएलपीएम। यही वह है जिसकी तलाश में मैं हूं। मूल्यांकन करते समय हमें घोंसले हुए पेड़ और ढेर के साथ बहने का मुद्दा था।यह हमें एन-आरी पेड़ उत्पन्न करने का मौका देता है और वृक्ष की गहराई को कम करता है –

संबंधित मुद्दे