दिलचस्प पोस्ट
रिजर्व.sendRedirect () का उपयोग कर छुपा पैरामीटर पास करें उद्देश्य सी संदेश प्रेषण तंत्र वर्तमान विधानसभा का मार्ग प्राप्त करना यह क्या है जो एन्यूम बनाता है। हसफ्लैग बहुत धीमा है? आरडीडीएस में स्पार्क-ओपनिंग फाइल नाम wpf में फ़ाइल पथ की सूची से ट्रीदृश्य को पॉप्युलेट करें क्या एक .net windows अनुप्रयोग को एक .exe में संकुचित किया जा सकता है? एक्सेल में अवधि और स्थान के अलावा स्ट्रिंग से सभी गैर अल्फ़ान्यूमेरिक वर्ण कैसे निकालें? मैथलेट कोड को पायथन में परिवर्तित करने के लिए एक उपकरण कैसे जावा एटिल से बचें। कॉन्ट्रैक्टमोडिफिकेशन अपेशन जब किसी अररियलिस्ट से तत्वों को निकालते और निकालते हैं अन्य सूची से मूल्यों के आधार पर सूची छंटनी? एंड्रॉइड: मैं इसे हिला करना चाहता हूं लंबाई का उपयोग किए बिना स्ट्रिंग की लंबाई () विधि एप्लिकेशन / एक्स-जावास्क्रिप्ट और टेक्स्ट / जावास्क्रिप्ट सामग्री प्रकारों के बीच का अंतर दिए गए HTML के साथ एक आइफ्रेम बनाना गतिशील रूप से

क्या आप पायथन की सिंटैक्स में नए स्टेटमेंट जोड़ सकते हैं?

क्या आप पायथन की सिंटैक्स में नए स्टेटमेंट जोड़ सकते हैं (जैसे print , raise , with )?

कहो, अनुमति दें ..

 mystatement "Something" 

या,

 new_if True: print "example" 

यदि आपको चाहिए , तो ऐसा नहीं है, बल्कि यदि यह संभव है (अजगर दुभाषियों कोड को संशोधित करने से कम)

Solutions Collecting From Web of "क्या आप पायथन की सिंटैक्स में नए स्टेटमेंट जोड़ सकते हैं?"

आपको यह उपयोगी पायेगा – पायथन इंटरनल: यहां पायथन के लिए एक नया स्टेटमेंट जोड़ा जा रहा है:


यह आलेख बेहतर ढंग से समझने का एक प्रयास है कि पायथन के फ्रंट-एंड कैसे काम करता है। बस प्रलेखन और स्रोत कोड को पढ़ना थोड़ा उबाऊ हो सकता है, इसलिए मैं यहां एक हाथ-थ्रू पर जा रहा हूं: मैं पायथन until एक बयान जोड़ने के लिए जा रहा हूं।

इस लेख के लिए सभी कोडिंग पायथन मर्क्यूरियल रिपॉजिटरी मिरर में अत्याधुनिक Py3k शाखा के विरुद्ध किया गया था।

बयान until

रूबी जैसी कुछ भाषाओं में एक बयान है, जो कि समय के लिए पूरक है ( until num == 0 बराबर है, while num != 0 )। रूबी में, मैं लिख सकता हूँ:

 num = 3 until num == 0 do puts num num -= 1 end 

और यह प्रिंट होगा:

 3 2 1 

इसलिए, मैं अजगर को समान क्षमता जोड़ना चाहता हूं। यही है, लिखने में सक्षम होने के नाते:

 num = 3 until num == 0: print(num) num -= 1 

भाषा-वकालत विषयांतर

यह लेख पायथन until एक बयान के अतिरिक्त सुझाव देने का प्रयास नहीं करता है। यद्यपि मुझे लगता है कि ऐसा कोई कथन कुछ कोड स्पष्ट कर देगा, और यह लेख दिखाता है कि यह कितना आसान है, मैं पूरी तरह से कम्युनिज्म के अजगर के दर्शन का सम्मान करता हूं। मैं यहाँ करने की कोशिश कर रहा हूं, वास्तव में, पायथन के आंतरिक कामकाज में कुछ अंतर्दृष्टि प्राप्त है

व्याकरण को संशोधित करना

अजगर pgen नामक कस्टम पार्सर जनरेटर का उपयोग करता है यह LL (1) पार्सर है जो पायथन स्रोत कोड को एक पार्स ट्री में कनवर्ट करता है। पारसर जनरेटर के लिए इनपुट फ़ाइल Grammar/Grammar [1] यह एक सरल पाठ फ़ाइल है जो पायथन के व्याकरण को निर्दिष्ट करती है।

