
一种基于规则模板的c++代码向c代码的自动转化方法
技术领域
1.本发明涉及计算机编程语言技术领域,尤其涉及一种基于规则模板的c++代码向c代码的自动转化方法。
背景技术:2.在主流的嵌入式平台中,主要由c++和c语言编写的控制程序进行驱动。支持c++语言的平台可以向下兼容c语言的程序,但仅支持c语言的平台无法直接使用c++程序,需要对c++代码进行转换。如何针对c++代码向c代码的转换流程,形成一套完整的转化方法模板,以指导c++代码向c代码的转换,是亟待解决的问题。
3.在转换流程中,人工的转换方式存在以下几方面的问题:
4.(1)人工转换c++代码的转换效率问题。目前c++代码转换成c代码的主流方法是抛弃部分c++语法特性进行重写,但与之相应的调用和部署方式也需要配套的改动,这种方式会耗费大量人力物力。
5.(2)人工转换的方式由于其工作量较大,通常需要较多人员进行协作转换。在这个过程中缺少一个通用的转换规则,导致需要更多的时间用于沟通制定临时的转换规则。在转换过程用人工的重复工作来处理大量代码,容易产生各种细节上的错误。
6.(3)人工转换的方式难以统一代码风格,造成代码可读性较差的问题。且部分c语言代码需要遵守一定的代码规范。
7.为此,需要建立一种转换流程,覆盖c++与c语言的基础语法特性,提高转化效率,实现部分转化的自动化。针对完整流程,可将转化结果形成完整的c语言工程,移交给其他人员后,可完整呈现各阶段转化成果;在总体转化阶段,提供部分语法自动转化功能,人员输入代码满足转化条件时,自动转化代码数据;在自动转化的过程中提供优化计算等符合c语言风格的代码规范转换。
技术实现要素:8.本发明要解决的技术问题为:
9.(1)代码细节多,人工转换耗时耗力;(2)转换过程涉及两种语言间的语法差异,人工转化方式容易出错且难以统一转换规则;(3)人工转化的方式难以统一代码风格,不符合c语言代码的相关规范。
10.本发明采用的技术方案如下:
11.一种基于规则模板的c++代码向c代码的自动转化方法,包括:
12.s1.代码文本生成语义树:输入并扫描待转化的c++代码,识别代码标识;按块和行分割代码,对每行代码进行语义分析,并生成语义树即结构化的数据;
13.s2.基本规则转化:对生成的语义树进行基本规则转化,包括类转化、全局变量转化、引用转化和类型转化;
14.s3.代码规范转换:对基本规则转化后的语义树进行代码规范转换,包括优化计
算、命名规范、注释规范和组织规范;
15.s4.语义树生成代码文本:从代码规范转换后的语义树中提取信息,按行和块组织代码并添加代码标识,从而生成c代码文本。
16.进一步地,步骤s1包括以下子步骤:
17.s101.加载待转化的c++代码文本;
18.s102.对代码进行词法扫描和语法扫描,获取代码信息,所述代码信息包括标识符信息和逻辑结构信息;
19.s103.对代码中的注释进行扫描,获取注释信息,所述注释包括独立注释和依附于代码的注释;
20.s104.扫描完后,对于获取的代码信息和注释信息,按照行号位置信息进行整合,形成结构化的数据。
21.进一步地,步骤s2中,所述类转化的方法包括:使用全局函数加函数指针实现类的成员函数功能,并对全局函数添加前缀。
22.进一步地,使用struct类型来组织类的基础部分,同时声明函数指针以实现成员函数的功能。
23.进一步地,先以全局函数的形式进行声明和定义,再声明成员函数并添加相应的前缀来标识成员函数的身份,添加额外的类型指针参数*p使其具有调用类内其他成员函数和成员变量的功能。
24.进一步地,为每个类添加注入函数,用于将已声明的成员函数的地址传入实例化对象的函数指针中,使其具备相应的成员函数属性;在构造函数中先执行注入函数,再执行其余构造函数内容。
25.进一步地,步骤s2中,所述引用转化的方法包括:将所涉及的引用形参转化为指针形参,并对函数体中相应的位置进行处理。
26.进一步地,步骤s2中,所述全局变量转化的方法包括:将局部变量声明调整至作用域头部。
27.进一步地,步骤s2中,所述类型转化包括对布尔类型的转化:在工程中添加convert_cplusplus2c.h头文件,在其中定义相关宏和结构体实现布尔类型的功能。
28.进一步地,步骤s3中,所述优化计算的方法包括:若每行代码对数学库函数的调用次数大于一次,则将调用字段拆替换为局部变量,所述局部变量包括局部变量声明、局部变量赋值和局部变量调用。
29.本发明的有益效果在于:
30.(1)本发明提供了统一化的c++代码转化c代码方法,将待转化的c++代码通过代码扫描工具存储为数据信息,并通过语义分析工具对数据信息进行基础的语义分析,将其划分为语义树,有更高的操作修改自由度。
31.(2)针对c++与c语言的部分语法特性差异制定了转化规则,并总结形成转化规则模板,应用该模板对存储代码信息的语义树进行处理,对规则模板之外的语法特性进行标记及报错处理,可帮助编码人员了解代码转换的结果。
32.(3)对有额外代码规范的情况制定了相应的代码规范模板,在自动的代码转化和人工调整后,基于代码规范模板对代码进行规范化处理,可提高代码的可读性。
33.(4)在完成上述处理后,对语义树中的代码信息重新组装输出,最终可得到符合相关规范的c语言代码。
34.(5)在代码转化流程中应用了自动化的代码处理,大大提升了代码转换的执行效率。
35.(6)形成了统一的转换规则,可强化自动转化代码的流程可控性,方便后续开发人员在其基础上进行纠错和二次开发。
36.(7)增加了代码规范约束,可进一步规范化代码,可提升代码的可读性,使得转换后的代码适用于不同的工况。
附图说明
37.图1本发明的c++代码向c代码的自动转化方法流程简图。
38.图2本发明的c++代码向c代码的自动转化方法流程框图。
39.图3本发明的代码扫描的运行过程图。
40.图4本发明的c++代码解析的运行过程图。
41.图5布尔类型定义头文件示例。
42.图6 c++中的类及其构造函数、析构函数、成员函数示例。
43.图7 c语言中类声明示例。
44.图8 c语言中类外成员函数声明示例。
45.图9 c语言中类的构造函数与注入函数示例。
46.图10本发明对于引用形参的处理示例。
47.图11本发明的对于函数体内引用的处理示例。
48.图12本发明的对于函数体调用点实参的处理示例。
49.图13本发明的局部变量处理示例。
50.图14本发明的优化计算对代码块的切片与筛选处理流程图。
51.图15本发明的优化计算对单行代码的处理流程图。
52.图16待优化的代码示例。
53.图17本发明的代码优化结果示例。
具体实施方式
54.为了对本发明的技术特征、目的和效果有更加清楚的理解,现说明本发明的具体实施方式。应当理解,此处所描述的具体实施例仅用以解释本发明,并不用于限定本发明,即所描述的实施例仅仅是本发明一部分实施例,而不是全部的实施例。基于本发明的实施例,本领域技术人员在没有做出创造性劳动的前提下所获得的所有其他实施例,都属于本发明保护的范围。
55.如图1和图2所示,本实施例提供了一种基于规则模板的c++代码向c代码的自动转化方法,包括代码文本读写、文本与语义树转换以及规则转换,具体包括以下步骤:
56.s1.代码文本生成语义树:输入并扫描待转化的c++代码,识别代码标识;按块和行分割代码,对每行代码进行语义分析,并生成语义树即结构化的数据;
57.s2.基本规则转化:对生成的语义树进行基本规则转化,包括类转化、全局变量转
化、引用转化和类型转化;
58.s3.代码规范转换:对基本规则转化后的语义树进行代码规范转换,包括优化计算、命名规范、注释规范和组织规范;
59.s4.语义树生成代码文本:从代码规范转换后的语义树中提取信息,按行和块组织代码并添加代码标识,从而生成c代码文本。
60.一、代码文本生成语义树
61.如图3所示,代码文本生成语义树包括以下子步骤:
62.s101.加载待转化的c++代码文本:加载需要扫描的vc工程、单个代码文件或内存中的代码文本;
63.s102.对代码进行词法扫描和语法扫描(忽略注释),获取代码信息,所述代码信息包括标识符信息(例如类信息、变量信息、函数信息等)和逻辑结构信息(例如if-else、for、while、do-while、switch等);
64.s103.对代码中的注释进行扫描,获取注释信息,所述注释包括独立注释(例如指令注释)和依附于代码的注释(例如算法注释);
65.s104.扫描完后,对于获取的代码信息和注释信息,按照行号位置信息进行整合,形成结构化的数据,方便后续代码转化操作。
66.需要说明的是,步骤s102和步骤s103可同时执行或交换顺序执行。
67.优选地,步骤s102的代码扫描的运行过程如图4所示。具体地,利用开源语法分析器antlr和集成调试工具antlrworks,基于成熟的c.g语法文件,并根据《c99》和《c++98》规范,对c.g文件进行修改和拓展,用于支持常见的c++代码解析,包括:
68.支持变量定义语句和执行语句交替;
69.命名空间前缀,如"std::string str;";
70.new和delete操作;
71.使用模板类型定义变量,如"vector《r》vec_r;";
72.引用操作符,如"int&r=i;";
73.c++结构体变量变量声明,如"r r;";
74.c++强制类型转换,如"int*iq=const_cast《int*》(ciq);";
75.支持解析if-elseif-else语句,而不是等效为如下形式:
76.77.例如,对以下示例代码进行解析:
[0078][0079][0080]
上述代码经词法语法解析后,生成抽象语法树(ast)如下所示:
[0081]
[0082]
[0083]
[0084]
[0085][0086]
二、基础规则转化
[0087]
基础规则转化包括类型转化、类转化、引用转化、全局变量转化。
[0088]
(1)类型转化
[0089]
在c90语法规范中,并未实现与c++类似的布尔类型,具体解决方法为:在工程中添加convert_cplusplus2c.h头文件,在其中定义相关宏和结构体实现布尔类型的功能,如图5所示。
[0090]
(2)类转化
[0091]
在c语言中,没有关键字class,即类的语法特性没有实现,仅有较为基础的struct结构体来存储自定义数据类型。c语言中类与结构体的区别主要如下:
[0092]
(1)c语言中的结构体能够封装数据类型,但不能含有函数,而类是面向对象的,除了自身的属性以外还可以封装行为方法,即类中可以有成员函数,结构体中没有。
[0093]
(2)c语言中定义结构体变量需要加struct关键字,类不需要。
[0094]
(3)c语言中结构体默认成员变量是公共的,类默认成员变量是私有的。
[0095]
(4)c语言中结构体是没有this指针的,而类有。
[0096]
针对区别(1),使用全局函数加函数指针来实现类的成员函数功能,同时对全局函数添加前缀来加以区分,如图6所示。具体主要由以下三部分实现。
[0097]
①
类声明
[0098]
如图7所示,c语言中使用struct类型来组织类的基础部分,同时声明函数指针以实现成员函数的功能。
[0099]
②
类外成员函数声明
[0100]
如图8所示,c语言中类的成员函数需要先以全局函数的形式进行声明和定义,声明成员函数为其添加相应的前缀来标识成员函数的身份,添加额外的类型指针参数*p使其具有调用类内其他成员函数和成员变量的功能,同时为每个类添加注入函数。
[0101]
③
类的构造函数与注入函数
[0102]
如图9所示,注入函数负责将之前声明的成员函数的地址传入实例化对象的函数指针中,使其具备了相应的成员函数属性。在构造函数中须先执行注入函数,再执行其余构造函数内容。
[0103]
(3)引用转化
[0104]
由于c语法不支持引用,故将所涉及的引用形参转化为指针形参,并对函数体中相应的位置进行处理,如图10所示。
[0105]
在处理形参后,函数调用点处的实参也需要相应的处理,如图11所示。
[0106]
(4)全局变量转化
[0107]
将局部变量声明调整至作用域头部,如图13所示。
[0108]
三、代码规范转换
[0109]
代码规范转换主要完成自定义的代码规范处理,包括优化计算、命名规范、注释规范和组织规范,现以优化计算为例进行说明。
[0110]
在函数体代码中,存在对math库函数进行多次重复调用的行为,这些调用的实参和返回结果都相同,重复调用降低了运行效率,故对这种情况进行代码自动优化。
[0111]
如图14所示,对用户输入的代码块,先按行进行切片,然后统计每行对数学库函数的调用次数,若大于一次则需要进行优化处理。
[0112]
如图15所示为优化计算对单行代码的处理流程,在经过优化计算处理后,数学库函数的调用字段被局部变量替代,通过局部变量来保证代码的语义正确性,如图16和图17分别为优化前后的代码。
[0113]
综上所述,本实施例提供的一种基于规则模板的c++代码向c代码的自动转化方法具有以下特点:
[0114]
(1)代码语义分析利用antlr等语法分析组件实现相应功能,要求待分析的代码具有格式化的注释标识,用以辅助语义识别;在完成语义分析后代码会以语义树的形式保存,有更高的操作修改自由度。
[0115]
(2)明确了c++与c语言之间的语法特性差异,对可以支持自动化转化的特性编写相对应的转化规则,总结转化规则用于转化流程,最终形成转化规则模板;对暂时无法支持的语法特性,通过其关键字进行标识。
[0116]
(3)为保证转换后工程不发生功能衰退,在需要的情况下可对原工程的组织结构
进行增添删改,维护原程序在调用方式和交互方式尽量不发生改变。
[0117]
(4)明确了c++代码至c代码的转化流程,可简化人工操作,提升转化的效率和准确性。
[0118]
(5)产生了一套转化规则模板,可提升编码人员间的协作效率。
[0119]
需要说明的是,对于前述的方法实施例,为了简便描述,故将其表述为一系列的动作组合,但是本领域技术人员应该知悉,本技术并不受所描述的动作顺序的限制,因为依据本技术,某些步骤可以采用其他顺序或者同时进行。其次,本领域技术人员也应该知悉,说明书中所描述的实施例均属于优选实施例,所涉及的动作和模块并不一定是本技术所必须的。