如何检测永远不会被调用的函数定义并将其从文件中删除然后保存?
假设我现在只有1个CPP文件,它有main()
函数和许多其他函数定义(函数定义也可以在main()
内)。如果我要编写一个程序来解析这个CPP文件,并检查一个函数是否被调用,如果没有被调用则删除,那么这样做的方式是什么?
我想到的方法很少:
main()
开头和结尾的行号。我可以通过维持一堆打开和关闭大括号{
和}
来实现。 main
之后的任何内容都是函数定义。然后我可以解析函数定义。为此,我可以通过以下方式解析它:
< string >< open paren >< comma separated string(s) for arguments >< closing paren >
一旦我拥有了(2)中描述的所有函数的名称,我就可以创建一个名称为key和value的映射为bool
,表示函数是否被调用一次或不。
最后再次解析文件以检查是否有任何名称与此地图相同的函数调用。函数调用可以来自main
或来自其他一些函数。可以根据函数是否被调用来标记键的值(即函数名称)。
我觉得我的逻辑很复杂,可以用更聪明的方式完成。根据上述逻辑,很难找到所有的角落情况(会有很多)。此外,可能存在函数指针以使解析逻辑变得困难。如果这还不够,那么函数指针也可以typedef
。
如何设计我的程序?是一个地图(维护文件名)和堆栈(维护大括号)正确的数据结构还是还有其他更适合处理它的东西?
注意:我不是在寻找任何工具来执行此操作。我也不想使用任何库(如果它存在以使事情变得容易)。
答案 0 :(得分:1)
我认为你不应该尝试从头开始构建一个C ++解析器,因为其他人在评论中说这真的很难。恕我直言,你最好从CLang库开始,而不是为你做低级解析,直接使用抽象语法树。
您甚至可以使用crange作为如何使用它们来生成交叉引用表的示例。
或者,您可以直接使用GNU global,因为它的if (Robot.IsConnected)
{
if (GamePad.GetState(PlayerIndex.One).IsButtonDown(Buttons.A) || GamePad.GetState(PlayerIndex.One).IsButtonDown(Buttons.B) || GamePad.GetState(PlayerIndex.One).IsButtonDown(Buttons.Y) || GamePad.GetState(PlayerIndex.One).IsButtonDown(Buttons.X))
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Y == ButtonState.Pressed)
{
Robot.SendMessage(driveRobot, straight);
}
if (Robot2.IsConnected)
{
if (GamePad.GetState(PlayerIndex.Two).IsButtonDown(Buttons.A) || GamePad.GetState(PlayerIndex.Two).IsButtonDown(Buttons.B) || GamePad.GetState(PlayerIndex.Two).IsButtonDown(Buttons.Y) || GamePad.GetState(PlayerIndex.Two).IsButtonDown(Buttons.X))
{
if (GamePad.GetState(PlayerIndex.Two).Buttons.Y == ButtonState.Pressed)
{
Robot.SendMessage(driveRobot2, straight);
}
命令直接生成您必须分析的定义和参考数据库。
恕我直言,这两种方式比从头创建C ++解析器更简单。
答案 1 :(得分:1)
您应该考虑很多问题。首先,您不应该假设main()
是源文件中的第一个函数。
即使它是,在main()
之前应该有一些函数头声明,以便编译器可以在main
中识别它们的调用。
接下来,函数的开始和结束括号不需要在单独的行中,它们也不必是它们行中的唯一字符。通常,几乎整个C ++代码可以放在一行中!
此外,函数可能因参数类型不同而具有相同的名称(重载),因此如果不将整个代码解析为,则不能识别调用哪个函数参数的类型。甚至更多:您必须执行与标准转换/强制转换匹配的类型列表,可能需要考虑内联构造函数调用。当然你不应该忘记默认参数。例如,resolving overloaded function call的Google会看到大纲here
此外,可能存在未使用功能链。例如,如果a()
调用b()
和b()
调用c()
和d()
,但a()
本身未调用,那么整个四个都未使用,即使存在b()
,c()
和d()
的“来电”。
还有可能通过指针调用函数,在这种情况下,您可能无法找到调用。例如:
int (*testfun)(int) = whattotest ? TestFun1 : TestFun2; // no call
int testResult = testfun(paramToTest); // unknown function called
最后,代码可能会被#define
- s。
结论:您可能必须编写自己的C ++编译器(机器代码生成器除外)才能实现目标。
答案 2 :(得分:1)
我能想到的最简单的方法是:
答案 3 :(得分:0)
这是一个非常粗略的想法,我怀疑它是非常有效的,但也许它可以帮助你开始。首先遍历文件一次,挑选出任何函数名称(我不完全确定你会怎么做)。但是一旦你有这些名字,再次遍历文件,在文件的任何地方,主要和其他功能中查找函数名称。如果您发现多于1个实例,则意味着正在调用该函数并且应该保留该函数。