[1] : यहां से, पायथन स्रोत में फ़ाइलों के संदर्भ स्रोत पेड़ की मूल अपेक्षाकृत दिए गए हैं, जो कि निर्देशिका है जहां आप विन्यस्त करते हैं और पायथन का निर्माण करते हैं।

व्याकरण फ़ाइल में दो संशोधनों की आवश्यकता है। पहला बयान until लिए एक परिभाषा जोड़ना है। मुझे पता चला कि कब while बयान परिभाषित किया गया था ( while_stmt ), और नीचे दिए गए जब until_stmt जोड़ा गया [2] :

 compound_stmt: if_stmt | while_stmt | until_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] while_stmt: 'while' test ':' suite ['else' ':' suite] until_stmt: 'until' test ':' suite 

[2] : यह एक सामान्य तकनीक को दर्शाता है जिसका इस्तेमाल मैं स्रोत कोड को संशोधित करते समय करता हूं: मैं समानता से काम करता हूं: यह सिद्धांत आपकी सभी समस्याओं का समाधान नहीं करेगा, लेकिन यह निश्चित रूप से प्रक्रिया को कम कर सकती है। चूंकि until इसके लिए किया जाना बाकी है, until से यह बहुत सुंदर दिशानिर्देश के रूप में कार्य करता है।

ध्यान दें कि मैंने अपनी परिभाषा से else खंड को बाहर करने का निर्णय लिया है, बस इसे थोड़ा अलग करने के लिए (और क्योंकि मैं स्पष्ट रूप से छोरों के else खंड को नापसंद करते हैं और ऐसा नहीं लगता कि यह ज़ेन ऑफ़ पायथन के साथ अच्छी तरह से फिट होता है) ।

दूसरे परिवर्तन के लिए नियम को संशोधित करना है compound_stmt तक until_stmt शामिल करने के लिए, जैसा कि आप ऊपर स्निपेट में देख सकते हैं यह सही है while_stmt , फिर से।

जब आप Grammar/Grammar को संशोधित करने के बाद चलाते make , तो नोट करें कि pgen प्रोग्राम Include/graminit.h और Python/graminit.c Include/graminit.h को फिर से उत्पन्न करने के लिए pgen प्रोग्राम चलाया जाता है, और फिर कई फाइलें फिर से संकलित हो जाती हैं

AST पीढ़ी कोड को संशोधित करना

पायथन पार्सर ने एक पेर्स ट्री बनाया है, इस पेड़ को एएसटी में बदल दिया गया है, क्योंकि एएसटीएस संकलन प्रक्रिया के बाद के चरणों में काम करने के लिए बहुत आसान है ।

इसलिए, हम Parser/Python.asdl यात्रा करने जा रहे हैं जो पायथन के Parser/Python.asdl की संरचना को परिभाषित करता है और until हमारे नए स्टेटमेंट के लिए एक एएसटी नोड जोड़ता है, फिर से नीचे सही है:

 | While(expr test, stmt* body, stmt* orelse) | Until(expr test, stmt* body) 

यदि आप अब रन make , तो ध्यान दें कि फ़ाइलों का एक समूह संकलित करने से पहले, Parser/asdl_c.py AST परिभाषा फ़ाइल से सी कोड उत्पन्न करने के लिए चलाया जाता है। प्रोग्रामिंग को आसान बनाने के लिए यह (जैसे कि Grammar/Grammar ) पायथन स्रोत-कोड का एक और उदाहरण है (दूसरे शब्दों में, एक डीएसएल)। यह भी ध्यान रखें कि Parser/asdl_c.py एक पायथन स्क्रिप्ट है, यह एक प्रकार की बूटस्ट्रैपिंग है – अजगर से अजगर का निर्माण करने के लिए, पायथन पहले ही उपलब्ध होना चाहिए।

जबकि Parser/asdl_c.py ने हमारे नए परिभाषित एएसटी नोड (फाइलों में Include/Python-ast.h और Python/Python-ast.c ) को Python/Python-ast.c करने के लिए कोड तैयार किया है, फिर भी हम उस कोड को लिखना है जो एक प्रासंगिक पार्स- हाथ में इसे पेड़ नोड में यह फ़ाइल Python/ast.c में किया जाता है। वहां, ast_for_stmt नामक फ़ंक्शन एएसटी नोड्स में बयान के लिए पेर्स ट्री नोड को धर्मान्तरित करता है। फिर, हमारे पुराने दोस्त द्वारा निर्देशित while , हम यौगिक स्टेटमेंट को संभालने के लिए बड़े switch में सीधे कूदते हैं और तब तक के लिए एक खंड जोड़ते हैं until_stmt :

 case while_stmt: return ast_for_while_stmt(c, ch); case until_stmt: return ast_for_until_stmt(c, ch); 

