Analizador de JavaScript en Python

Hay un analizador de JavaScript al menos en C y Java (Mozilla), en JavaScript (otra vez Mozilla) y Ruby. ¿Hay alguna actualmente por ahí para Python?

No necesito un intérprete de JavaScript, per se, solo un analizador que cumple con los estándares ECMA-262.

Una búsqueda rápida en Google no reveló respuestas inmediatas, así que le pregunto a la comunidad SO.

Related of "Analizador de JavaScript en Python"

ANTLR , otra herramienta para el reconocimiento de idiomas, es una herramienta de lenguaje que proporciona un marco para construir reconocedores, intérpretes, comstackdores y traductores a partir de descripciones gtwigticales que contienen acciones en una variedad de idiomas de destino.

El sitio de ANTLR proporciona muchas gramáticas, incluida una para JavaScript .

A medida que sucede, hay una API de Python disponible, por lo que puede llamar al lexer (reconocedor) generado desde la gramática directamente desde Python (buena suerte).

Hoy en día, hay al menos una herramienta mejor, llamada slimit :

SlimIt es un minificador de JavaScript escrito en Python. Comstack JavaScript en un código más compacto para que se descargue y se ejecute más rápido.

SlimIt también proporciona una biblioteca que incluye un analizador de JavaScript, un lexer, una impresora bonita y un visitante de árbol.

Manifestación:

Imagina que tenemos el siguiente código javascript:

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

Y ahora necesitamos obtener valores de email , phone y name del objeto de data .

La idea aquí sería crear una instancia de un analizador slimit , visitar todos los nodos, filtrar todas las asignaciones y colocarlas en el diccionario:

 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: 'abc@g.com', 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 

Se imprime:

 {'name': "'XYZ'", 'url': "'http://www.example.com'", 'type': '"POST"', 'phone': "'9999999999'", 'data': '', 'email': "'abc@g.com'"} 

Como mencionó pib, pynarcissus es un tokenizador de Javascript escrito en Python. Parece tener algunas ventajas, pero hasta ahora ha funcionado bien para lo que quiero lograr.

Actualizado: Tomé otra grieta en Pynarcissus y debajo está una dirección de trabajo para usar PyNarcissus en un sistema de patrón de visitantes. Desafortunadamente, mi cliente actual compró la siguiente iteración de mis experimentos y decidió no hacerlo público. Una versión más limpia del código a continuación está aquí en general.

 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) 

He traducido esprima.js a Python:

https://github.com/PiotrDabkowski/pyjsparser

Es una traducción manual, por lo que es muy rápido, toma aproximadamente 1 segundo analizar el archivo angular.js (por lo tanto, 100 k caracteres por segundo). Admite ECMAScript 5.1 completo y partes de la versión 6, por ejemplo, las funciones de flecha, const , let .

Alternativamente, puede utilizar la traducción automática de la versión más reciente de esprima a python, que funciona muy bien y es compatible con todo JavaScript 6!

Puede probar python-spidermonkey. Es un contenedor sobre spidermonkey que es el nombre clave para la implementación de JavaScript de Mozilla C.