至少在C和Java(Mozilla),JavaScript(再次使用Mozilla)和Ruby中都有一个JavaScript解析器.目前有没有针对Python的?
我本身不需要JavaScript解释器,只需要符合ECMA-262标准的解析器.
一个快速的谷歌搜索显示没有立即答案,所以我问SO社区.
如今,至少有一种更好的工具,称为slimit
:
SlimIt是一个用Python编写的JavaScript缩小器.它将JavaScript编译成更紧凑的代码,以便下载和运行更快.
SlimIt还提供了一个库,其中包括JavaScript解析器,词法分析器,漂亮的打印机和树访问者.
演示:
想象一下,我们有以下javascript代码:
$.ajax({ type: "POST", url: 'http://www.example.com', data: { email: 'abc@g.com', 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: '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'"}
ANTLR,另一种语言识别工具,是一种语言工具,它提供了一个框架,用于从包含各种目标语言中的动作的语法描述构建识别器,解释器,编译器和翻译器.
该ANTLR站点提供了许多语法,包括一个针对JavaScript.
实际上,有一个Python API可用 - 所以你可以直接从Python调用从语法生成的词法分析器(识别器)(祝你好运).
正如pib所提到的,pynarcissus是一个用Python编写的Javascript tokenizer.它似乎有一些粗糙的边缘,但到目前为止我一直在努力完成我想要完成的任务.
更新:在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
这是一个手动翻译,所以它非常快,解析angular.js
文件大约需要1秒钟(每秒100k字符).它支持整个ECMAScript 5.1和版本6的部分 - 例如Arrow函数const
,let
.
或者你可以使用自动翻译 esprima的新版本到python,它运行良好并支持整个JavaScript 6!