अब हमें ast_for_until_stmt को लागू करना चाहिए यह रहा:

 static stmt_ty ast_for_until_stmt(struct compiling *c, const node *n) { /* until_stmt: 'until' test ':' suite */ REQ(n, until_stmt); if (NCH(n) == 4) { expr_ty expression; asdl_seq *suite_seq; expression = ast_for_expr(c, CHILD(n, 1)); if (!expression) return NULL; suite_seq = ast_for_suite(c, CHILD(n, 3)); if (!suite_seq) return NULL; return Until(expression, suite_seq, LINENO(n), n->n_col_offset, c->c_arena); } PyErr_Format(PyExc_SystemError, "wrong number of tokens for 'until' statement: %d", NCH(n)); return NULL; } 

दोबारा, इस बात को कोडित किया गया था, until कि मैं बराबर के साथ ast_for_while_stmt देख रहा हूं, until कि मैंने else खंड का समर्थन न करने का निर्णय लिया हो। अपेक्षित होने पर, एएसटी को फिर से पुनरावर्ती रूप से बनाया जाता है, अन्य एएसटी बनाने वाली ast_for_expr का उपयोग करके स्थिति अभिव्यक्ति और ast_for_suite लिए ast_for_suite जैसे कथन until के शरीर के लिए। अंत में, एक नए नोड का नाम दिया गया

ध्यान दें कि हम NCH और CHILD जैसे कुछ मैक्रोज़ के जरिए पेर्स-ट्री नोड n का उपयोग करते हैं। ये समझने योग्य हैं – उनका कोड Include/node.h

अवसाद: एएसटी संरचना

मैंने बयान के लिए एक नए प्रकार के एएसटी बनाने का फैसला किया, लेकिन वास्तव में यह आवश्यक नहीं है मैं कुछ काम सहेज सकता था और मौजूदा एएसटी नोड्स के इस्तेमाल से नई कार्यक्षमता को लागू कर सकता था, क्योंकि:

 until condition: # do stuff 

कार्यात्मक रूप से समतुल्य है:

 while not condition: # do stuff 

ast_for_until_stmt में नोड Until बनाने के बजाय, मैं एक नोड के साथ एक नोड बना सकता है While एक बच्चे के रूप में नोड। चूंकि AST संकलक पहले से ही इन नोड्स को कैसे संभालना जानता है, इस प्रक्रिया के अगले चरण को छोड़ दिया जा सकता है।

एटीएस को बाइटकोड में संकलित करना

अगले चरण एएसटी को पायथन बाइटकोड में संकलित कर रहा है। संकलन में एक इंटरमीडिएट परिणाम होता है जो कि सीएफजी (नियंत्रण फ्लो ग्राफ) होता है, लेकिन जब से उसी कोड को संभालता है, तब से मैं इस विवरण को अब तक अनदेखा कर दूंगा और इसे दूसरे लेख के लिए छोड़ दूंगा।

कोड हम अगले पर दिखेगा Python/compile.cwhile की अगुवाई के बाद, हम फ़ंक्शन compiler_visit_stmt पाते हैं, जो कि बाइटकोड में विवरणों को संकलित करने के लिए ज़िम्मेदार है। हम इसके लिए एक खंड जोड़ें:

 case While_kind: return compiler_while(c, s); case Until_kind: return compiler_until(c, s); 

यदि आपको आश्चर्य है कि क्या Until_kind है, तो यह एक निरंतर है (वास्तव में _stmt_kind का मूल्य) स्वचालित रूप से AST परिभाषा फ़ाइल से Include/Python-ast.h वैसे भी, हम compiler_until कहते हैं, जो निश्चित रूप से अभी भी मौजूद नहीं है। मैं इसे एक पल के लिए मिल जाएगा

यदि आप मेरी तरह उत्सुक हैं, तो आप देखेंगे कि compiler_visit_stmt अजीब है स्रोत के पेड़ को छानने की कोई भी राशि नहीं बताती है कि उसे कहां कहा जाता है। जब यह मामला है, तो केवल एक ही विकल्प रहता है – सी मैक्रो-फ़ू। दरअसल, एक छोटी जांच हमें Python/compile.c मैक्रो को Python/compile.c में परिभाषित Python/compile.c :

 #define VISIT(C, TYPE, V) {\ if (!compiler_visit_ ## TYPE((C), (V))) \ return 0; \ 

यह compiler_visit_stmt को compiler_body में शामिल करने के लिए उपयोग किया जाता है हमारे व्यापार पर वापस, हालांकि …

