轻量级javascript到javascript解析器

时间:2011-07-27 22:09:22

标签: javascript parsing compiler-construction

我如何将轻量级javascript写入javascript解析器。一些简单的东西可以转换一些代码片段。

我想基本上在函数public中创建内部范围对象。

这样的事情

var outer = 42;
window.addEventListener('load', function() {
   var inner = 42;
   function magic() {
       var in_magic = inner + outer;
       console.log(in_magic);
   }
   magic();
}, false);

将编译为

__Scope__.set('outer', 42);
__Scope__.set('console', console);
window.addEventListener('load', constructScopeWrapper(__Scope__, function(__Scope__) {
    __Scope__.set('inner', 42);
    __Scope__.set('magic',constructScopeWrapper(__Scope__, function _magic(__Scope__) {
        __Scope__.set('in_magic', __Scope__.get('inner') + __Scope__.get('outer'));
        __Scope__.get('console').log(__Scope__.get('in_magic'));
    }));
    __Scope__.get('magic')();
}), false);

Demonstation Example

这背后的动机是序列化功能和闭包的状态,并使它们在不同的机器(客户端,服务器,多个服务器)之间保持同步。为此,我需要[[Scope]]

的表示

问题:

  1. 我可以在不编写完整JavaScript的情况下执行此类编译器 - > (略有不同)JavaScript编译器?
  2. 我将如何编写这样的编译器?
  3. 我可以重复使用现有的js - > js编译器?

5 个答案:

答案 0 :(得分:4)

考虑到您想要访问和恢复所有程序状态,我认为您的任务不容易或简短。其中一个问题是您可能必须在计算过程中的任何时刻捕获程序状态,对吧?这意味着所示的例子并不完全正确;在执行该代码之前捕获状态类型(除了您已经预先计算了初始化魔法的总和,并且在代码运行原始JavaScript之前不会发生)。我假设您可能希望在执行期间的任何时刻捕获状态。

您说明问题的方式是,您需要JavaScript中的JavaScript解析器。 我假设您正在想象您现有的JavaScript代码J,包括这样的JavaScript解析器以及生成结果代码G所需的任何其他内容,并且当J启动时它将自身的副本提供给G,制作序列化代码S并以某种方式加载它。 (我认为如果可以处理所有Javascript,G非常大而且很小) 因此,您的JavaScript图像包含J,大G,S,并在启动时执行昂贵的操作(将J添加到G)。

我认为可能更好地为您服务的是一个工具G,它可以离线处理原始JavaScript代码J,并生成可以添加到/替换J执行的程序状态/闭包序列化代码S(以保存和恢复该状态) 。 J + S被发送给永远不会看到G或其执行的客户端。这将S的生成与J的运行时执行分离,节省了客户端执行时间和空间。

在这种情况下,您需要一个能够最简单地生成此类代码的工具。纯JavaScript解析器是一个开始但不太可能;您需要符号表支持才能知道哪个函数代码连接了函数调用F(...),以及哪个变量定义与哪个范围对应于赋值或访问变量V.您可能需要实际修改原始代码J插入可以捕获程序状态的访问点。您可能需要流量分析来找出某些值的去向。在JavaScript中坚持所有这些,缩小了您的解决方案范围。

对于这些任务,您可能会发现program transformation工具很有用。这些工具包含用于感兴趣的语言的解析器,构建表示程序的AST,启用标识符到定义映射(“符号表”)的构造,可以对表示接入点插入的AST进行修改,或者合成AST代表您的演示示例,然后重新生成包含已修改的J和添加S的有效JavaScript代码。 在我所知道的所有程序转换系统中(包括维基百科网站上的所有程序转换系统),没有一个是用JavaScript实现的。

我们的DMS Software Reengineering Toolkit是一个程序转换系统,提供我刚才描述的所有功能。 (是的,它的大而古老;它必须处理真实计算机语言的复杂性)。它有一个JavaScript front end,包含一个完整的ASTs JavaScript解析器,以及从修改或合成的AST重新生成JavaScript代码的机制。 (也是大而古老的;好的东西,古老的+古老的仍然只是古老的)。如果它有用,DMS还为构建控制和数据流分析提供支持。

答案 1 :(得分:3)

我试图寻找要修改的现有解析器。也许您可以调整JSLint / JSHint?

答案 2 :(得分:3)

如果你想要一个简单的界面,你可以试试node-burrito:https://github.com/substack/node-burrito

它使用uglify-js解析器生成AST,然后递归遍历节点。您所要做的就是给出一个测试每个节点的回调。您可以更改需要更改的内容,然后输出生成的代码。

答案 3 :(得分:3)

上面的重写存在问题,你没有将魔法的初始化提升到范围的顶部。

有很多项目可以解析JavaScript。

  1. Crock的Pratt parser适用于适合“好的部分”的JavaScript,而不适合其他JS。
  2. 基于ometa的es-lab解析器,它处理完整的语法,包括Crock的解析器遗漏的很多极端情况。它的表现可能不如Crock's。
  3. narcissus解析器和评估程序。我对此没有多少经验。
  4. 还有一些JavaScript的高质量词法分析器可以让你在令牌级别操作JS。这可能比听起来更难,因为JavaScript不是词法规则,并且如果没有完整的解析,就很难预测分号插入。

    我的es5-lexer是一个精心构建且高效的EcmaScript 5词法分析器,可以对JavaScript进行标记化。它是启发式的,其中JavaScript的语法不是词法规则但启发式非常好,它提供了一种转换令牌流的方法,以便保证解释器以词法分析器解释令牌的方式解释它,这样如果你不相信你的输入,你仍然可以确定,即使根据某些奇怪输入的规范不正确,安全转换的基础解释也是合理的。

答案 4 :(得分:0)

您的问题与JS Opfuscators和JS Compressors所解决的问题一致 - 它们以及您需要能够将JS解析并重新格式化为等效的脚本;

obfuscators here进行了很好的讨论,问题的可能解决方案可能是利用其中一个FOSS版本的解析和生成器部分。

一个标注,您的示例代码没有考虑您想要设置/获取的变量的范围,并且最终将成为您必须解决的问题。

<强>加成

鉴于闭包定义函数的范围问题,您可能不太可能将此问题解决为静态解析问题,因为必须导入/导出闭包外部的范围变量以解析/保存和重新实例化范围。因此,您可能需要深入了解评估引擎本身,并且可能获得V8引擎并对解释器本身进行攻击 - 假设您不需要将其作为通用交叉所有脚本引擎并且您可以将其绑定直到您控制的单个实现。