上篇文章:用pycparser解析C语言踩坑记录
简单的使用参考GitHub库中给的example即可。如果想要进行深度使用,可以参考c_ast.py和_c_ast.cfg文件,在里面详细描述了不同类型节点的定义。接下来我会对此详细描述,并介绍这些节点的用法。
基类
所有类型的节点都是由Node类继承而来,例如
我之后会一直用这个赋值Assignment节点来举例
show函数
用来递归地打印一棵语法树
可选是否输出属性名、该段代码的起始坐标(第几行第几列)等,看注释即可。
其中coord类在plyparser.py中定义
迭代方法children()
在pycparser中,不同类型的节点的孩子叫法都不同。比如赋值Assignment有两个孩子——lvalue和rvalue,声明序列DeclList有若干声明语句作为孩子存在decls数组中。这样一来就很难实现一个通用的遍历算法。于是库作者设计了children函数,在每个节点子类中重写它为遍历本类型节点的孩子。
当然,最最贴心的是,作者还为每个类实现了__iter__方法,这样每个类都成为了Iterable对象,可以直接使用for循环对该节点遍历,遍历出的元素就是它的孩子。
attr_names存储属性名
与千人千面的孩子名类似的,不同类型节点也有它独有的属性。为了方便统一的算法书写,在每个类中都有一个attr_names成员变量存储所有的属性名。参见上面赋值节点的图
这样一来,比如在show函数中输出节点所有属性就可以这样做:(attrnames是选择是否输出属性名)
大家可以发现attr_names和children构成了节点主要的成员变量(从某种意义上来说children是的),它们被在__slots__中预先声明。这点给我动态添加新的属性造成了阻碍,所以我在进行分析的时候根据pyparser生成语法树的信息复刻出了一棵新树