जैसा वादा किया गया है, यहां compiler_until :

 static int compiler_until(struct compiler *c, stmt_ty s) { basicblock *loop, *end, *anchor = NULL; int constant = expr_constant(s->v.Until.test); if (constant == 1) { return 1; } loop = compiler_new_block(c); end = compiler_new_block(c); if (constant == -1) { anchor = compiler_new_block(c); if (anchor == NULL) return 0; } if (loop == NULL || end == NULL) return 0; ADDOP_JREL(c, SETUP_LOOP, end); compiler_use_next_block(c, loop); if (!compiler_push_fblock(c, LOOP, loop)) return 0; if (constant == -1) { VISIT(c, expr, s->v.Until.test); ADDOP_JABS(c, POP_JUMP_IF_TRUE, anchor); } VISIT_SEQ(c, stmt, s->v.Until.body); ADDOP_JABS(c, JUMP_ABSOLUTE, loop); if (constant == -1) { compiler_use_next_block(c, anchor); ADDOP(c, POP_BLOCK); } compiler_pop_fblock(c, LOOP, loop); compiler_use_next_block(c, end); return 1; } 

मेरे पास एक बयान है: यह कोड पायथन बाइटकोड की गहरी समझ के आधार पर लिखा नहीं गया था। लेख के बाकी हिस्सों की तरह, यह परिजन compiler_while समारोह की नकल में किया गया था। इसे ध्यान से पढ़कर, हालांकि, ध्यान में रखते हुए कि पायथन वीएम स्टैक-आधारित है, और डिस मॉड्यूल के दस्तावेज में dis है, जिसमें विवरण के साथ पायथन बाइटकोड्स की सूची है , यह समझना संभव है कि क्या हो रहा है।

यही है, हमने किया … क्या हम नहीं?

सभी परिवर्तन करने और चलाना make , हम नए संकलित पायथन को चला सकते हैं और कथन until हमारा नया प्रयास कर सकते हैं:

 >>> until num == 0: ... print(num) ... num -= 1 ... 3 2 1 

वॉइला, यह काम करता है! चलिए देखते हैं कि डिप्टी मॉड्यूल का उपयोग करके नए स्टेटमेंट के लिए बाइटकोड बनाया गया है:

 import dis def myfoo(num): until num == 0: print(num) num -= 1 dis.dis(myfoo) 

यहां परिणाम है:

 4 0 SETUP_LOOP 36 (to 39) >> 3 LOAD_FAST 0 (num) 6 LOAD_CONST 1 (0) 9 COMPARE_OP 2 (==) 12 POP_JUMP_IF_TRUE 38 5 15 LOAD_NAME 0 (print) 18 LOAD_FAST 0 (num) 21 CALL_FUNCTION 1 24 POP_TOP 6 25 LOAD_FAST 0 (num) 28 LOAD_CONST 2 (1) 31 INPLACE_SUBTRACT 32 STORE_FAST 0 (num) 35 JUMP_ABSOLUTE 3 >> 38 POP_BLOCK >> 39 LOAD_CONST 0 (None) 42 RETURN_VALUE 

सबसे दिलचस्प ऑपरेशन संख्या 12 है: यदि स्थिति सही है, तो हम लूप के बाद कूदते हैं। यह until लिए सही शब्दार्थ है यदि कूद निष्पादित नहीं किया जाता है, तो लूप बॉडी चलती रहती है जब तक यह ऑपरेशन 35 पर हालत में वापस कूद जाता है।

मेरे परिवर्तन के बारे में अच्छा लग रहा है, तब मैंने अपने बाइटकोड दिखाने के बजाय फ़ंक्शन ( myfoo(3) निष्पादित करने की कोशिश की) परिणाम उत्साहजनक से कम था:

 Traceback (most recent call last): File "zy.py", line 9, in myfoo(3) File "zy.py", line 5, in myfoo print(num) SystemError: no locals when loading 'print' 

वाह … यह अच्छा नहीं हो सकता तो क्या हुआ?

लापता प्रतीक तालिका का मामला

एएसटी संकलित करते समय पायथन कम्पाइलर के चरणों में से एक यह संकलित कोड के लिए एक प्रतीक तालिका बना रहा है। PySymtable_Build में PyAST_Compile कॉल करने के लिए प्रतीक तालिका मॉड्यूल ( Python/symtable.c ) कहते हैं, जो एएसटी को कोड पीढ़ी के कार्यों के समान तरीके से चलता है। प्रत्येक दायरे के लिए एक प्रतीक तालिका होने से कंपाइलर कुछ महत्वपूर्ण जानकारी का पता लगाने में मदद करता है, जैसे कि वे चर वैश्विक हैं और जो एक क्षेत्र के लिए स्थानीय हैं।

