最近换了linux,没有了vs很不习惯,虽然还有eclipse和codeblocks也不错,但是c++类函数代码生成不怎么强,基本没有。
每次写c++代码,写完.h头文件里类的声明后总要在.cpp文件里再写实现,这个时候通常把头文件的函数声明复制过来,再加上类作用域限定符,写多了感觉很麻烦。而且容易复制错地方。不过现在既然在linux下就自己动手丰衣足食吧,所以就像自己做个工具完成这件事。
字符串处理是脚本语言的强项,学了python后还没怎么用过,这次就用python做吧。
先在命令行里输入.h文件和.cpp文件的路径,可以不要.cpp文件,那样就从头生成.cpp文件。
先扫描.cpp文件(如果有的话)用正则表达式把纯函数声明(就是函数名和参数类型,不要参数名,要去空格)抓出来,存在列表里。
再扫描.h文件,同样用正则先抓出类名。
再抓纯函数声明,然后每抓出一项,就和刚才存的比对,如果没有就在.cpp文件里加上这个函数的空实现,当然如果开头没有给.cpp文件就把所有的函数都加进去。
工具只能针对一个文件里只有一个类的情况,类型名不能有泛型,而且函数声明要写在一行里,代码风格不能太乱。接下来希望能改进到支持一个文件有多个类。
虽然说起来很简单,但是便起来很麻烦,尤其是正则表达式调的我眼都花了。
不多说了,上代码:
'''
#headfileparse.py
'''
import re
line_pattern = re.compile(r'\A\s*//.*')
mullinestart_pattern = re.compile(r'\A\s*/\*.*')
mullineend_pattern = re.compile(r'.*\*/\s*\Z')
fun_pattern = re.compile(r'((~?\w+|operator [-\].[<>+*&|^/%=\(\)]{1,2})\s*\(.*\)\s*(const)?);')
class_pattern = re.compile(r'\A\s*class\s+(\w+)')
inline_pattern = re.compile(r'\A.*\s*inline\s*.*')
returnvaluetype_pattern = re.compile(r'\A\s*((virtual|static|explicit)\s+)?((const\s+)?(?!virtual)\w+(?!\w+\s*\()(\s*(\*|&))?\s*(const\s+)?)'+fun_pattern.pattern)
def is_linecomment(line):
match = line_pattern.match(line)
return match;
def is_mullinecomment_start(line):
match = mullinestart_pattern.match(line)
return match;
def is_mullinecomment_end(line):
match = mullineend_pattern.match(line)
return match;
def is_function(line):
match = fun_pattern.search(line)
if match:
return match.group(1)
else:
return None
def is_classname(line):
match = class_pattern.match(line)
return match;
def get_classname(line):
match = class_pattern.match(line)
if match:
return match.group(1)
else:
return None
def is_inlinemember(line):
match = inline_pattern.match(line)
return match;
def get_returnedvaluetype(line):
match = returnvaluetype_pattern.match(line)
if match:
return match.group(3)
else:
return None
'''
#sourcefileparse.py
Created on 2013-5-23
@author: bjr
'''
import re
fun_pattern = re.compile(r'(((~?\w+|operator [-\].[<>+*&|^/%=\(\)]{1,2})\s*\(.*\))\s*(const)?){?')
fun_declare_pattern = re.compile(r'((?:~?\w+|operator [-\].[<>+*&|^/%=\(\)]{1,2})\s*)\((\s*((const\s+)?\w+(\s*(\*|&))*\s*(const\s+)?)\w*\s*(=[^,)]*)?(,|\)))*')
type_pattern = re.compile(r'(\s*((const\s+)?\w+(\s*(\*|&))*\s*(const\s+)?)\w*\s*(=[^,)]*)?(,|\)))')
def get_fun_declare(fun):
match = fun_declare_pattern.match(fun)
fun_name = match.group(1).replace(' ','')
param = []
param_str = fun[match.end(1)+1:]
while match:
match = type_pattern.search(param_str)
if match:
param.append(match.group(2).replace(' ',''))
param_str = param_str[match.end(8):]
param.insert(0, fun_name)
return param;
def is_function(line):
match = fun_pattern.search(line)
if match:
return match.group(1)
else:
return None
'''
#function_check.py
Created on 2013-5-23
@author: bjr
'''
import sourcefileparse
import sys
import headfileparse
if len(sys.argv)>1:
headfilename = sys.argv[1]
if not headfilename.lower().endswith(".h"):
print "error headfile type"
sys.exit();
else:
print "must need headfile"
sys.exit();
try:
headfile = open(headfilename)
except IOError:
print "can't open "+headfilename
sys.exit();
if len(sys.argv)>2:
sourcefilename = sys.argv[2]
if not sourcefilename.lower().endswith(".cpp"):
print "error sourcefile type"
sys.exit();
else:
sourcefilename = headfilename[:-2]+".cpp"
try:
sourcefile = open(sourcefilename,"r")
except IOError:
try:
sourcefile = open(sourcefilename,"w")
except IOError:
print "can't write"+sourcefilename
sys.exit()
print >> sourcefile,'#include"'+headfilename+'"'
sourcefile.close()
sourcefile = open(sourcefilename,"r+w")
classname=None
functionprefix=None
functionname=None
mulcommentflag=False
fun_implement_list = []
#parse sourcefile
for line in sourcefile.readlines():
if mulcommentflag:
if headfileparse.is_mullinecomment_end(line):
mulcommentflag=False;continue
if headfileparse.is_mullinecomment_start(line):mulcommentflag=True; continue
if headfileparse.is_linecomment(line):continue
function = sourcefileparse.is_function(line)
if function:
fun_implement_list.append(sourcefileparse.get_fun_declare(function))
#parse headfile
for line in headfile.readlines():
if mulcommentflag:
if headfileparse.is_mullinecomment_end(line):
mulcommentflag=False;continue
if headfileparse.is_mullinecomment_start(line):mulcommentflag=True; continue
if headfileparse.is_linecomment(line):continue
if not classname:
if headfileparse.is_classname(line):
classname = headfileparse.get_classname(line)
continue
function = sourcefileparse.is_function(line)
if function:
if sourcefileparse.get_fun_declare(function) not in fun_implement_list:
function = str(function)
functionreturn = headfileparse.get_returnedvaluetype(line)
if functionreturn:
functionreturn = str(functionreturn)
else:
functionreturn = ""
functioniplement = functionreturn+classname+"::"+function+"\n{\n}\n"
print >>sourcefile,functioniplement
#print fun_implement_list
headfile.close()
sourcefile.close()
用python运行最后一个function_check.py,把头文件名和.cpp文件名作为参数传进去。
这个是在python2.6下运行的,python3的自己把print的那些语句改成符合python3的形式就行。