2008-12-24 41 views
42

Có một trình phân tích cú pháp JavaScript ít nhất trong C và Java (Mozilla), trong JavaScript (Mozilla một lần nữa) và Ruby. Có bất kỳ hiện tại có cho Python?Trình phân tích cú pháp JavaScript trong Python

Tôi không cần trình thông dịch JavaScript, chỉ cần một trình phân tích cú pháp đạt tiêu chuẩn ECMA-262.

Tìm kiếm nhanh trên google không tiết lộ câu trả lời ngay lập tức, vì vậy tôi hỏi cộng đồng SO.

Trả lời

16

ANTLR, ANother Tool for Language Recognition, là công cụ ngôn ngữ cung cấp khuôn khổ để xây dựng trình nhận dạng, thông dịch viên, trình biên dịch và dịch từ các mô tả ngữ pháp có chứa nhiều ngôn ngữ đích.

Trang web ANTLR cung cấp nhiều ngữ pháp, bao gồm one for JavaScript.

Khi điều đó xảy ra, có sẵn Python API - vì vậy bạn có thể gọi lexer (bộ nhận dạng) được tạo từ ngữ pháp trực tiếp từ Python (chúc may mắn).

+0

điều này có thể chính xác những gì tôi cần, vì tôi thực sự muốn mở rộng ngữ pháp javascript chuẩn. cảm ơn! – Claudiu

+23

cả hai ngôn ngữ ecmascript/javascript cho antlr3 đều bị hỏng và không bị mờ. đó là cá trích đỏ. –

4

Bạn có thể thử python-spidermonkey Đó là trình bao bọc trên spidermonkey là tên mã cho việc triển khai javascript của Mozilla.

+1

Thật không may spidermonkey đã chết ngược dòng. –

11

Như đã đề cập, pynarcissus là trình mã thông báo Javascript được viết bằng Python. Nó dường như có một số cạnh thô nhưng cho đến nay đã làm việc tốt cho những gì tôi muốn thực hiện.

Đã cập nhật: Tìm một vết nứt khác tại pynarcissus và dưới đây là hướng làm việc để sử dụng PyNarcissus trong mẫu khách truy cập như hệ thống. Thật không may, khách hàng hiện tại của tôi đã mua lần lặp tiếp theo của các thử nghiệm của tôi và đã quyết định không biến nó thành nguồn công khai. Một phiên bản sạch của mã dưới đây là trên ý chính here

from pynarcissus import jsparser 
from collections import defaultdict 

class Visitor(object): 

    CHILD_ATTRS = ['thenPart', 'elsePart', 'expression', 'body', 'initializer'] 

def __init__(self, filepath): 
    self.filepath = filepath 
    #List of functions by line # and set of names 
    self.functions = defaultdict(set) 
    with open(filepath) as myFile: 
     self.source = myFile.read() 

    self.root = jsparser.parse(self.source, self.filepath) 
    self.visit(self.root) 


def look4Childen(self, node): 
    for attr in self.CHILD_ATTRS: 
     child = getattr(node, attr, None) 
     if child: 
      self.visit(child) 

def visit_NOOP(self, node): 
    pass 

def visit_FUNCTION(self, node): 
    # Named functions 
    if node.type == "FUNCTION" and getattr(node, "name", None): 
     print str(node.lineno) + " | function " + node.name + " | " + self.source[node.start:node.end] 


def visit_IDENTIFIER(self, node): 
    # Anonymous functions declared with var name = function() {}; 
    try: 
     if node.type == "IDENTIFIER" and hasattr(node, "initializer") and node.initializer.type == "FUNCTION": 
      print str(node.lineno) + " | function " + node.name + " | " + self.source[node.start:node.initializer.end] 
    except Exception as e: 
     pass 

def visit_PROPERTY_INIT(self, node): 

    # Anonymous functions declared as a property of an object 
    try: 
     if node.type == "PROPERTY_INIT" and node[1].type == "FUNCTION": 
      print str(node.lineno) + " | function " + node[0].value + " | " + self.source[node.start:node[1].end] 
    except Exception as e: 
     pass 


def visit(self, root): 

    call = lambda n: getattr(self, "visit_%s" % n.type, self.visit_NOOP)(n) 
    call(root) 
    self.look4Childen(root) 
    for node in root: 
     self.visit(node) 

filepath = r"C:\Users\dward\Dropbox\juggernaut2\juggernaut\parser\test\data\jasmine.js" 
outerspace = Visitor(filepath) 
+0

Điều này không thể phát ra JavaScript từ một AST được phân tích cú pháp, có thể không? Tôi muốn sửa đổi AST và phát ra JavaScript mới, nhưng dường như nó không làm được điều đó. – gsingh2011

+0

@ gsingh2011 Không, nó khá khó khăn với việc phân tích cú pháp để làm theo cách khác là vượt qua khả năng của nó. – David

30

Ngày nay, có ít nhất một tốt hơn công cụ, gọi là slimit:

SlimIt là một Javascript minifier viết bằng Python. Nó biên dịch JavaScript thành mã nhỏ gọn hơn để nó tải xuống và chạy nhanh hơn .

SlimIt cũng cung cấp thư viện bao gồm trình phân tích cú pháp JavaScript, lexer, máy in đẹp và khách truy cập cây.

Demo:

Hãy tưởng tượng chúng ta có mã javascript sau:

$.ajax({ 
    type: "POST", 
    url: 'http://www.example.com', 
    data: { 
     email: '[email protected]', 
     phone: '9999999999', 
     name: 'XYZ' 
    } 
}); 

Và bây giờ chúng ta cần phải nhận được email, phonename giá trị từ đối tượng data.

Ý tưởng ở đây sẽ được khởi tạo một phân tích cú pháp slimit, hãy truy cập tất cả các nút, lọc tất cả các bài tập và đặt chúng vào từ điển:

from slimit import ast 
from slimit.parser import Parser 
from slimit.visitors import nodevisitor 


data = """ 
$.ajax({ 
    type: "POST", 
    url: 'http://www.example.com', 
    data: { 
     email: '[email protected]', 
     phone: '9999999999', 
     name: 'XYZ' 
    } 
}); 
""" 

parser = Parser() 
tree = parser.parse(data) 
fields = {getattr(node.left, 'value', ''): getattr(node.right, 'value', '') 
      for node in nodevisitor.visit(tree) 
      if isinstance(node, ast.Assign)} 

print fields 

It in:

{'name': "'XYZ'", 
'url': "'http://www.example.com'", 
'type': '"POST"', 
'phone': "'9999999999'", 
'data': '', 
'email': "'[email protected]'"} 
+1

Điều này thật tuyệt! Ngoài ra, bạn có thể truy cập từng giá trị dưới dạng Từ điển, như: 'trường in ['url']' – aesede

7

Tôi đã dịch esprima .js sang Python:

https://github.com/PiotrDabkowski/pyjsparser

Đó là một bản dịch thủ công nên rất nhanh, mất khoảng 1 giây để phân tích cú pháp angular.js tệp (do đó, 100k ký tự mỗi giây). Nó hỗ trợ toàn bộ ECMAScript 5.1 và các phần của phiên bản 6 - ví dụ các hàm Arrow, const, let.

Hoặc bạn có thể sử dụng automated translation phiên bản mới hơn của esprima để python hoạt động tốt và hỗ trợ toàn bộ JavaScript 6!

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