समस्या को ठीक करने के लिए, हमें Python/symtable.c में symtable_visit_stmt फ़ंक्शन को संशोधित करना symtable_visit_stmt , until स्टेटमेंट्स के लिए समान कोड के बाद, बयान until संभाल करने के लिए कोड जोड़ना [3] :

 case While_kind: VISIT(st, expr, s->v.While.test); VISIT_SEQ(st, stmt, s->v.While.body); if (s->v.While.orelse) VISIT_SEQ(st, stmt, s->v.While.orelse); break; case Until_kind: VISIT(st, expr, s->v.Until.test); VISIT_SEQ(st, stmt, s->v.Until.body); break; 

[3] : वैसे, इस कोड के बिना Python/symtable.c लिए कंपाइलर चेतावनी है। कम्पाइलर नोटिस कि जब Until_kind मूल्य का मूल्य Until_kind के स्विच स्टेटमेंट में नहीं किया जाता है और शिकायत करता है। कंपाइलर चेतावनियों की जांच करना हमेशा महत्वपूर्ण होता है!

और अब हम वास्तव में कर चुके हैं इस परिवर्तन के बाद स्रोत को myfoo(3) से myfoo(3) का निष्पादन अपेक्षित होता है

निष्कर्ष

इस आलेख में मैंने यह दिखाया है कि पायथन के लिए एक नया स्टेटमेंट कैसे जोड़ें। यद्यपि पायथन कम्पाइलर के कोड में बदलाव की बहुत आवश्यकता होती है, इस बदलाव को लागू करना मुश्किल नहीं था, क्योंकि मैंने एक दिशानिर्देश के रूप में समान और मौजूदा कथन का उपयोग किया था।

पायथन कम्पाइलर सॉफ्टवेयर का एक अत्याधुनिक हिस्सा है, और मैं इसमें एक विशेषज्ञ होने का दावा नहीं करता हूं। हालांकि, मैं वास्तव में पायथन के आंतरिकों में दिलचस्पी रहा हूँ, और विशेषकर इसके फ्रंट-एंड इसलिए, मैं इस अभ्यास को संकलक के सिद्धांतों और स्रोत कोड के सैद्धांतिक अध्ययन के लिए एक बहुत उपयोगी साथी मिला। यह भविष्य के लेखों के आधार के रूप में काम करेगा जो कि संकलक में गहराई से आएगा।

संदर्भ

मैं इस लेख के निर्माण के लिए कुछ उत्कृष्ट संदर्भों का इस्तेमाल किया। यहां वे किसी खास क्रम में नहीं हैं:

  • पीईपी 339: सीपीयेथॉन कंपाइलर का डिजाइन – शायद अजगर कंपाइलर के लिए आधिकारिक दस्तावेजों का सबसे महत्वपूर्ण और व्यापक टुकड़ा है। बहुत कम होने के कारण, यह पायथन के पायथन के अच्छे दस्तावेजों की कमी को प्रदर्शित करता है।
  • "पायथन कंपाइलर इंटरनेशनल" – थॉमस ली द्वारा एक लेख
  • "पायथन: डिजाइन और कार्यान्वयन" – गिडो वैन रॉसम की एक प्रस्तुति
  • पायथन (2.5) आभासी मशीन, एक निर्देशित दौरा – पीटर टॉगर द्वारा एक प्रस्तुति

मूल स्रोत

इस तरह से काम करने का एक तरीका स्रोत को पूर्वप्रक्रिया करना है और इसे संशोधित करना है, अजगर को अपने जोड़ा गया स्टेटमेंट का अनुवाद करना। ऐसी कई समस्याएं हैं जो इस दृष्टिकोण को लाएंगी, और मैं इसे सामान्य उपयोग के लिए नहीं सुझाऊंगा, लेकिन भाषा के प्रयोग के लिए या विशिष्ट प्रयोजन के मेटाप्रोग्राफिकिंग के लिए, यह कभी-कभी उपयोगी हो सकता है

उदाहरण के लिए, हम कहते हैं कि हम एक "माइपरिंट" कथन पेश करना चाहते हैं, जिससे कि स्क्रीन पर मुद्रण के बजाय एक विशिष्ट फ़ाइल में प्रवेश किया जाता है अर्थात:

 myprint "This gets logged to file" 

के बराबर होगा

 print >>open('/tmp/logfile.txt','a'), "This gets logged to file" 

