2008-12-24 22 views
42

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

No necesito un intérprete de JavaScript, per se, solo un analizador que cumpla 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.

Respuesta

16

ANTLR, otra herramienta para el reconocimiento de idioma, es una herramienta de lenguaje que proporciona un marco para construir reconocedores, compiladores, intérpretes, traductores y de las descripciones gramaticales que contienen acciones en una variedad de idiomas de destino.

El sitio ANTLR proporciona muchas gramáticas, incluyendo one for JavaScript.

Ocurre que hay un Python API disponible, por lo que puede llamar al lexer (reconocedor) generado desde la gramática directamente desde Python (buena suerte).

+0

esto podría ser exactamente lo que necesito, ya que de hecho quiero extender la gramática de JavaScript estándar. ¡Gracias! – Claudiu

+23

ambas gramáticas ecmascript/javascript para antlr3 están rotas y no se han mantenido. es un arenque rojo. –

4

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

+1

Desafortunadamente spidermonkey está muerto río arriba. –

11

Como se menciona pib, pynarcissus es un tokenizador Javascript escrito en Python. Parece tener algunas asperezas, pero hasta ahora ha funcionado bien para lo que quiero lograr.

Actualizado: Se produjo otra grieta en pynarcissus y debajo hay una dirección de trabajo para utilizar PyNarcissus en un patrón de visitante como el sistema. Lamentablemente, mi cliente actual compró la próxima iteración de mis experimentos y decidió no convertirlo en fuente pública. Una versión más limpia del código siguiente es el quid 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

Esto no puede emitir JavaScript desde un AST analizado, ¿o sí? Quería modificar el AST y emitir nuevo JavaScript, pero no parece que esto pueda hacer eso. – gsingh2011

+0

@ gsingh2011 No, luchó un poco con el análisis, por lo que lo contrario es mucho más allá de sus capacidades. – David

30

Hoy en día, hay por lo menos una herramienta mejor, llama slimit:

SLIMIT es un JavaScript Minifier escrito en Python. Compila JavaScript en un código más compacto para que se descargue y ejecute más rápido.

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

Demostración:

Imaginemos que tenemos el siguiente código JavaScript:

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

Y ahora tenemos que conseguir email, phone y name valores del objeto data.

La idea sería crear una instancia de un analizador slimit, visitar todos los nodos, filtrar todas las asignaciones y ponerlos 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: '[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 

Imprime:

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

¡Esto es simplemente genial! También puede acceder a cada valor como un diccionario, como: 'print fields ['url']' – aesede

7

He traducido Esprima .js a Python:

https://github.com/PiotrDabkowski/pyjsparser

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

Alternativamente, usted puede usar automated translation de la versión más reciente de esprima a python que funciona muy bien y admite JavaScript completo 6!

Cuestiones relacionadas