13

我是doctest的作者,它是 JavaScript 和 CoffeeScript 的快速而肮脏的doctests。我想通过使用 JavaScript 解析器而不是正则表达式来定位注释,从而使库不那么脏。

我想使用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用来获取评论,但我不确定如何更新树。

4

2 回答 2

3

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

.... 事实上,Esprima 将评论捕获列为当前错误: http ://code.google.com/p/esprima/issues/detail?id=197

... Acorn 的代码就在 GitHub 中。它似乎也抛弃了评论。

因此,看起来您可以先修复任一解析器以捕获评论,此时您的任务应该很简单,或者您被卡住了。

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

我将观察到大多数解析器(包括这些解析器)通过使用或应用正则表达式的等价物来读取源代码并将其分解为标记。因此,如果您已经在使用它们来定位注释(这意味着使用它们来定位 *non*comments 以丢弃,例如,您需要识别包含类似注释文本的字符串文字并忽略它们),您就是在查找注释方面,解析器无论如何都会做得很好。如果你想要做的只是用它们的内容完全替换它们,那么用注释前缀/后缀 /* */ 剥离的源流回显显然完全符合你的要求,所以所有这些解析机制似乎都是矫枉过正。

于 2013-02-08T09:51:31.970 回答
2

您已经可以使用 Esprima 来实现您想要的:

  1. 解析代码,获取注释(作为数组)。
  2. 遍历评论,看看是否每一个都是你感兴趣的。
  3. 如果您需要转换注释,请注意其范围。收集所有转换。
  4. 从头到尾应用转换,以便范围不会移动。

诀窍是这里不改变AST。只需应用文本更改,就好像您直接对源字符串进行典型的搜索替换一样。因为替换的位置可能会移动,所以你需要收集所有东西,然后从最后一个开始。有关如何进行这种转换的示例,请查看我的博客文章“从双引号到单引号”(它处理字符串引号,但原理保持不变)。

最后但并非最不重要的一点是,您可能想要使用稍微高级一点的实用程序,例如Rocambole

于 2013-02-19T00:48:15.623 回答