2015-12-30 14 views
7

Tôi có một số mã JavaScript, từ đó tôi cần tìm các chỉ mục bắt đầu + kết thúc của mọi biểu thức chính quy theo nghĩa đen.Liệt kê các cụm từ thông dụng qua UglifyJS

Thông tin đó có thể được trích xuất từ ​​UglifyJS như thế nào?

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

Cấu trúc tôi đang nhận biến số parsed rất phức tạp. Và tất cả những gì tôi cần là một mảng của [{startIdx, endIdx}, {startIdx, endIdx}] của mọi biểu thức chính quy theo nghĩa đen.

P.S. Nếu ai đó nghĩ rằng cùng một công việc có thể được thực hiện theo cách tốt hơn thông qua UglifyJS, bạn được hoan nghênh đề xuất!

CẬP NHẬT

Tôi biết nếu tôi đào sâu hơn vào cấu trúc phân tích cú pháp, sau đó cho tất cả các biểu hiện thường xuyên Tôi có thể tìm đối tượng:

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' 
} 

tôi cần phải tìm ra cách để kéo tất cả các đối tượng như từ cấu trúc được phân tích cú pháp, vì vậy tôi có thể biên dịch danh sách các chỉ mục vị trí.

+0

Bạn có bao giờ nói cho chúng tôi biết bạn sẽ làm gì với các chuỗi hoặc chuỗi trích xuất được trích xuất hoặc chỉ mục của chúng khi bạn đã trích xuất chúng? –

+0

@torazaburo nó là một phần của một trình phân tích cú pháp khác đã hoàn thành, ngoại trừ hỗ trợ các biểu thức chính quy một cách chính xác. Tôi đã quản lý để cô lập khoảng 99% của tất cả các trường hợp, nhưng 1% cuối cùng có vẻ như không thể không đánh giá đầy đủ biểu hiện. Tôi chỉ cần biết các cụm từ thông dụng được đặt trong bất kỳ dòng mã nào. –

Trả lời

1

Tôi nhận được điều này hữu ích cuối cùng link to the UglifyJS author's blog post, đã chỉ cho tôi đúng hướng. Dựa trên blog mà tôi đã có thể sửa đổi mã liệt kê của tôi như sau:

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; 
} 

Không chỉ điều này là ngắn hơn và hoạt động tương tự, nhưng tốc độ xử lý của nó là gần như ngay lập tức, trong vòng 10ms, trong đó đặt kết quả trước (430ms) để xấu hổ.

Bây giờ là kết quả tôi đang tìm kiếm! :)

CẬP NHẬT: Cuối cùng, tôi phát hiện ra rằng đối với nhiệm vụ cụ thể này, esprima là lựa chọn tốt hơn nhiều. Nó nhanh hơn nhiều và có hỗ trợ ES6 đầy đủ, không giống như UglifyJS.

Các nhiệm vụ rất tương tự thực hiện thông qua esprima, nhờ sự hỗ trợ tuyệt vời từ Ariya Hidayat:

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; 
} 

Như bạn có thể thấy, với esprima bạn thậm chí không cần phải phân tích mã, bạn vượt qua trong mã gốc thay vào đó, esprima sẽ chỉ mã hóa, nhanh hơn.

+0

Rất vui vì bạn đã tìm được giải pháp. Bạn cũng nên đánh dấu câu trả lời của riêng mình là được chấp nhận :) –

+0

@HenriqueBarcelos StackOverflow không cho phép chấp nhận câu trả lời của riêng 2 ngày sau khi trả lời. –

+0

Nhưng esprima đã được đề xuất rõ ràng là giải pháp tốt nhất trong một câu hỏi liên quan mà bạn đã đăng và IIRC bạn đã loại bỏ nó là quá mức cần thiết. –

0

Vì chưa có ai trả lời, tôi đã xoay xở để đưa ra giải pháp dựa trên hoạt động, mặc dù có lẽ không phải là giải pháp tốt nhất.

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; 
} 

Những điều tôi không thích về cách tiếp cận như vậy:

  • Tôi đang sử dụng nó chống lại một khổng lồ, 30.000 dòng JavaScript tập tin, mà được phân tích bởi UglifyJS trong 240ms, và sau đó tôi thuật toán mất 430ms khác chỉ để liệt kê các biểu thức chính quy. Điều này có vẻ khá kém hiệu quả.

  • Tôi phải sửa đổi các đối tượng gốc với thuộc tính used vì cấu trúc được phân tích cú pháp sử dụng tham chiếu lẫn nhau, nếu không sẽ dẫn đến vòng lặp vô hạn và hết ngăn xếp cuộc gọi. Mặc dù tôi không lo lắng về điều đó lắm, vì tôi không sử dụng dữ liệu được phân tích cú pháp cho bất kỳ thứ gì khác.

Nếu bạn biết cách tiếp cận tốt hơn - vui lòng ném vào! Tại thời điểm này, tôi chủ yếu quan tâm đến việc cải thiện hiệu suất của điều tra của tôi, hiện đang khá chậm, so với việc phân tích cú pháp thực tế.

Các vấn đề liên quan