Python中的JavaScriptparsing器

至less在C和Java(Mozilla),JavaScript(再次使用Mozilla)和Ruby中都有一个JavaScriptparsing器。 目前有没有Python?

我不需要一个JavaScript解释器本身,只需要一个符合ECMA-262标准的parsing器。

一个快速的谷歌search显示没有即时的答案,所以我问的SO社区。

ANTLR是另一种语言识别工具,它是一种语言工具,它提供了一个框架,用于从包含各种目标语言的动作的语法描述中构build识别器,解释器,编译器和翻译器。

ANTLR网站提供了许多语法,其中包括一个用于JavaScript的语法。

碰巧,有一个Python API可用 – 所以你可以直接从Python调用从语法生成的词法分析器(识别器)(祝你好运)。

现在,至less有一个更好的工具,称为slimit

SlimIt是一个用Python编写的JavaScript缩小器。 它将JavaScript编译成更紧凑的代码,以便下载和运行得更快。

SlimIt还提供了一个库,包括一个JavaScriptparsing器,词法分析器,漂亮的打印机和树访问者。

演示:

想象一下,我们有以下的JavaScript代码:

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

现在我们需要从data对象中获取emailphonename值。

这里的想法是实例化一个slimitparsing器,访问所有节点,筛选所有的任务,并把它们放到字典中:

 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 

它打印:

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

正如pib提到的, pynarcissus是一个用Python编写的Javascript标记器。 它似乎有一些粗糙的优势,但到目前为止,我已经做好了我想完成的工作。

更新:在pynarcissus接受了另一个裂缝,下面是使用PyNarcissus作为系统访问者模式的工作方向。 不幸的是,我现在的客户购买了我的实验的下一个迭代,并决定不公开来源。 下面的代码更干净的版本在这里

 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) 

我已经翻译esprima.js到Python:

https://github.com/PiotrDabkowski/pyjsparser

这是一个手工翻译,所以它非常快,parsingangular.js文件需要大约1秒(所以每秒100K字符)。 它支持整个ECMAScript 5.1和版本6的部分 – 例如箭头函数, constlet

另外,你也可以使用esprima的新版本的自动翻译function ,并且支持整个JavaScript 6!

你可以试试python-spidermonkey它是一个spidermonkey的包装器,它是Mozilla的C实现javascript的代号。