将JavaScript AST中的注释替换为从注释派生的子树';内容

将JavaScript AST中的注释替换为从注释派生的子树';内容,javascript,parsing,abstract-syntax-tree,Javascript,Parsing,Abstract Syntax Tree,我是《快速而肮脏的JavaScript和CoffeeScript》的作者。我希望通过使用JavaScript解析器而不是正则表达式来定位注释,从而使库不那么脏 我想使用或执行以下操作: 创建一个AST 在树中漫游,对于每个注释节点: 从注释节点的文本创建AST 用此子树替换主树中的注释节点 输入: !function() { // > toUsername("Jesper Nøhr") // "jespernhr" var toUsername = function(tex

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

我想使用或执行以下操作:

  • 创建一个AST
  • 在树中漫游,对于每个注释节点:
  • 从注释节点的文本创建AST
  • 用此子树替换主树中的注释节点
  • 输入:

    !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()
      }
    
    }()
    
    输出:

    !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提供了一个函数,它接受一个节点类型和一个函数,并在每次遇到指定类型的节点时遍历调用该函数的树。这似乎很有希望,但不适用于评论


    使用Esprima,我可以使用
    Esprima.parse(输入,{comment:true,loc:true})。comments
    来获取注释,但我不知道如何更新树。

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

    。。。。事实上,Esprima将注释捕获列为当前错误:

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

    因此,看起来您需要先修复解析器以捕获注释,此时您的任务应该是简单的,否则,您将陷入困境

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


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

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

  • 解析代码,获取注释(作为数组)
  • 反复浏览这些评论,看看它们是否都是你感兴趣的
  • 如果需要转换注释,请注意其范围。收集所有转换
  • 将变换应用回“第一个”,使范围不会移动
  • 诀窍在于不要改变AST。简单地应用文本更改,就像您直接对源字符串执行典型的搜索替换一样。因为替换的位置可能会改变,所以您需要收集所有内容,然后从最后一个开始执行。关于如何执行这种转换的示例,请看我的博客文章(它涉及字符串引号,但原理保持不变)


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

    您尝试过吗?我不知道该项目。看起来很有希望。