2013-08-28 5 views
18

एक हफ्ते पहले मैंने निम्नलिखित प्रोजेक्ट शुरू किया: एक व्याकरण जो जावा कोड के प्रत्यय को पहचानता है।एएनटीएलआर: जावा व्याकरण के प्रत्यय को पहचानने वाले इस व्याकरण का व्यवहार कैसे समझाया जा सकता है?

मैंने बेसलाइन के रूप में जावा (Java.g4) के लिए आधिकारिक ANTLR व्याकरण का उपयोग किया और कुछ नियमों को जोड़ना शुरू कर दिया। हालांकि, उन नए नियमों ने बाएं रिकर्सन भी पेश किया जिसे मुझे भी निपटना पड़ा।

कुछ दिनों के काम के बाद मेरे पास following code था। जब मैंने परीक्षण शुरू किया तो मैंने कुछ असामान्य देखा जो मैं अभी भी समझा नहीं सकता। जब इनपुट दिया { } पार्सर मुझे no viable alternative at input '<EOF>' बताता है लेकिन जब मैं नियम s2 के दाएँ हाथ के पक्ष में टर्मिनलों का क्रम बदलने के, खासकर अगर हम v2_1 | v2_2 | v2_3 ...v2_36 | v2_1 | v2_2 ... करने से दाएँ हाथ के पक्ष बदल (टर्मिनल v2_36 में ले जाया जाता पहली स्थिति), अनुक्रम { } स्वीकार किया जाता है।

मेरा पहला विचार थे क्योंकि मैंने देखा है कि इनपुट { } साथ पार्सर के पहले संस्करण नियम v2_3 पालन करने के लिए शुरू होता है कि Antlr पीछे नहीं है और सिर्फ इतना है कि कुछ भी नहीं पाया गया है की रिपोर्ट और अन्य विकल्पों पर विचार करने के लिए प्रयास नहीं करता है (कि मुझे क्या लगता है लेकिन शायद यह सच नहीं है) जैसे v2_36 जो वास्तव में सकारात्मक उत्तर देते हैं।

लेकिन, कुछ शोध के बाद, मुझे पता चला कि ANTLR वास्तव में बैकट्रैक करता है लेकिन केवल अगर सब कुछ विफल हो जाता है। कम से कम यह v3.3 के लिए सच है (इसे आधिकारिक ANTLR पेपर में पढ़ें) लेकिन मुझे लगता है कि यह v4 के लिए भी सच है। अब मैं थोड़ा उलझन में हूँ। इस परियोजना पर इतने सारे घंटों खर्च करने के बाद मैं वास्तव में भयानक महसूस करूंगा यदि मैं इसे काम नहीं करता हूं। क्या कोई किसी प्रकार की टिप या कुछ दे सकता है? धन्यवाद, बहुत सराहना की जाएगी।

संपादित

grammar Java; 
@parser::members {String ruleName; } 

start : compilationUnitSuf EOF; 

compilationUnitSuf 
    : {ruleName = "typeDeclarationSuf"; } s2 
    ; 

s2: '{' '}' v2_81 | '{' '}'; 
v2_81 : {ruleName.equals("enumBodyDeclarationsSuf")}? t173 | t173 '}'; 
t173: '}' | '{'*; 

LBRACKET: '{'; 
RBRACKET: '}'; 

WS : [ \t\r\n\u000C]+ -> skip 
    ; 

को समस्या को अलग करने की तो क्यों भविष्यवाणी एल्गोरिथ्म मुझे सुझाव है s2 -> v'{' '}' v2_81 -> ... बजाय s2 -> '{' '}' पालन करने के लिए प्रबंधित?

+1

मुझे नहीं पता कि _ "जावा कोड के प्रत्यय" _ से आपका क्या मतलब है। –

+0

यदि हमारे पास दिए गए जावा कोड के टोकन के अनुक्रम 'ए [1..एन]' हैं, तो हम अनुक्रम 'ए [जे], एक [जे + 1], ..., एक [ n] 'कुछ' 1 <= j <= n' के लिए (कोड 'कक्षा ए {int a;}' संभावित प्रत्यय 'ए {int a;}', '{int a;}', 'int a ;} 'आदि) लेकिन मुझे लगता है कि यह – svs

+2

प्रश्न के लिए अप्रासंगिक है क्या आप एएनटीएलआर का उपयोग कर रहे हैं? प्रत्यय पार्सिंग के लिए, एक जीएलआर पार्सर बहुत आसान होगा, और यह लगभग एलआर (1) व्याकरण को लगभग रैखिक समय, आईआईआरसी में विश्लेषण करेगा। ग्र्यून एंड जैकब्स (पार्सिंग टेक्निक्स: ए प्रैक्टिकल गाइड) में प्रत्यय पार्सिंग के बारे में एक पूरा अध्याय है। – rici

उत्तर

1

मुझे लगता है कि आप पाएंगे कि यह आपके द्वारा अपेक्षित तरीके से बैकट्रैक नहीं कर रहा है। इसका कारण यह है कि यह {} पाता है और फिर v2_181 देखने की अपेक्षा करता है, जो इसे नहीं मिलता है। क्योंकि यह बैकट्रैक नहीं करता है, यह आपको इच्छित विकल्प नहीं मिलता है। विकल्प केवल v2_181 वैकल्पिक बनाने के लिए है, तो आपको बैकट्रैकिंग की आवश्यकता नहीं है। नीचे कुछ:

grammar Java; 
@parser::members {String ruleName; } 

start : compilationUnitSuf EOF; 

compilationUnitSuf 
    : {ruleName = "typeDeclarationSuf"; } s2 
    ; 

s2: '{' '}' v2_81?; 
v2_81 : {ruleName.equals("enumBodyDeclarationsSuf")}? t173 | t173 '}'; 
t173: '}' | '{'*; 

LBRACKET: '{'; 
RBRACKET: '}'; 

WS : [ \t\r\n\u000C]+ -> skip 
    ; 
संबंधित मुद्दे