ECMA标准的各种解析器。
calmjs.parse的Python项目详细描述
calmjs.parse
用于理解的解析器和助手库的集合 ecmascript;一个近乎功能完整的fork of slimit 。cli前端 对于此软件包,将作为 压接 单独发货。
简介
对于任何使用javascript代码的构建系统 结合模块系统,能够理解哪些模块 一组给定的资源要求或提供是最重要的。作为卡尔姆一家 project提供了一个生成和使用这些模块的框架 定义,全面理解 给定的javascript源是给定的。这个目标最初是实现的 使用一个javascript minifier库,它还提供了 使用python lex yacc(即 层 )。
然而,截至2017年年中,有人注意到 slimit 仍在 四年以上的最低维护状态(最近 版本0.8.1于2013年3月26日发布,同时发布了一些严重的 悬而未决的问题在这段时间内一直没有得到解决。 在那段时间里。由于calmjs框架的开发需要 这些问题要尽快纠正,决定 slimit的解析器部分被制作出来。这是为了迎合 当前对calmjs项目的兴趣在那个时刻及时出现。
叉子最初是从另一个纤细的叉子上切下来的(特别是 lelit/slimit ),正如它介绍的那样 聚合了来自不同来源的许多错误修复。确保一 更好的质量控制和保证,一些有问题的变化 那个叉子引来的东西被移走了。此外,还创建了新的测试来 使覆盖率达到最大,在 slimit 跟踪器上报告的问题是 在适用的情况下,记录并正式化为测试用例。最后,语法 已更新规则以确保更好地符合ECMA-262(ES5) 规格。
calmjs.parse的目标是提供一个与slimit类似的api 提供,除了以更具扩展性的方式 正确性检查到位。然而,这导致了一些操作 这可能需要比slimit实现的时间更长,例如 输出打印效果良好。
通过 压接
安装
可以执行以下命令来获取最新的稳定 从pypi安装到 当前的python环境。
$ pip install calmjs.parse
由于此包使用 ply ,因此需要生成优化 它的lexer模块。calmjs.parse的轮分布 不需要这个额外的步骤,因为它包含这些预生成的模块 对于3.11版之前的 ply (当时提供的最新版本 但是源tarball或如果 ply 版本 安装在受支持版本之外,如下所示 注意事项适用。
如果最近发布的 ply 可用,并且环境 升级到那个版本,那些预先生成的模块可能会 不兼容,这可能导致性能下降和/或错误。 可以通过手动优化来实现纠正措施 如果新版本的 calmjs.parse 不可用,或者 ply 可能 如果可能,请降级回3.11版。
安装软件包后,可以对安装进行测试 直接使用
替代安装方法(针对开发人员、高级用户)
目前仍在开发calmjs.parse 功能和错误修复,开发版本可以通过 吉特喜欢这样:
$ pip install git+https://github.com/calmjs/calmjs.parse.git#egg=calmjs.parse
或者,可以直接克隆git存储库并执行 python setup.py在源代码的根目录中开发 目录。
可能需要对平台和 不使用utf8作为默认编码的系统。
手动优化
由于lex和yacc需要生成符号表,因此 优化性能就是缓存结果。对于 层 ,这是 使用自动生成的模块完成。但是,生成的文件是 用版本号标记,因为结果可能特定于 已安装版本的 层 。在calmjs.parse中 它们是特定于 ply 和主要python版本的名称 版本,因为两者都会导致 自动生成模块的输出和期望。
通常,此优化过程是自动的,并且是正确的 将生成符号表,但在某些情况下 失败,因此为此原因 calmjs.parse 提供一个helper模块 可选择调用以确保 编码用于生成该文件。其他可能的原因 必须允许系统管理员这样做 用户,因为他们可能没有该级别的写入权限。
要从shell执行优化器,提供的帮助程序脚本可以 像这样使用:
$ python -m calmjs.parse.parsers.optimize
如果出现警告,警告令牌已定义但未使用,则它们 可能会被安全地忽略。
此步骤通常对于安装此软件包的用户是可选的 从pypi通过python轮,提供了 安装部分已处理。
测试安装
为了确保 calmjs.parse 安装正常工作, 内置测试套件可以通过以下方式执行:
$ python -m unittest calmjs.parse.tests.make_suite
如果出现故障,请在问题跟踪程序中提交一个问题 回溯,和/或方法of安装。请也包括 有关环境的适用信息,例如 这个软件,python版本,操作系统环境 已安装的 ply 版本,以及与 手头的问题。
用法
由于这是一个解析器库,因此不提供可执行的shell命令。 但是,在顶层提供了一个helper可调用对象 立即访问解析功能。可以这样使用:
>>> fromcalmjs.parseimportes5>>> program_source=u'''
... // simple program
... var main = function(greet) {
... var hello = "hello " + greet;
... return hello;
... };
... console.log(main('world'));
... '''>>> program=es5(program_source)>>> # for a simple repr-like nested view of the ast>>> program# equivalent to repr(program)<ES5Program @3:1 ?children=[
<VarStatement @3:1 ?children=[
<VarDecl @3:5 identifier=<Identifier ...>, initializer=<FuncExpr ...>>
]>,
<ExprStatement @7:1 expr=<FunctionCall @7:1 args=<Arguments ...>,
identifier=<DotAccessor ...>>>
]>
>>> # automatic reconstruction of ast into source, without having to>>> # call something like `.to_ecma()`>>> print(program)# equivalent to str(program)var main = function(greet) {
var hello = "hello " + greet;
return hello;
};
console.log(main('world'));
>>>
请注意缩进的变化,因为默认打印机有自己的缩进 缩进方案。如果需要注释,可以调用解析器 将 与u comments=true一起使用
>>> program_wc=es5(program_source,with_comments=True)>>> print(program_wc)// simple program
var main = function(greet) {
var hello = "hello " + greet;
return hello;
};
console.log(main('world'));
>>>
还需要注意的是,捕获注释有一些限制 记录在限制部分。
解析器类在calmjs.parse.parsers下组织。 模块,每种语言都在各自的模块下。一 在 calmjs.parse.lexers 模块。目前,只有ES5支持 实施。
精美/微型打印
还有一组漂亮的打印辅助程序,用于将ast返回 变成一根绳子。它们可用作函数或类构造函数, 并通过组合在 calmjs.parse.unparsers和相关模块。
有一个默认的短手助手,用于旋转先前生成的 AST返回到字符串中,可以使用 参数,例如用于缩进的字符:(注意 通过打印隐式调用 以前是通过这个实现的。
>>> fromcalmjs.parse.unparsers.es5importpretty_print>>> print(pretty_print(program,indent_str=' '))var main = function(greet) {
var hello = "hello " + greet;
return hello;
};
console.log(main('world'));
>>>
也有一个打印没有任何不需要的空白,作品 作为源代码缩小器:
>>> fromcalmjs.parse.unparsers.es5importminify_print>>> print(minify_print(program))var main=function(greet){var hello="hello "+greet;return hello;};...
>>> print(minify_print(program,obfuscate=True,obfuscate_globals=True))var a=function(b){var a="hello "+b;return a;};console.log(a('world'));
注意,在第二个示例中, obfuscate_globals 选项是 仅用于演示全局范围上的源代码混淆, 而且这通常不是一个应该在生产上启用的选项 打算由其他包(其他源)重用的库代码 引用原始未模糊的名称将无法执行此操作。
或者,可以使用 以与上述基本对象相同的名称提供的属性 最初是导入的。相关关键字参数将被转移 到相应的底层函数,例如:
>>> # pretty print without comments being parsed>>> print(es5.pretty_print(program_source))var main = function(greet) {
var hello = "hello " + greet;
return hello;
};
console.log(main('world'));
>>> # pretty print with comments parsed>>> print(es5.pretty_print(program_source,with_comments=True))// simple program
var main = function(greet) {
var hello = "hello " + greet;
return hello;
};
console.log(main('world'));
>>> # minify print>>> print(es5.minify_print(program_source,obfuscate=True))var main=function(b){var a="hello "+b;return a;};console.log(main('world'));
源映射生成
对于源映射的生成,较低级别的unparser实例可以 通过打印机工厂功能之一构造。经过 在ast节点中,将生成生成包含 生成的文本片段,以及其他有助于 生成源映射。有来自 可以像这样使用calmjs.parse.sourcemap模块来编写 将源代码重新生成到某个流,同时处理 结果转换为源映射文件。例如:
$ pip install calmjs.parse
0
同样,这对minify打印机也同样有效,它提供 使用不需要的空白创建缩小的输出的能力 删除并用尽可能短的值模糊标识符。
注意,在前面的例子中,write中的第二个返回值 方法未使用,并且传入了自定义值。这是 只是因为 程序是如何从字符串生成的,因此 sourcepath属性没有为 在生成的源映射中填充 "sources" 列表。对于 下面的示例为程序上的该属性指定一个值 直接。
$ pip install calmjs.parse
1
用于处理命名的treams(即打开的文件,或 流对象,如分配有name属性的 io.stringio 由 io 模块的 read 和 write 函数提供。 下面的示例演示如何使用函数从 流式处理并将相关项写回write only 溪流:
$ pip install calmjs.parse
2
用于将多个源简单地连接到一个文件中,以及 内联源映射(即,其中sourcemappingurl是 json字符串的base64编码),可以执行以下操作:
$ pip install calmjs.parse
3
在本例中, io.write 函数提供了 unparser,一个生成器表达式,它将从 两个源文件,然后是target和sourcemap参数 是相同的,它强制源映射生成器生成 Base64编码。
请注意,如果向小型打印机提供多个AST, 全局变量被混淆后,生成的脚本将具有 当解组完成时,被后面的全局名称弄乱的全局名称 分别通过 io.write 函数。
高级用法
低级拆开API
当然,前面演示的打印机是使用 底层的unparser类,它反过来连接了walk 在Walker模块中找到的函数和Dispatcher类。步行 函数使用Dispatcher的一个实例遍历AST节点 类,它为特定的 提供的ast节点的类型,以及相关的处理程序。这些 可以使用现有的规则提供程序函数设置处理程序。为了 例如,一个打印机,用于在维护 es5 ast输出的缩进可以这样构造:
$ pip install calmjs.parse
4
每个规则(函数)都有特定的选项,使用 特定的关键字参数和详细信息分别记录在它们各自的 文档字符串。
树木行走
ast(抽象语法树)泛型walker类在 合适的命名模块calmjs.parse.walkers。两个默认walker 提供类。其中一个是reprwalker类 之前演示过。另一个是walker类 提供AST树的泛型树行走方法的集合 节点。下面是关于如何提取所有 给定脚本文件中的对象分配:
$ pip install calmjs.parse
5
更多细节和示例用法可从 在模块中找到docstrings。
限制
当前的评论可能不完整
由于lexer/parser的实现以及ast
节点类型已经实现,在
如果启用,则可能会公开注释。目前,这种限制是存在的
对于由使用多个
lexer令牌一次-只有在第一个令牌之前的注释将是
已捕获,并丢弃所有剩余评论。
例如,这个限制意味着
else
之前的任何注释
标记将被忽略(因为注释将由
提供,如果
token),作为
的生产规则,如果
节点同时使用这两个
令牌和实现的节点只为
评论。同样,在三元组中
:
标记之前的任何注释
语句也将被丢弃,因为这是使用的第二个令牌
根据产生
条件节点的产生式规则。
故障排除
语法分析器类的实例化失败,出现unicodeencodeerror
对于未将utf8配置为默认值的平台或系统 编码时,在构造 分析器实例。例如:
$ pip install calmjs.parse
6
提供了一个解决方案帮助程序脚本,其执行方式如下:
$ python -m calmjs.parse.parsers.optimize
有关此主题的更多详细信息,请参见手动优化。 本文档的一节。
慢性能
由于这个程序基本上完全分解成非常小的函数, 与其他方法相比,这将导致严重的性能损失 由于函数调用是最昂贵的 python中的操作。有可能进一步优化 通过组合所有 但是,解析的生成器对每个asttype节点类型都起作用 这可能需要令牌和布局函数都没有 具有名称冲突的参数,新函数将接受 一次就解决了这些争论。
贡献
- 问题跟踪器: https://github.com/calmjs/calmjs.parse/issues
- 源代码:https://github.com/calmjs/calmjs.parse" rel="nofollow">https://github.com/calmjs/calmjs.parse
法律
calmjs.parse包版权所有(c)2017奥克兰生物工程 奥克兰大学研究所。calmjs.parse包是 根据麻省理工学院许可证(特别是外籍人士许可证)进行许可,其中 与slimit软件包发布时使用的许可证相同。
lexer、解析器和其他类型定义部分是 最初从 slimit 包导入; slimit 是版权所有(C) 拉斯兰·斯皮瓦克。
CALMJS项目版权所有(c)2017奥克兰生物工程 奥克兰大学研究所。