2013-02-06 27 views
13

我是doctest的作者,快速和脏doctests为JavaScript和CoffeeScript。我想通过使用JavaScript解析器而不是正则表达式来定位注释,从而减少库的脏问题。替换JavaScript中的评论AST与从评论的内容派生的子树

我想使用EsprimaAcorn做到以下几点:

  1. 创建AST
  2. 走的树,并为每个注释节点:
    1. 创建一个从评论的AST节点的文本
    2. 用此子树替换主树中的注释节点

输入:

!function() { 

    // > toUsername("Jesper Nøhr") 
    // "jespernhr" 
    var toUsername = function(text) { 
    return ('' + text).replace(/\W/g, '').toLowerCase() 
    } 

}() 

输出:

!function() { 

    doctest.input(function() { 
    return toUsername("Jesper Nøhr") 
    }); 
    doctest.output(4, function() { 
    return "jespernhr" 
    }); 
    var toUsername = function(text) { 
    return ('' + text).replace(/\W/g, '').toLowerCase() 
    } 

}() 

我不知道如何做到这一点。 Acorn提供了一个walker,它接受一个节点类型和一个函数,并在每次遇到指定类型的节点时遍历调用该函数的树。这似乎很有前途,但不适用于评论。

与Esprima我可以使用esprima.parse(input, {comment: true, loc: true}).comments来获得评论,但我不知道如何更新树。

+1

你试过[JSShaper](https://github.com/olov/jsshaper)吗? –

+0

我不知道那个项目。看起来很有希望。 – davidchambers

回答

3

大多数AST产生的解析器会丢弃评论。我不知道Esprima或Acorn做了什么,但这可能是问题所在。

....其实,Esprima列出注释捕获作为当前的错误: http://code.google.com/p/esprima/issues/detail?id=197

... Acorn的代码是正确的,在GitHub上。它似乎也放弃了评论。

因此,看起来您可以修复任何一个解析器来捕获注释,此时您的任务应该很简单,或者您被困住了。

我们的DMS Software Reengineering Toolkit拥有可在树中捕获注释的JavaScript解析器。它也有语言substring解析器,可用于将注释文本解析为任何类型注释表示的JavaScript AST(例如,函数声明,表达式,变量声明等),以及支持机制新的AST进入主树。如果您要操纵AST,这个子字符串功能可能很重要:大多数解析器不会解析任意语言片段,它们仅用于解析“整个程序”。对于DMS,没有要替换的注释节点;有与AST节点相关的评论,所以嫁接过程比“替换评论节点”有点棘手。还是很容易的。

我会观察到大多数解析器(包括这些)通过使用或应用正则表达式的等价物来读取源代码并将其分解为令牌。因此,如果您已经在使用这些来查找评论(这意味着使用它们来查找*非*评论以便丢弃,例如,您需要识别包含类似注释的文本的字符串文本并忽略它们),您所做的和解析器无论如何都会按照找到注释。如果你想要做的只是用它们的内容来替换它们,用源码流/注释前缀/ suffix/* * /剥离来回显源码流将完全按照你想要的来做,所以这些解析机制看起来似乎是矫枉过正的。

2

您已经可以用Esprima达到你想要的东西:

  1. 解析代码,得到的意见(如数组)。
  2. 迭代评论,看看你是否都感兴趣。
  3. 如果你需要转换评论,请注意它的范围。收集所有转换。
  4. 先应用变换,以避免范围偏移。

诀窍是这里没有改变AST。只需直接应用文本更改,就好像您正在对源字符串进行典型搜索替换一样。因为替换的位置可能会发生变化,所以您需要收集所有内容,然后从最后一个位置开始。有关如何进行此类转换的示例,请参阅我的博客帖子"From double-quotes to single-quotes"(它涉及字符串引号,但原理保持不变)。

最后但并非最不重要的一点,您可能需要使用一个稍高级别的实用程序,如Rocambole