Parser JavaScript w Pythonie [zamknięty]

Istnieje parser JavaScript przynajmniej w C i Javie (Mozilla), w JavaScript (znowu Mozilla) i Ruby. Czy istnieje obecnie coś dla Pythona?

Nie potrzebuję interpretera JavaScript, per se, tylko parsera zgodnego ze standardami ECMA-262.

Szybkie wyszukiwanie w google nie ujawniło żadnych natychmiastowych odpowiedzi, więc pytam społeczność SO.

Author: Yangshun Tay, 2008-12-24

5 answers

ANTLR, inne narzędzie do rozpoznawania języków, jest narzędziem językowym, które zapewnia ramy do konstruowania rozpoznawaczy, tłumaczy, kompilatorów i tłumaczy z opisów gramatycznych zawierających działania w różnych językach docelowych.

Strona ANTLR zawiera wiele gramatyk , w tym jeden dla JavaScript .

Tak się składa, że jest dostępne API Pythona - można więc wywołać generowany lexer (rozpoznawacz) z gramatyki bezpośrednio z Pythona (powodzenia).

 17
Author: gimel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-29 07:15:54

Obecnie istnieje co najmniej jedno lepsze narzędzie, zwane slimit:

SlimIt to minifier JavaScript napisany w Pythonie. Kompiluje JavaScript w bardziej kompaktowy kod, dzięki czemu pobiera i uruchamia szybciej.

SlimIt zapewnia również bibliotekę, która zawiera Parser JavaScript, lexer, Ładna drukarka i gość z drzewa.

Demo:

Wyobraź sobie, że mamy następujący kod javascript:

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

And now We need to get email, phone i name wartości z obiektu data.

Ideą byłoby utworzenie instancji parsera slimit, odwiedzenie wszystkich węzłów, filtrowanie wszystkich przypisań i umieszczenie ich w słowniku:

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

Drukuje:

{'name': "'XYZ'", 
 'url': "'http://www.example.com'", 
 'type': '"POST"', 
 'phone': "'9999999999'", 
 'data': '', 
 'email': "'[email protected]'"}
 32
Author: alecxe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-04 05:09:39

Jak wspomniano pib, pynarcissus jest tokenizerem Javascript napisanym w Pythonie. Wydaje się, że ma kilka szorstkich krawędzi, ale do tej pory działa dobrze na to, co chcę osiągnąć.

Aktualizacja: zrobiłem kolejny crack na pynarcissus i poniżej jest kierunek pracy dla korzystania z PyNarcissus w systemie wzorca odwiedzającego. Niestety mój obecny klient kupił kolejną iterację moich eksperymentów i postanowił nie podawać jej do wiadomości publicznej. Czystszą wersją poniższego kodu jest na gist Tutaj

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)
 11
Author: David,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-15 08:48:26

Przetłumaczyłem esprimę.js do Pythona:

Https://github.com/PiotrDabkowski/pyjsparser

Jest to tłumaczenie ręczne, więc jego bardzo szybkie, zajmuje około 1 sekundy, aby przetworzyć plik angular.js (więc 100k znaków na sekundę). Obsługuje cały ECMAScript 5.1 oraz części wersji 6 - na przykład funkcje strzałek, const, let.

Alternatywnie możesz użyć automatycznego tłumaczenia nowszej wersji esprimy do Pythona, który działa świetnie i obsługuje całe JavaScript 6!

 7
Author: Piotr Dabkowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-10 22:59:41

Możesz spróbować python-spidermonkey Jest to wrapper nad spidermonkey, który jest nazwą kodową dla implementacji JavaScript w języku C Mozilli.

 4
Author: swamy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-24 09:39:05