मान लें कि आप अपने सभी तरीकों को खोजने के लिए अपने स्रोत कोड को पार्स करना चाहते हैं, जहां वे परिभाषित हैं और वे कौन से तर्क लेते हैं।
आप यह कैसे कर सकते हैं?
आपका पहला विचार इसके लिए एक रेगेक्सपी लिखना हो सकता है...
लेकिन क्या कोई बेहतर तरीका है?
हाँ!
स्थिर विश्लेषण एक ऐसी तकनीक है जिसका उपयोग आप तब कर सकते हैं जब आपको स्रोत कोड से ही जानकारी निकालने की आवश्यकता हो।
यह स्रोत कोड को टोकन (पार्सिंग) में परिवर्तित करके किया जाता है।
आइए इसमें शामिल हों!
पार्सर जेम का उपयोग करना
रूबी के पास मानक पुस्तकालय पर एक पार्सर उपलब्ध है, जिसका नाम रिपर है। आउटपुट के साथ काम करना मुश्किल है इसलिए मैं शानदार पार्सर मणि का उपयोग करना पसंद करता हूं। रूबोकॉप अपना जादू करने के लिए इस रत्न का उपयोग करता है।
इस रत्न में एक बाइनरी भी शामिल है जिसका उपयोग आप कुछ कोड को सीधे पार्स करने और परिणामी पार्स ट्री देखने के लिए कर सकते हैं।
यहां एक उदाहरण दिया गया है :
ruby-parse -e '%w(hello world).map { |c| c.upcase }'
आउटपुट इस तरह दिखता है:
(block (send (array (str "hello") (str "world")) :map) (args (arg :c)) (send (lvar :c) :upcase))
यह उपयोगी हो सकता है यदि आप यह समझने की कोशिश कर रहे हैं कि रूबी कुछ कोड कैसे पार करती है। लेकिन अगर आप अपना खुद का विश्लेषण उपकरण बनाना चाहते हैं तो आपको स्रोत फ़ाइल को पढ़ना होगा, उसे पार्स करना होगा और फिर उत्पन्न पेड़ को पार करना होगा।
उदाहरण :
require 'parser/current' code = File.read('app.rb') parsed_code = Parser::CurrentRuby.parse(code)की आवश्यकता है
पार्सर आपके कोड का एएसटी (सार सिंटेक्स ट्री) लौटाएगा। नाम से डरो मत, यह जितना आसान लगता है उससे कहीं ज्यादा आसान है 🙂
एएसटी को पार करना
अब जबकि आपने पार्सर . का उपयोग करके अपना कोड पार्स कर लिया है मणि आपको परिणामी एएसटी को पार करने की आवश्यकता है।
आप ऐसा एक वर्ग बनाकर कर सकते हैं जो AST::Processor . से विरासत में मिला हो ।
उदाहरण :
class Processor < AST::Processor end
फिर आपको इस क्लास को इंस्टेंट करना होगा और .प्रोसेस . को कॉल करना होगा विधि:
ast = Processor.new ast.process(parsed_code)
आपको कुछ पर_ . परिभाषित करने की आवश्यकता है तरीके। ये विधियां एएसटी में नोड नामों के अनुरूप हैं।
यह पता लगाने के लिए कि आपको किन विधियों को परिभाषित करने की आवश्यकता है, आप हैंडलर_मिसिंग . जोड़ सकते हैं आपके प्रोसेसर वर्ग के लिए विधि। आपको शुरू करने के लिए . की भी आवश्यकता है विधि।
class Processor < AST::Processor def on_begin(node) node.children.each { |c| process(c) } end def handler_missing(node) puts "missing #{node.type}" end endडालता है
यहां हम हैं :
आपके पास रूबी एएसटी और एक बुनियादी प्रोसेसर है, जब आप इस कोड को चलाते हैं तो आप अपने एएसटी के लिए नोड प्रकार देखेंगे।
अब :
आपको सभी पर_ . को लागू करने की आवश्यकता है जिन तरीकों का आप उपयोग करना चाहते हैं। उदाहरण के लिए, अगर मुझे सभी इंस्टेंस मेथड के नाम उनके लाइन नंबर के साथ चाहिए तो मैं यह कर सकता हूं:
def on_def(node) line_num = node.loc.line method_name = node.children[0] puts "Found #{method_name} at line #{line_num}" endपर रखता है
जब आप अपना प्रोग्राम अभी चलाते हैं, तो उसे पाए गए सभी विधि नामों को प्रिंट करना चाहिए।
निष्कर्ष
रूबी स्थिर विश्लेषण उपकरण बनाना उतना मुश्किल नहीं है जितना यह लग सकता है। यदि आप अधिक संपूर्ण उदाहरण चाहते हैं तो मेरे class_indexer मणि पर एक नज़र डालें। अब आपके अपने उपकरण बनाने की बारी है!
कृपया इस पोस्ट को साझा करें अगर आपने इसका आनंद लिया!