2015-12-30 6 views
7

के माध्यम से नियमित अभिव्यक्तियों का आकलन करें मेरे पास कुछ जावास्क्रिप्ट कोड है, जिसमें से मुझे प्रत्येक शाब्दिक नियमित अभिव्यक्ति की प्रारंभ + अंत अनुक्रमणिका मिलनी चाहिए।UglifyJS

ऐसी जानकारी UglifyJS से कैसे निकाली जा सकती है?

var uglify = require('uglify-js'); 
var code = "func(1/2, /hello/);"; 
var parsed = uglify.parse(code); 

संरचना जो मैं परिवर्तनीय parsed में प्राप्त कर रहा हूं वह बहुत ही जटिल है। और मुझे बस हर शाब्दिक नियमित अभिव्यक्ति के [{startIdx, endIdx}, {startIdx, endIdx}] की एक सरणी चाहिए।

पीएस अगर कोई सोचता है कि एक ही कार्य को इस तरह से पूरा किया जा सकता है जो UglifyJS के माध्यम से बेहतर है, तो आपको सुझाव देने के लिए आपका स्वागत है!

अद्यतन

मैं जानता हूँ कि अगर मैं पार्स संरचना में गहराई तक जाएं, तो हर नियमित अभिव्यक्ति के लिए मैं पा सकते हैं वस्तु:

AST_Token { 
    raw: '/hello/', 
    file: null, 
    comments_before: [], 
    nlb: false, 
    endpos: 17, 
    endcol: 17, 
    endline: 1, 
    pos: 10, 
    col: 10, 
    line: 1, 
    value: /hello/, 
    type: 'regexp' 
} 

मैं यह पता लगाने की कैसे इस तरह के सभी वस्तुओं को खींचने के लिए की जरूरत है पार्सेड संरचना से, इसलिए मैं स्थिति सूचकांक की सूची संकलित कर सकता हूं।

+0

क्या आप कभी भी हमें यह बताने जा रहे हैं कि आप निकाले जाने के बाद इन निकाले गए रेगेक्स या तारों या उनके सूचकांक के साथ क्या करने जा रहे हैं? –

+0

@torazaburo यह नियमित रूप से अभिव्यक्तियों का समर्थन करने के अलावा, एक और पार्सर का हिस्सा है जो पहले से ही समाप्त हो चुका है। मैंने सभी मामलों में से 99% को अलग करने में कामयाब रहा है, लेकिन अंतिम 1% पूर्ण अभिव्यक्ति मूल्यांकन के बिना असंभव प्रतीत होता है। मुझे बस यह जानने की जरूरत है कि कोड की किसी भी पंक्ति के भीतर नियमित अभिव्यक्तियां कहां स्थित हैं। –

उत्तर

1

मुझे यह अंततः उपयोगी link to the UglifyJS author's blog post मिला, जिसने मुझे सही दिशा में इंगित किया। कि ब्लॉग के आधार पर मैं निम्नलिखित करने के लिए अपने गणन कोड को संशोधित करने में सक्षम था:

function enumRegEx(parsed) { 
    var result = []; 
    parsed.walk(new uglify.TreeWalker(function (obj) { 
     if (obj instanceof uglify.AST_RegExp) { 
      result.push({ 
       startIdx: obj.end.col, 
       endIdx: obj.end.endcol 
      }); 
     } 
    })); 
    return result; 
} 

इतना ही नहीं इस बात में कम है और एक ही काम करता है, लेकिन इसके प्रसंस्करण गति लगभग तत्काल है, 10ms के भीतर है, जो पिछले परिणाम डालता है (430 एमएमएस) शर्म की बात है।

अब वह परिणाम है जिसे मैं ढूंढ रहा था! :)

अद्यतन: अंत में, मुझे पता चला कि इस विशेष कार्य के लिए esprima एक बेहतर विकल्प है। यह बहुत तेजी से है और UglifyJS के विपरीत, पूर्ण ES6 समर्थन है।

बहुत ही कार्य Ariya Hidayat से उत्कृष्ट समर्थन करने के लिए esprima के माध्यम से किया है, धन्यवाद:

function parseRegEx(originalCode) { 
    var result = []; 
    esprima.tokenize(originalCode, {loc: true, range: true}, function (obj) { 
     if (obj.type === 'RegularExpression') { 
      result.push({ 
       startIdx: obj.range[0], 
       endIdx: obj.range[1] 
      }); 
     } 
    }); 
    return result; 
} 

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

+0

खुशी है कि आपको एक समाधान मिल गया है। आपको स्वीकार किए गए अपने उत्तर को भी चिह्नित करना चाहिए :) –

+0

@ हेनरिक बार्सेलोस स्टैक ओवरव्लो उत्तर देने के 2 दिनों के लिए अपने उत्तरों को स्वीकार करने की अनुमति नहीं देता है। –

+0

लेकिन एस्प्रिमा को आपके द्वारा पोस्ट किए गए संबंधित प्रश्न में सबसे अच्छा समाधान के रूप में स्पष्ट रूप से सुझाव दिया गया था, और आईआईआरसी ने इसे ओवरकिल के रूप में खारिज कर दिया था। –

0

चूंकि किसी ने अभी तक जवाब नहीं दिया है, इसलिए मैंने काम पर चलने वाले समाधान के साथ आने में कामयाब रहा है, हालांकि शायद सबसे अच्छा नहीं है।

function enumRegEx(parsed) { 
    var result = []; 

    function loop(obj) { 

     if (obj && typeof obj === 'object') { 
      if (obj.used) { 
       return; 
      } else { 
       obj.used = true; 
      } 
      if (obj instanceof Array) { 
       obj.forEach(function (d) { 
        loop(d); 
       }); 
      } else { 
       if (obj instanceof uglify.AST_Node) { 
        for (var v in obj) { 
         loop(obj[v]); 
        } 
       } else { 
        if (obj instanceof uglify.AST_Token) { 
         if (obj.type === 'regexp') { 
          result.push({ 
           startIdx: obj.col, 
           endIdx: obj.endcol 
          }); 
         } 
        } 
       } 
      } 
     } 
    } 

    loop(parsed); 
    return result; 
} 

चीजें मैं इस तरह के दृष्टिकोण के बारे में पसंद नहीं है:

  • मैं एक बहुत बड़ा, 30,000 लाइनों जावास्क्रिप्ट फ़ाइल है, जो 240ms में UglifyJS द्वारा पार्स हो जाता है के खिलाफ यह उपयोग कर रहा हूँ, और फिर मेरा नियमित अभिव्यक्तियों को गिनने के लिए एल्गोरिदम एक और 430ms लेता है। यह काफी अक्षम है।

  • मुझे मूल वस्तुओं को used के साथ संशोधित करना है क्योंकि पार्सेड संरचना आपसी संदर्भों का उपयोग करती है, जो अन्यथा असीमित लूप और कॉल स्टैक से बाहर निकलती हैं। हालांकि मैं इसके बारे में चिंतित नहीं हूं, क्योंकि मैं किसी और चीज़ के लिए पार्स किए गए डेटा का उपयोग नहीं कर रहा हूं।

यदि आप बेहतर दृष्टिकोण जानते हैं - कृपया इसे फेंक दें! इस बिंदु पर मैं अपने गणित के प्रदर्शन में सुधार करने में अधिक रुचि रखता हूं, जो वर्तमान में वास्तविक पार्सिंग की तुलना में काफी धीमी है।

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