识别C#或C ++函数从行计数程序开始

时间:2010-01-18 21:27:42

标签: c# c++ function token

我有一个用C#编写的程序,当给定C ++或C#文件时,计算文件中的行数,计算注释和设计器生成的代码块中的行数。我想添加计算文件中有多少函数以及这些函数中有多少行的能力。我无法弄清楚如何确定一行(或一系列行)是否是函数(或方法)的开头。

至少,函数声明是返回类型,后跟标识符和参数列表。有没有办法在C#中确定令牌是有效的返回类型?如果没有,有没有办法轻松确定一行代码是否是函数的开头?基本上我需要能够可靠地区分类似的东西。

bool isThere() 
{
...
}

来自

bool isHere = isThere()

isThere()

以及任何其他功能声明相似。

5 个答案:

答案 0 :(得分:2)

执行此操作的问题是要准确地执行此操作,您必须考虑可以定义C#函数的所有可能方法。实质上,您需要编写解析器。这样做超出了简单SO答案的范围。

这个问题可能会以正则表达式的形式出现很多答案,它们适用于常见情况,但可能会在以下情况下爆发

int
?
/* this 
is */
main /* legal */ (code c) { 
}

答案 1 :(得分:1)

我可能会使用正则表达式,但是考虑到数据类型和声明选项以及用户定义的类型/ clases的数量,这将是非常重要的。要简单地避免从函数调用中捕获赋值,您可以从正则表达式(未经测试)开始,如:

(private|public|internal|protected|virtual)?\s+(static)?\s+(int|bool|string|byte|char|double|long)\s+([A-Za-z][A-Za-z_0-9]*)\s*\(

这不是(通过一个长镜头)抓住一切,你需要调整它。

另一种方法可能涉及反射以确定函数声明,但是当您想要进行静态源代码分析时,这可能不合适。

答案 2 :(得分:1)

首先扫描范围。当你在文件中工作时,你需要计算开括号{和关闭括号},以便你知道你所在的范围。你还需要在扫描文件时解析//和/ * ... * / ,所以你可以告诉我什么时候在评论中,而不是真正的代码。还有#if,但你必须编译代码才能知道如何解释这些。

然后你需要在一些范围打开大括号之前立即解析文本以弄清楚它们是什么。您的函数可能位于全局范围,类范围或命名空间范围内,因此您必须能够解析命名空间和类以标识您正在查看的范围类型。你通常可以通过相当简单的解析来逃避(大多数程序员使用类似的风格 - 例如,有人在'Fred Fred'和它的开括号之间放置空行是不常见的。但是他们可能会写'class Fred {'。那里也是他们将额外的垃圾放在线上的机会 - 例如'模板类__DECLSPEC MYWEIRDMACRO Fred {'。但是,你可以通过一个非常简单的方式逃脱“这条线是否包含两侧带有空格的'class'这个词?启发式,在大多数情况下都有效。

好的,所以你现在知道你在一个名字空间里面,在一个类里面,你找到了一个新的开放范围。这是一种方法吗?

方法的主要识别特征是:

  • 返回类型。这可以是任何字符序列,可以是许多标记(“__DLLEXPORT const unsigned myInt32typedef *&”)。除非你编译整个项目,否则你没有机会。
  • 功能名称。单个令牌(但要注意“operator =”等)
  • 包含零个或多个参数或'void'的一对括号。这是你最好的线索。
  • 函数声明不包括将在许多范围之前的某些保留字(例如枚举,类,结构等)。它可能会使用一些您不得绊倒的保留字(模板,常量等)。

所以你可以搜索一个空白行或一行结尾; {或}表示前一个语句/范围的结束。然后抓住该点和范围的开放括号之间的所有文本。然后提取令牌列表,并尝试匹配参数列表括号。检查所有令牌都不是保留字(枚举,结构,类等)。

这将给你一个“合理程度的信心”,你有一个方法。您不需要太多解析就可以获得相当高的准确度。您可能会花费大量时间查找混淆“解析器”的所有特殊情况,但如果您正在开发一个相当一致的代码库(即只是您自己公司的代码),那么您可能能够识别所有代码中的方法相当容易。

答案 3 :(得分:0)

如果你想写一个真正的解析器(我知道你可能不想),那么试试ANTLR。如果不出意外,这将是一个有趣的项目

答案 4 :(得分:-1)

  

有没有办法在C#中确定令牌是有效的返回类型?

您可以非常轻松地确定它是返回类型还是错误(通过确保它不是那个位置的其他任何东西)。而且您可能不需要保证无效代码的“正确”行为。

然后你找到括号。