李桑 2009年08月13日 星期四 20:16 | 4324次浏览 | 7条评论
python ply cppheaderparser psdl c++头文件解析
PSDL(Protocol Signature Description Language)--协议特征描述语言
最近需要对psdl文件及c++头文件进行解析,解出类、结构体、方法、属性等内容,在网上找到了ply( http://www.dabeaz.com/ply/ )及cppheaderparser( http://sourceforge.net/projects/cppheaderparser/ ),ply
是python实现lex and yacc的一个工具, cppheaderparser是一个使用ply对c++头文件进行解析的库。但是经过测试 cppheaderparser并不满足我的需求,它不支持内部类及结构体嵌套解析,不支持变量名字为数组,经过了winpdb的调试及代码的修改终于支持了!
首先,先安装ply,然后下载 cppheaderparser,修改CppHeaderParser.py文件为如下内容(不支持语法着色,晕那!)。
修改82行为
t_NAME = r'[<>A-Za-z_\[\]][A-Za-z0-9_\[\]]*'
修改371-483行为如下内容
self.curClass = ""
self.classes = {}
self.nameStack = []
self.lastClass = "" #2009-08-11 lisang save last class name
self.curAccessSpecifier = 'private'
if (len(self.headerFileName)):
headerFileStr = "\n".join(open(self.headerFileName).readlines())
self.braceDepth = 0
lex.input(headerFileStr)
curLine = 0
curChar = 0
if not tok:
break
curLine = tok.lineno
curChar = tok.lexpos
if (tok.type == 'OPEN_BRACE'):
if len(self.nameStack) and not is_enum_namestack(self.nameStack):
if len(self.lastClass) == 0: #2009-08-11 lisang save last class name
self.lastClass = self.curClass
self.evaluateStack()
else:
self.nameStack.append(tok.value)
self.braceDepth += 1
elif (tok.type == 'CLOSE_BRACE'):
if len(self.nameStack) and is_enum_namestack(self.nameStack):
self.nameStack.append(tok.value)
elif self.braceDepth > 0:
self.evaluateStack()
else:
self.nameStack = []
#self.braceDepth -= 1
#if (self.braceDepth == 0):
# self.curClass = ""
self.curClass = self.lastClass #2009-08-11 lisang save last class name
self.lastClass = ""#2009-08-11 lisang reset last class name value
if (tok.type == 'OPEN_PAREN'):
self.nameStack.append(tok.value)
elif (tok.type == 'CLOSE_PAREN'):
self.nameStack.append(tok.value)
elif (tok.type == 'EQUALS'):
self.nameStack.append(tok.value)
self.nameStack.append(tok.value)
elif (tok.type == 'PLUS'):
self.nameStack.append(tok.value)
elif (tok.type == 'STRING_LITERAL'):
self.nameStack.append(tok.value)
elif (tok.type == 'NAME' or tok.type == 'AMPERSTAND' or tok.type == 'ASTERISK'):
if (tok.value == 'class' or tok.value == 'struct'):
self.nameStack.append(tok.value)
elif (tok.value in supportedAccessSpecifier):# and self.braceDepth == 1):
self.curAccessSpecifier = tok.value
else:
self.nameStack.append(tok.value)
elif (tok.type == 'COLON'):
#Dont want colon to be first in stack
if len(self.nameStack) == 0:
continue
self.nameStack.append(tok.value)
elif (tok.type == 'SEMI_COLON'):
#if (self.braceDepth < 2):
self.evaluateStack()
elif (tok.value == 'PRECOMP_MACRO'):
pass
except:
raise CppParseError("Not able to parse %s on line %d evaluating \"%s\"\nError around: %s"
% (self.headerFileName, tok.lineno, tok.value, " ".join(self.nameStack)))
def evaluateStack(self):
"""Evaluates the current name stack"""
if (len(self.curClass)):
if (debug): print "%s (%s) "%(self.curClass, self.curAccessSpecifier),
if (len(self.nameStack) == 0):
if (debug): print "(Empty Stack)"
return
#2009-08-11 lisang add struct type
elif (self.nameStack[0] == "class" or self.nameStack[0] == "struct"):
self.evaluateClassStack()
elif (len(self.curClass) == 0):
self.nameStack = []
return
elif (self.braceDepth < 1):
#Ignore global stuff for now
if (debug): print "Global stuff: ", self.nameStack
self.nameStack = []
return
#elif (self.braceDepth > 1):
# self.nameStack = []
# return
elif is_enum_namestack(self.nameStack):
#elif self.nameStack[0] == "enum":
self.evaluateEnumStack()
elif ('(' in self.nameStack):
self.evaluateMethodStack()
else:
self.evaluatePropertyStack()
self.nameStack = []
def evaluateClassStack(self):
"""Create a Class out of the name stack (but not its parts)"""
#dont support sub classes today
if (debug): print 'self.nameStack',self.nameStack
#2009-08-11 lisang support inner class embeded
#if self.braceDepth != 0:
# return
newClass = CppClass(self.nameStack)
if len(newClass.keys()):
self.curClass = newClass["name"]
self.classes[self.curClass] = newClass
else:
self.curClass = ""
使用的c++头文件例子如下:
测试输出结果如下图所示:
后续可能还需要根据具体的需求进行修改,如对宏定义、命名空间、虚函数等进行支持,ply还真是不错,很方便!
Zeuux © 2024
京ICP备05028076号
回复 王依依 2009年08月14日 星期五 09:56
回复 李桑 2009年08月14日 星期五 12:43