Парсер JavaScript в Python
Существует JavaScript-парсер, по крайней мере, на C и Java (Mozilla), в JavaScript (Mozilla снова) и Ruby. Есть ли в настоящее время для Python?
Мне не нужен интерпретатор JavaScript, как таковой, только парсер, соответствующий стандартам ECMA-262.
Быстрый поиск по Google не выявил немедленных ответов, поэтому я прошу сообщество SO.
Ответы
Ответ 1
ANTLR, еще один инструмент для распознавания языков - это инструмент языка, который обеспечивает основу для создания распознавателей, интерпретаторов, компиляторов и переводчики из грамматических описаний, содержащие действия на разных целевых языках.
ANTLR содержит много грамматик, в том числе one для JavaScript.
Как это происходит, существует Python API, поэтому вы можете вызывать лексер (распознаватель), сгенерированный из грамматики, непосредственно из Python (удачи).
Ответ 2
В настоящее время существует хотя бы один лучший инструмент, называемый slimit
:
SlimIt - это JavaScript minifier, написанный на Python. Он компилирует JavaScript в более компактный код, чтобы он загружал и запускал быстрее.
SlimIt также предоставляет библиотеку, содержащую парсер JavaScript, лексер, красивый принтер и посетитель дерева.
Демо:
Представьте, что у нас есть следующий код javascript:
$.ajax({
type: "POST",
url: 'http://www.example.com',
data: {
email: '[email protected]',
phone: '9999999999',
name: 'XYZ'
}
});
И теперь нам нужно получить значения email
, phone
и name
от объекта data
.
Идея здесь заключалась бы в создании экземпляра парсера slimit
, посещении всех узлов, фильтрации всех назначений и перевода их в словарь:
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
Он печатает:
{'name': "'XYZ'",
'url': "'http://www.example.com'",
'type': '"POST"',
'phone': "'9999999999'",
'data': '',
'email': "'[email protected]'"}
Ответ 3
Как упоминалось в pib, pynarcissus является токенизатором Javascript, написанным на Python. Кажется, что у него есть некоторые грубые грани, но до сих пор хорошо работает для того, чего я хочу достичь.
Обновлено: Взял еще одну трещину на pynarcissus, а ниже - рабочее направление для использования PyNarcissus в шаблоне посетителя, таком как система. К сожалению, мой текущий клиент купил следующую итерацию моих экспериментов и решил не делать это публичным источником. Более чистая версия приведенного ниже кода находится на gist здесь
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)
Ответ 4
Я перевел esprima.js на Python:
https://github.com/PiotrDabkowski/pyjsparser
Это ручной перевод, поэтому он очень быстрый, занимает около 1 секунды для анализа angular.js
файла (так 100 тыс. символов в секунду). Он поддерживает весь ECMAScript 5.1 и части версии 6 - например, функции Arrow, const
, let
.
В качестве альтернативы вы можете использовать автоматический перевод более новой версии esprima на python, который отлично работает и поддерживает весь JavaScript 6!
Ответ 5
Вы можете попробовать python-spidermonkey
Это оболочка над spidermonkey, которая является кодовым именем для реализации javascript для Mozilla C.