आपकी सिंटैक्स मौजूदा अजगर से मेल खाता है इस बात पर निर्भर करते हुए कि कैसे अपनी जगह बदलने के लिए, एक एएसटी उत्पन्न करने के लिए regex प्रतिस्थापन से, कई विकल्प हैं। एक अच्छा मध्यवर्ती दृष्टिकोण टोकनेइज़र मॉड्यूल का उपयोग करना है। यह आपको नए खोजशब्दों, नियंत्रण संरचनाओं आदि को जोड़ने की अनुमति देता है, जबकि स्रोत को समान रूप से अजगर दुभाषिया की व्याख्या करते हुए, इस प्रकार टूटने वाले क्रूड रिगेक्स समाधान से बचने का कारण होगा उपरोक्त "माइपरिंट" के लिए, आप निम्न परिवर्तन कोड लिख सकते हैं:

 import tokenize LOGFILE = '/tmp/log.txt' def translate(readline): for type, name,_,_,_ in tokenize.generate_tokens(readline): if type ==tokenize.NAME and name =='myprint': yield tokenize.NAME, 'print' yield tokenize.OP, '>>' yield tokenize.NAME, "open" yield tokenize.OP, "(" yield tokenize.STRING, repr(LOGFILE) yield tokenize.OP, "," yield tokenize.STRING, "'a'" yield tokenize.OP, ")" yield tokenize.OP, "," else: yield type,name 

(यह माइक्रिंट प्रभावी रूप से एक खोजशब्द बनाते हैं, इसलिए अन्यत्र एक चर के रूप में उपयोग की संभावनाओं का कारण बन सकता है)

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

 import new def myimport(filename): mod = new.module(filename) f=open(filename) data = tokenize.untokenize(translate(f.readline)) exec data in mod.__dict__ return mod 

इसके लिए आपको अपने अनुकूलित कोड को सामान्य अजगर मॉड्यूल से भिन्न रूप से संभालना आवश्यक है अर्थात् " some_mod = myimport("some_mod.py") import some_mod " के बजाय " some_mod = myimport("some_mod.py") "

एक अन्य काफी साफ (यद्यपि हेकी) समाधान एक कस्टम एन्कोडिंग बनाने के लिए है ( पीईपी 263 देखें) क्योंकि यह नुस्खा दर्शाता है। आप इसे इस रूप में लागू कर सकते हैं:

 import codecs, cStringIO, encodings from encodings import utf_8 class StreamReader(utf_8.StreamReader): def __init__(self, *args, **kwargs): codecs.StreamReader.__init__(self, *args, **kwargs) data = tokenize.untokenize(translate(self.stream.readline)) self.stream = cStringIO.StringIO(data) def search_function(s): if s!='mylang': return None utf8=encodings.search_function('utf8') # Assume utf8 encoding return codecs.CodecInfo( name='mylang', encode = utf8.encode, decode = utf8.decode, incrementalencoder=utf8.incrementalencoder, incrementaldecoder=utf8.incrementaldecoder, streamreader=StreamReader, streamwriter=utf8.streamwriter) codecs.register(search_function) 

अब इस कोड को चलाए जाने के बाद (उदाहरण के लिए आप इसे अपने .pythonrc या site.py में रख सकते हैं) "# coding: mylang" की टिप्पणी से शुरू होने वाला कोई भी कोड स्वचालित रूप से उपरोक्त preprocessing चरण के माध्यम से अनुवाद किया जाएगा। जैसे।

 # coding: mylang myprint "this gets logged to file" for i in range(10): myprint "so does this : ", i, "times" myprint ("works fine" "with arbitrary" + " syntax" "and line continuations") 

चेतावनियां:

पूर्वप्रक्रमक दृष्टिकोण में समस्याएं हैं, क्योंकि आप संभवत: से परिचित होंगे यदि आपने सी प्रीप्रोसेसर के साथ काम किया है मुख्य एक डिबगिंग है सभी अजगर देखता है preprocessed फ़ाइल है जिसका मतलब है कि स्टैक ट्रेस आदि में मुद्रित पाठ उस संदर्भ में होगा। यदि आपने महत्वपूर्ण अनुवाद किया है, तो यह आपके स्रोत टेक्स्ट से बहुत भिन्न हो सकता है उपरोक्त उदाहरण लाइन नंबर आदि नहीं बदलता है, तो बहुत अलग नहीं होगा, लेकिन जितना अधिक आप इसे बदलते हैं, उतना कठिन यह पता लगाना होगा।

हां, कुछ हद तक यह संभव है। वहाँ एक मॉड्यूल है जो goto को लागू करने और "खोजशब्दों" से comefrom लिए sys.settrace() का उपयोग करता है:

 from goto import goto, label for i in range(1, 10): for j in range(1, 20): print i, j if j == 3: goto .end # breaking out from nested loop label .end print "Finished" 

सोर्स कोड को बदलने और पुनः कंपाइलिंग (जो कि ओपन सोर्स के साथ संभव है) में छोटा, आधार भाषा बदलना वास्तव में संभव नहीं है।

यहां तक ​​कि अगर आप स्रोत को पुनः कंपाइल करते हैं, तो यह अजगर नहीं होगा, बस आपके हैक किए गए अप संस्करण को बदल दिया जाएगा जो आपको बहुत सावधान रहने की आवश्यकता है ताकि ये बग्स को इसमें न डालें।

