【问题标题】:Comment extractor [closed]评论提取器[关闭]
【发布时间】:2020-05-05 06:15:48
【问题描述】:

我正在寻找用于 C、C++、Python 或 Node.js 的命令行工具或库,它们可以仅从各种语言的源文件中提取 cmets。

例如,给定“bob.c”:

int main(){ //Here is a comment
  int i=3;  /*Another comment*/
}

应返回以下内容:

Here is a comment
Another comment

可能包含行号。

这应该适用于“bob.py”、“bob.js”、“bob.css”、“bob.rb”、“bob.asm”等。

这个问题与this other one 不同,因为我不仅对 C 风格的 cmets 感兴趣,而且对其他问题也感兴趣。

此外,我非常怀疑正则表达式作为解决方案。评论式的短语可以以非常复杂的方式放置在引用的文本中;我还没有看到解决这个问题的正则表达式解决方案。

【问题讨论】:

  • 我不认为 cmets 一定有任何类型的结构化格式。
  • 也许使用regex
  • @QuaxtonHale,那绝对是黑暗。几乎所有关于 SO 建议使用正则表达式提取 cmets 的答案都是错误的。大多数语言都包含引号分隔的文本,其中可能包含简单的正则表达式认为是 cmets 的短语。您可以构建复杂的正则表达式,但是,当您处理完所有特殊情况时,您已经创建了一个难以理解的混乱。
  • 如果你想处理各种各样的语言,你要么需要决定它们属于什么类别(C-like,使用 C 风格的 cmets,COBOL 和 COBOL 风格的 cmets,...)并为每个构建一个词法分析器。如果该语言有很多奇怪的词法语法(PHP 在这方面非常糟糕,请查看内插字符串),此类词法分析器的细节可能会变得棘手。 ...

标签: python c++ parsing comments


【解决方案1】:

您可以将正则表达式表与 python、C++、grep 等中的任何一个一起使用,令人作呕,请记住,许多语言都有多种注释类型,并且某些类型的 cmets(在某些语言中)可以多线。可以轻松返回行号。

以查看 python re 库文档为起点。

【讨论】:

  • 那条路绝对是黑暗。几乎所有关于 SO 建议使用正则表达式提取 cmets 的答案都是错误的。大多数语言都包含引号分隔的文本,其中可能包含简单的正则表达式认为是 cmets 的短语。您可以构建复杂的正则表达式,但是,当您处理完所有特殊情况时,您已经创建了一个难以理解的混乱。
  • 我和史蒂夫一起做这个。如果您必须 解析 语言,则正则表达式将不起作用。然而,事实证明,我们使用非常多的正则表达式来定义词法分析器。查看任何标准的词法分析器生成器。在某些特殊情况下,正则表达式不起作用,但如果您可以使用词法分析器为语言定义 all 词位,那么您当然可以过滤掉所有不满足要求的 cmets OP的请求。事实上,通过合并所有非注释标记的正则表达式,您可以有效地定义一个只有两个词位的词法分析器:COMMENT 和 OTHERSTUFF。这很容易过滤。
  • ... 你可能不得不编写一些丑陋的 hack(几乎在每个词法分析器中都可以找到)来处理诸如 PHP 的文档字符串之类的讨厌的东西,其中打开字符串的字符序列也会关闭它;你不能用正则表达式来表达。但是如果您愿意通过经典方案构建词法分析器,那么构建仅提取任何语言的 cmets 的特殊词法分析器并不难;对于 N 种语言,构建 N 个这样的词法分析器。
  • @Richard:就你的观点而言,如果你定义一个传统的词法分析器,你会发现实际上你写了很多词法表达式来覆盖语言中的所有词素,每个词法都有自己的特殊情况.大多数人不认为正则表达式定义的词法分析器是难以理解的混乱。相反,他们认为它们是管理数十个正则表达式的有组织的方式。是的,对于许多语言,如果你处理所有的词位,你将需要这种复杂性;如果您要合并所有不感兴趣的,则更少,但合并后的正则表达式可能会很大。
  • @IraBaxter:你说的非常真实,我很感激。我的犹豫是,SO 是一个无法完成工作的正则表达式的荒地,答案通常是构建更复杂的正则表达式。但是,你是对的,有一些方法可以组织方法,以便它们形成一个架构良好的整体。现在支持史蒂夫。
【解决方案2】:

[OP 要求将此作为答案发布]

如果您想处理多种语言,您要么需要确定它们属于类别(类 C,使用 C 风格 cmets,COBOL 和 COBOL 风格 cmets,...)并构建一个词法分析器每个。如果该语言有很多奇怪的词法语法(PHP 在这方面非常糟糕,请查看内插字符串),此类词法分析器的细节可能会变得棘手。

如果您想要一个现成的,我们的源代码搜索引擎通过对您提供的代码库进行词法分析和索引来提供大规模搜索;它有大约 40 多种语言和方言的词法分析器;要求它查找所有 cmets(或任何其他令牌)并将它们全部作为搜索命中导出到命中日志文件是微不足道的。 (此命令实际上是打开日志后的字母“C”[for Comments])。

[回答一个附加问题]。它具有 GUI 和命令行界面。

【讨论】:

    【解决方案3】:

    在 Ira Baxter 的帮助下,我通过搜索词法分析器找到了 Pygments。

    Pygments 理解 massive number of languages 并将其中任何一种语言的输入转换为适合突出显示的标准化 HTML 输出。

    以下内容获取目录路径,递归搜索代码文件,并返回文件名字典和每个文件中的 cmets:

    import glob
    import io
    import os
    import pathlib
    
    import git
    from pygments.formatter import Formatter
    import pygments
    import pygments.lexers
    
    
    
    class CommentExtractor(Formatter):
      def __init__(self, **options):
        Formatter.__init__(self, **options)
      def format(self, tokensource, outfile):
        for ttype, value in tokensource:
          if ttype in pygments.token.Comment:
            outfile.write(value)
    
    
    
    def GetCommentsFromFile(path):
      lexer = pygments.lexers.get_lexer_for_filename(path)
      comments = io.StringIO()
      pygments.highlight(
        code      = open(path,'r').read(),
        lexer     = lexer,
        formatter = CommentExtractor(), 
        outfile   = comments
      )
      return comments.getvalue()
    
    
    
    def GetCommentsFromFiles(rootpath, excluded):
      files = {}
      for (dirpath, dirnames, filenames) in os.walk(rootpath):
        #Skip hidden directories
        dirnames[:] = [d for d in dirnames if not d.startswith('.')]
        for filename in filenames:
          if filename.startswith('.'):       #Skip hidden files
            continue
          if pathlib.Path(filename).suffix in excluded:
            continue
          filename = os.path.join(dirpath, filename)
          try:
            files[filename] = GetCommentsFromFile(filename)
          except pygments.util.ClassNotFound:
            pass
      return files
    
    
    
    excluded_files_types = {".md", ".yml", ".bat", ".sh"}
    
    files_and_comments = GetCommentsFromFiles(
      rootpath = "root_of_code_directories",
      excluded = excluded_files_types
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-28
      • 2011-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-09
      • 2012-05-19
      • 1970-01-01
      相关资源
      最近更新 更多