ऐसा लगता है कि कभी-कभी एंट्लर लेक्सर एक खराब विकल्प बनाता है जिस पर नियमों की धारा को टोकन करने के लिए उपयोग करने के लिए नियम ... मैं यह समझने की कोशिश कर रहा हूं कि एंटरल को स्पष्ट-से-मानव-सही विकल्प चुनने में कैसे मदद करें। मैं इस तरह पाठ पार्स हैं:एंटरल लेक्सर टोकन जो समान तारों से मेल खाते हैं, क्या होगा यदि लालची लेजर गलती करता है?
d/dt(x)=a
a=d/dt
d=3
dt=4
यह एक दुर्भाग्यपूर्ण वाक्य रचना कि एक मौजूदा भाषा का उपयोग करता है और मैं के लिए एक पार्सर लिखने के लिए कोशिश कर रहा हूँ है। "डी/डीटी (एक्स)" एक अंतर समीकरण के बाईं ओर का प्रतिनिधित्व कर रहा है। यदि आपको जरूरी है तो लिंगो को अनदेखा करें, बस यह जान लें कि यह "डी" द्वारा विभाजित नहीं है "डीटी"। हालांकि, "डी/डीटी" की दूसरी घटना वास्तव में "डी" द्वारा विभाजित "डी" है। ।!
यहाँ मेरी व्याकरण है:
grammar diffeq_grammar;
program : (statement? NEWLINE)*;
statement
: diffeq
| assignment;
diffeq : DDT ID ')' '=' ID;
assignment
: ID '=' NUMBER
| ID '=' ID '/' ID
;
DDT : 'd/dt(';
ID : 'a'..'z'+;
NUMBER : '0'..'9'+;
NEWLINE : '\r\n'|'\r'|'\n';
इस व्याकरण lexer पहले "घ/डीटी (" पकड़ लेता है और टोकन डीडीटी करने के लिए इसे बदल जाता है का उपयोग करते समय बिल्कुल सही अब बाद में lexer देखता है दूसरा "डी" इसके बाद "/" और कहते हैं, "हमम, मैं इसे एक आईडी और एक '/' के रूप में मिलान कर सकता हूं या मैं लालची हो सकता हूं और डीडीटी से मेल खाता हूं।" लेक्सर लालची हो जाता है ... लेकिन यह बहुत कम जानता है, वहां है नहीं "(" कुछ धारा बाद में इनपुट स्ट्रीम में। "जब लेक्सर लापता दिखता है" ("यह एक मिस्मिटेड टोकन एक्सेप्शन फेंकता है!
एकमात्र समाधान जो मैंने पाया है, सभी नियमों को स्थानांतरित करना है एक के साथ पार्सर व्याकरण की तरह: अगर मैं पहले से ही काम कर कोड की पंक्तियों पहले व्याकरण काम कर पर निर्भर के हजारों नहीं था
grammar diffeq_grammar;
program : (statement? NEWLINE)*;
statement
: diffeq
| assignment;
diffeq : ddt id ')' '=' id;
assignment
: id '=' number
| id '=' id '/' id
;
ddt : 'd' '/' 'd' 't' '(';
id : CHAR+;
number : DIGIT+;
CHAR : 'a'..'z';
DIGIT : '0'..'9';
NEWLINE : '\r\n'|'\r'|'\n';
यह एक अच्छा उपाय है। इस समस्या का शोध करने में 2 दिन व्यतीत करने के बाद मैं इस निष्कर्ष पर पहुंचा हूं कि एक लेक्सर ... वास्तव में दो मामलों में अंतर करने में सक्षम होना चाहिए। कुछ बिंदु पर एंटर लेक्सर दो नियमों के बीच निर्णय ले रहा है: डीडीटी और आईडी। यह डीडीटी चुनता है क्योंकि लेजर लालची है। लेकिन जब डीडीटी से मेल खाता है, तो मैं लेक्सर को आईडी का उपयोग करने के लिए वापस जाना चाहता हूं।
मैं भविष्यवाणियों या अन्य चालों का उपयोग करने के साथ ठीक हूं, जब तक व्याकरण मूल रूप से वही रहता है (यानी, लेक्सर में नियम, लेक्सर में रहते हैं। और अधिकांश नियम छूटे रहते हैं।)।
आदर्श रूप से मैं डीडीटी के लिए किसी भी वैध एंटर कोड के साथ लेक्सर नियम संशोधित कर सकता हूं ... और किया जा सकता है।
मेरी लक्षित भाषा जावा है।
धन्यवाद!
अद्यतन
कुछ महान जवाब के लिए आप लोग धन्यवाद !! मैंने उस उत्तर को स्वीकार किया जो मेरे प्रश्न के अनुरूप सबसे अच्छा है। मेरे द्वारा उपयोग किया जाने वाला वास्तविक समाधान मेरे अपने उत्तर में है (स्वीकार किए गए उत्तर नहीं), और ऐसे कई उत्तर हैं जो काम कर सकते थे। पाठक, सभी उत्तरों की जांच करें; उनमें से कुछ आपके मामले से बेहतर हो सकते हैं।
@dasblinkenlight, आपने पहले से ही इसकी अनुशंसा की है, इसलिए ओपी को इसके बारे में पता है: आपको मुझे मनाने की आवश्यकता नहीं है। चूंकि ओपी ने विशेष रूप से पूछा कि क्या व्याकरण रह सकता है वही, मैंने इसे पोस्ट किया। –
आप सही हैं, मैंने पहले पढ़ने पर "कामकाजी कोड की हजारों लाइनों" के बारे में हिस्सा याद किया। – dasblinkenlight
@dasblinkenlight, मेरा मतलब आपके जवाब को हटाने के लिए नहीं था! हालांकि ओपी जितना संभव हो उतना छोटा व्याकरण बदलना चाहता था, फिर भी आप एक जवाब के योग्य वैध बिंदु बढ़ाते हैं। –