हालांकि, मुझे यकीन नहीं है कि आप ऐसा क्यों करना चाहते हैं पायथन की ऑब्जेक्ट-ओरिएंटेड फीचर्स इस तरह की भाषा के साथ समान परिणाम प्राप्त करना काफी आसान बनाता है क्योंकि यह खड़ा है।

सामान्य जवाब: आपको अपनी स्रोत फाइलों को पूर्वप्रक्रमित करने की आवश्यकता है

अधिक विशिष्ट उत्तर: EasyExtend स्थापित करें , और निम्न चरणों का पालन करें:

i) एक नया लैंगलेट (विस्तार भाषा) बनाएं

 import EasyExtend EasyExtend.new_langlet("mystmts", prompt = "my> ", source_ext = "mypy") 

अतिरिक्त विनिर्देश के बिना फाइलों का एक गुच्छा EasyExtend / langlets / mystmts / के तहत बनाया जाएगा

ii) ओपन माइस्टैंट्स / पर्सडीफे / ग्रामर .ext और निम्नलिखित पंक्तियां जोड़ें

 small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_stmt | my_stmt ) my_stmt: 'mystatement' expr 

यह आपके नए स्टेटमेंट के सिंटैक्स को परिभाषित करने के लिए पर्याप्त है। Small_stmt गैर-टर्मिनल पायथन व्याकरण का हिस्सा है और यह उस स्थान पर है जहां नया स्टेटमेंट आदी है। पारसर अब नए बयान को पहचान लेगा, अर्थात् उसमें एक स्रोत फाइल पार्स की जाएगी। कंपाइलर इसे अस्वीकार कर देगा यद्यपि क्योंकि यह अभी भी वैध पायथन में परिवर्तित किया जाना है।

iii) अब किसी को बयान के शब्दों को जोड़ना होगा। इसके लिए किसी को एमएसआईटीएमटी / लैंगलेटपेज को संपादित करना होगा और एक my_stmt नोड विज़ेट को जोड़ना होगा।

  def call_my_stmt(expression): "defines behaviour for my_stmt" print "my stmt called with", expression class LangletTransformer(Transformer): @transform def my_stmt(self, node): _expr = find_node(node, symbol.expr) return any_stmt(CST_CallFunc("call_my_stmt", [_expr])) __publish__ = ["call_my_stmt"] 

iv) सीडी से लंगलेट / माइस्टैंट और टाइप करें

 python run_mystmts.py 

अब एक सत्र शुरू किया जाएगा और नए परिभाषित कथन का उपयोग किया जा सकता है:

 __________________________________________________________________________________ mystmts On Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] __________________________________________________________________________________ my> mystatement 40+2 my stmt called with 42 

एक तुच्छ कथन में आने के लिए बहुत कुछ कदम हैं, है ना? कोई एपीआई नहीं है, जो कि कोई भी सरल चीजों को बिना व्याकरण के परवाह किए बिना परिभाषित करता है। लेकिन ईई कुछ बग बहुत विश्वसनीय मॉड्यूल है तो यह समय की बात है कि एपीआई उभरता है जिससे प्रोग्रामर्स इंफिक्स ऑपरेटरों या छोटे स्टेटमेंट जैसे सुविधाजनक ओओ प्रोग्रामिंग का उपयोग करके सुविधाजनक सामान को परिभाषित कर सकते हैं। अधिक जटिल चीज़ों के लिए पायथन में पूरी भाषा एम्बेड करना एक लैंगलेट बनाने के माध्यम से एक पूर्ण व्याकरण दृष्टिकोण के चारों ओर जाने का कोई तरीका नहीं है।

नया बयान जोड़ने का एक बहुत सरल लेकिन गंदे तरीका है, केवल व्याख्यात्मक मोड में । मैं इसे केवल sys.displayhook का उपयोग करते हुए जीन एनोटेशन के संपादन के लिए बहुत कम 1-अक्षर के आदेशों का उपयोग कर रहा हूं, लेकिन सिर्फ इसलिए मैं इस प्रश्न का उत्तर दे सकता हूं मैंने वाक्यविन्यास त्रुटियों के लिए sys.excepthook को भी जोड़ दिया उत्तरार्द्ध वास्तव में बदसूरत है, रेखांकित बफर से कच्चे कोड को प्राप्त करना। लाभ यह है, इस तरह से नए बयानों को जोड़ना मुश्किल है

 jcomeau@intrepid:~/$ cat demo.py; ./demo.py #!/usr/bin/python -i 'load everything needed under "package", such as package.common.normalize()' import os, sys, readline, traceback if __name__ == '__main__': class t: @staticmethod def localfunction(*args): print 'this is a test' if args: print 'ignoring %s' % repr(args) def displayhook(whatever): if hasattr(whatever, 'localfunction'): return whatever.localfunction() else: print whatever def excepthook(exctype, value, tb): if exctype is SyntaxError: index = readline.get_current_history_length() item = readline.get_history_item(index) command = item.split() print 'command:', command if len(command[0]) == 1: try: eval(command[0]).localfunction(*command[1:]) except: traceback.print_exception(exctype, value, tb) else: traceback.print_exception(exctype, value, tb) sys.displayhook = displayhook sys.excepthook = excepthook >>> t this is a test >>> tt command: ['t', 't'] this is a test ignoring ('t',) >>> ^D 

Google के द्वारा पीडीएफ में एचटीएमएल में कनवर्ट किए गए नए स्टेटमेंट जोड़ने पर मुझे एक मार्गदर्शिका मिली है:

http://209.85.173.104/search?q=cache:IjUb82taSq0J:www.troeger.eu/teaching/pythonvm08lab.pdf+python+add+statement&hl=en&ct=clnk&cd=10

मूल रूप से, नए बयानों को जोड़ने के लिए, आपको Python/ast.c (अन्य चीजों के बीच) को संपादित करना होगा और अजगर द्विआधारी को Python/ast.c कंपाइल करना होगा।

हालांकि यह संभव है, न करें। आप कार्यों और कक्षाओं के माध्यम से लगभग सब कुछ हासिल कर सकते हैं (जो लोगों को आपकी स्क्रिप्ट को चलाने के लिए अजगर को पुनः कंपाइल करने की आवश्यकता नहीं है ..)

EasyExtend का उपयोग करना संभव है:

EasyExtend (ईई) शुद्ध पायथन में लिखी गई एक प्रीप्रोसेसर जनरेटर और मेटाप्रोग्रामिंग ढांचे और CPython के साथ एकीकृत है। EasyExtend का मुख्य उद्देश्य विस्तार भाषाओं का निर्माण है यानी कस्टम सिंटैक्स और सिमेंटिक्स को पायथन में जोड़ता है।

दुभाषिया को संशोधित किए बिना मुझे पता है कि पिछले कई वर्षों में कई भाषाओं को "एक्स्टेंसिबल" के रूप में वर्णित किया गया है, लेकिन जिस तरह से आप वर्णन कर रहे हैं आप फ़ंक्शन और क्लासेस जोड़कर पायथन का विस्तार करते हैं।

एक भाषा है जो अजगर नामक अजगर पर आधारित है जिसके साथ आप ऐसा काम कर सकते हैं। यह थोड़ी देर के लिए विकास में नहीं रहा है, लेकिन जिन सुविधाओं के लिए आपने पूछा वे नवीनतम संस्करण के साथ काम करते हैं

यह भाषा वाक्यविन्यास में बिल्कुल नए कथन नहीं जोड़ रहा है, लेकिन मैक्रोज़ एक शक्तिशाली टूल हैं: https://github.com/lihaoyi/macropy

कुछ चीजें सज्जाकारों के साथ किया जा सकता है उदाहरण के लिए मान लें, पायथन के पास कोई बयान नहीं था हम इस तरह एक समान व्यवहार को लागू कर सकते हैं:

 # ====== Implementation of "mywith" decorator ====== def mywith(stream): def decorator(function): try: function(stream) finally: stream.close() return decorator # ====== Using the decorator ====== @mywith(open("test.py","r")) def _(infile): for l in infile.readlines(): print(">>", l.rstrip()) 

यह एक बहुत ही अशुभ समाधान है, जैसा कि यहां किया गया है। विशेष रूप से व्यवहार जहां डेकोरेटर फ़ंक्शन कॉल करता है और किसी को _ सेट करता है अनपेक्षित होता है स्पष्टीकरण के लिए: यह डेकोरेटर लेखन के बराबर है

 def _(infile): ... _ = mywith(open(...))(_) # mywith returns None. 

और सज्जाकारों को आम तौर पर संशोधित करने की अपेक्षा होती है, कार्य निष्पादित करने के लिए नहीं।

मैंने एक ऐसी स्क्रिप्ट में पहले ऐसी विधि का उपयोग किया था, जहां मुझे कई फ़ंक्शंस के लिए अस्थायी रूप से कार्यशील निर्देशिका सेट करनी थी।

दस साल पहले आप नहीं कर सके, और मुझे शक है कि बदल गया है। हालांकि, यदि आप अजगर को पुनः कंपाइल करने के लिए तैयार थे, तो वाकई सिंटैक्स को फिर से संशोधित करने में कठिनाई नहीं थी, और मुझे संदेह है कि बदल गया है, या तो