环境:win7_64旗舰版,VS2008

场景:C++与lua交互是比较繁琐的,当我们编写一个C++类后,如果要给lua使用,就必须写一个lua包装类,将lua与原始C++类关联起来。其实这部分代码编写完全可以通过工具生成,前提是我们能解析C++头文件,然后根据解析出来的"类"和“函数”信息就可以自动生成相关的代码。

cpp_class_grammar.h

  1. #pragma once
  2.  
  3. #define BOOST_REGEX_NO_LIB
  4. #include "boost/spirit.hpp"
  5. #include <list>
  6.  
  7. namespace bs = boost::spirit;
  8.  
  9. namespace cpp_grammar {
  10.  
  11. // 类型
  12. enum type {
  13. t_undifined = ,
  14. t_void,
  15. t_int,
  16. t_float,
  17. t_double,
  18. t_c_str,
  19. };
  20.  
  21. // 函数参数信息
  22. struct _func_param {
  23. type m_paramType; // 参数类型
  24. std::string m_paramName; // 参数名称
  25. };
  26.  
  27. // 函数信息
  28. struct _function {
  29. type m_returnType;
  30. std::string m_funcName;
  31. std::list<_func_param> m_funcParams;
  32. };
  33.  
  34. // 类信息
  35. struct _class {
  36. std::string m_className;
  37. std::list<_function> m_funcs;
  38. };
  39.  
  40. // 树结构
  41. template<class _Value>
  42. class Tree {
  43. public:
  44. Tree(Tree* parent) : m_parent(parent) {}
  45.  
  46. Tree* parent() { return m_parent; }
  47.  
  48. Tree* newTree(const _Value& value);
  49. void addChild(Tree* tree);
  50. void print();
  51.  
  52. public:
  53. _Value m_value; // 当前节点存储的值
  54. std::vector<Tree*> m_childlers; // 子节点列表
  55.  
  56. private:
  57. Tree* m_parent; // 父节点
  58. };
  59. typedef Tree<_class> class_tree;
  60.  
  61. class class_action;
  62. }
  63.  
  64. struct CppClassGrammar : public bs::grammar < CppClassGrammar > {
  65.  
  66. CppClassGrammar();
  67. ~CppClassGrammar();
  68.  
  69. cpp_grammar::class_tree& getTree();
  70.  
  71. bool doParse(const std::string& input);
  72.  
  73. template<typename ScannerT>
  74. struct definition {
  75.  
  76. bs::rule<ScannerT> _cpp_key; // 类关键字(class)
  77. bs::rule<ScannerT> _cpp_type; // 类型
  78. bs::rule<ScannerT> _cpp_comment; // 单行注释
  79.  
  80. bs::rule<ScannerT> _identifier; // 标示(解析类名、函数名、参数名等)
  81. bs::rule<ScannerT> _access_ctrl; // 访问控制权限(public、protected、private)
  82.  
  83. bs::rule<ScannerT> _tag_brace_nest; // 函数内的嵌套大括号(包括函数体)
  84. bs::rule<ScannerT> _func_param; // 函数参数(类型 + 参数名)
  85. bs::rule<ScannerT> _function; // 函数
  86.  
  87. bs::rule<ScannerT> _class; // 类
  88. bs::rule<ScannerT> _root;
  89.  
  90. definition(const CppClassGrammar& self);
  91. const bs::rule<ScannerT>& start() { return _root; }
  92. };
  93.  
  94. cpp_grammar::class_action* m_class_action;
  95. };

cpp_class_grammar.cpp

  1. #include "cpp_class_grammar.h"
  2. #include "boost/function.hpp"
  3. #include "boost/bind.hpp"
  4. #include "boost/algorithm/string.hpp"
  5.  
  6. using namespace cpp_grammar;
  7.  
  8. namespace cpp_grammar {
  9.  
  10. template<class _Value>
  11. Tree<_Value>* Tree<_Value>::newTree(const _Value& value)
  12. {
  13. Tree<_Value>* tree = new Tree(NULL);
  14. tree->m_value = value;
  15. return tree;
  16. }
  17.  
  18. template<class _Value>
  19. void Tree<_Value>::addChild(Tree<_Value>* tree)
  20. {
  21. tree->m_parent = this;
  22. m_childlers.push_back(tree);
  23. }
  24.  
  25. template<class _Value>
  26. void Tree<_Value>::print() {
  27. std::cout << m_value.c_str() << std::endl;
  28. std::vector<Tree*>::iterator iter = m_childlers.begin();
  29. for (; iter != m_childlers.end(); ++iter) {
  30. (*iter)->print();
  31. }
  32.  
  33. }
  34.  
  35. // 解析CLASS结构后特定的行为操作
  36. class class_action {
  37. public:
  38. typedef boost::function<void(char)> CallbackOne;
  39. typedef boost::function<void(const char*, const char*)> CallbackTwo;
  40.  
  41. CallbackTwo m_comment; // 注释
  42. CallbackTwo m_className; // 类名
  43. CallbackOne m_innerClass; // 进类
  44. CallbackOne m_outterClass; // 出类
  45.  
  46. CallbackTwo m_funcReturn; // 函数返回类型
  47. CallbackTwo m_funcName; // 函数名
  48. CallbackTwo m_funcParamType; // 函数参数类型
  49. CallbackTwo m_funcParamName; // 函数参数名称
  50.  
  51. class_action()
  52. : m_root(NULL)
  53. , m_node(&m_root)
  54. , m_newNode(NULL)
  55. {
  56. m_comment = boost::bind(&class_action::comment, this, _1, _2);
  57. m_className = boost::bind(&class_action::className, this, _1, _2);
  58. m_innerClass = boost::bind(&class_action::innerClass, this, _1);
  59. m_outterClass = boost::bind(&class_action::outterClass, this, _1);
  60. m_funcReturn = boost::bind(&class_action::funcReturn, this, _1, _2);
  61. m_funcName = boost::bind(&class_action::funcName, this, _1, _2);
  62. m_funcParamType = boost::bind(&class_action::funcParamType, this, _1, _2);
  63. m_funcParamName = boost::bind(&class_action::funcParamName, this, _1, _2);
  64. }
  65.  
  66. class_tree& getTree() { return m_root; }
  67.  
  68. private:
  69. // 单行注释
  70. void comment(const char* start, const char* end) {
  71. std::string s(start, end);
  72. }
  73. // 类名
  74. void className(const char* start, const char* end) {
  75. _class c;
  76. c.m_className.assign(start, end);
  77. delete m_newNode;
  78. m_newNode = m_node->newTree(c);
  79. }
  80. // 进/出类
  81. void innerClass(char) { m_node->addChild(m_newNode); m_node = m_newNode; m_newNode = NULL; }
  82. void outterClass(char) { m_node = m_node->parent(); }
  83. // 函数返回类型
  84. void funcReturn(const char* start, const char* end) {
  85. _function f;
  86. f.m_returnType = ParseType(start, end);
  87. m_node->m_value.m_funcs.push_back(f);
  88. }
  89. // 函数名称
  90. void funcName(const char* start, const char* end) {
  91. m_node->m_value.m_funcs.back().m_funcName.assign(start, end);
  92. }
  93. // 函数参数类型
  94. void funcParamType(const char* start, const char* end) {
  95. _func_param fp;
  96. fp.m_paramName.assign(start, end);
  97. m_node->m_value.m_funcs.back().m_funcParams.push_back(fp);
  98. }
  99. // 函数参数名称
  100. void funcParamName(const char* start, const char* end) {
  101. m_node->m_value.m_funcs.back().m_funcParams.back().m_paramType = ParseType(start, end);
  102. }
  103. // 将字符串转换为类型
  104. static type ParseType(const char* start, const char* end) {
  105. std::string s(start, end);
  106. if (s == "void")
  107. return t_void;
  108. if (s == "float")
  109. return t_float;
  110. if (s == "double")
  111. return t_double;
  112. if (s.find("char") != s.npos && s.find("*") != s.npos)
  113. return t_c_str;
  114. return t_undifined;
  115. }
  116.  
  117. private:
  118. class_tree m_root; // 树根节点
  119. class_tree* m_node; // 当前所在节点
  120. class_tree* m_newNode; // 新添加的子节点
  121. };
  122.  
  123. // 删除多行注释/**/
  124. struct EraseComment {
  125.  
  126. EraseComment(const std::string& source) {
  127. m_source.reserve(source.size());
  128. bs::parse_info<> pi = bs::parse(source.c_str(), *(
  129. bs::comment_p("/*", "*/")[boost::bind(&EraseComment::Comment, this, _1, _2)]
  130. | bs::anychar_p[boost::bind(&EraseComment::Anychar, this, _1)]
  131. ));
  132. }
  133.  
  134. const std::string& str() const { return m_source; }
  135.  
  136. private:
  137. static void Comment(EraseComment* self, const char* start, const char* end) {
  138. std::string s(start, end);
  139. }
  140. static void Anychar(EraseComment* self, char ch) {
  141. self->m_source.push_back(ch);
  142. }
  143.  
  144. mutable std::string m_source;
  145. };
  146. }
  147.  
  148. CppClassGrammar::CppClassGrammar()
  149. {
  150. m_class_action = new class_action();
  151. }
  152.  
  153. CppClassGrammar::~CppClassGrammar()
  154. {
  155. delete m_class_action;
  156. m_class_action = NULL;
  157. }
  158.  
  159. bool CppClassGrammar::doParse(const std::string& input)
  160. {
  161. cpp_grammar::EraseComment cmt(input);
  162.  
  163. bs::parse_info<> pi = bs::parse(cmt.str().c_str(), *this, bs::space_p);
  164. return pi.hit;
  165. }
  166.  
  167. cpp_grammar::class_tree& CppClassGrammar::getTree()
  168. {
  169. return m_class_action->getTree();
  170. }
  171.  
  172. template<typename ScannerT>
  173. CppClassGrammar::definition<ScannerT>::definition(const CppClassGrammar& self)
  174. {
  175. // 解析CPP关键字和类型
  176. _cpp_key = bs::str_p("class");
  177. _cpp_type = bs::str_p("void") | "int" | "float" | "double"
  178. | (!bs::str_p("const") >> "char" >> '*');
  179.  
  180. /* 解析单行注释 */
  181. _cpp_comment = bs::comment_p("//")[self.m_class_action->m_comment];
  182.  
  183. /* 解析标示和访问控制权限 */
  184. // 1.class class_name; // 类名
  185. // 2.class class_name {} // 类名
  186. // 3.class class_name : public base {} // 类名
  187. // 4.void func(); // 函数名
  188. // 5.void func(int name); // 函数参数名
  189. // 6.void func(int, int name); // 函数参数名
  190. _identifier = *(~bs::space_p - (bs::ch_p('{') | '(' | ')' | ',' | ';' | ':'));
  191. _access_ctrl = (bs::str_p("public") | "protected" | "private") >> ':';
  192.  
  193. /* 解析函数体(目前只解析括号) */
  194. // 1.{ { 123 };; };;
  195. _tag_brace_nest = (*(bs::anychar_p - '{' - '}')) // 匹配任意字符到'{'或'}'为止
  196. >> '{' // 匹配'{'
  197. >> *_tag_brace_nest // 递归嵌套(括号内可以嵌套括号)
  198. >> *~bs::ch_p('}') >> '}' // 匹配任意字符到'}'为止,匹配'}'
  199. >> *bs::ch_p(';'); // 匹配';'
  200.  
  201. /* 解析函数参数 */
  202. // 1.() // 无参函数
  203. // 2.(int a, int b) // 有参函数(包括参数类型和参数名称)
  204. // 3.(int, int) // 有参函数(只包括参数类型,省略参数名称)
  205. _func_param = _cpp_type[self.m_class_action->m_funcParamType]
  206. >> _identifier[self.m_class_action->m_funcParamName]
  207. >> *(bs::ch_p(',')
  208. >> _cpp_type[self.m_class_action->m_funcParamType]
  209. >> _identifier[self.m_class_action->m_funcParamName]);
  210.  
  211. /* 解析函数 */
  212. // 1.void fun() const;
  213. // 2.void fun() const {}
  214. _function = _cpp_type[self.m_class_action->m_funcReturn] // 匹配函数返回值类型
  215. >> _identifier[self.m_class_action->m_funcName] // 匹配函数名称
  216. >> '(' >> !_func_param >> ')' // 匹配函数参数(匹配0次或1次)
  217. >> *(bs::anychar_p - ';' - '{') // 匹配任意字符到';'或'{'为止
  218. >> (bs::ch_p(';') | _tag_brace_nest); // 匹配';'或函数体(函数体是用'{'和'}'组成的成对字符)
  219.  
  220. /*解析CLASS*/
  221. // 1.class test; 类声明
  222. // 2.class test : public base {}; 类定义
  223. // 当匹配到特定的字符后,便会执行特定的操作[]
  224. _class = bs::str_p("class") // 匹配字符串"class"
  225. >> _identifier[self.m_class_action->m_className] // 匹配类名
  226. >> *(bs::anychar_p - '{' - ';') // 匹配任意字符到'{'或';'为止(前者是识别类定义,后者是识别类声明)
  227. >> bs::ch_p('{')[self.m_class_action->m_innerClass] // 匹配到'{',表示进类主体
  228. >> *(_cpp_comment // 匹配单行注释
  229. | _access_ctrl // 匹配访问权限
  230. | _class // 匹配嵌套类(递归嵌套,理论上N层嵌套类,既嵌套类中也可能存在嵌套类)
  231. | _function // 匹配类成员函数
  232. )
  233. >> bs::ch_p('}')[self.m_class_action->m_outterClass] // 匹配'}',表示出类主体
  234. >> *bs::ch_p(';'); // 类定义结束
  235.  
  236. /**解析整个.h文件,在一个.h文件内,可能会定义多个类*/
  237. _root = *(_cpp_comment | _function | _class | bs::anychar_p);
  238. }

test.cpp

  1. #include "stdafx.h"
  2. #include <fstream>
  3. #include <sstream>
  4. #include <locale>
  5.  
  6. #include "cpp_class_grammar.h"
  7.  
  8. int _tmain(int argc, _TCHAR* argv[])
  9. {
  10. std::vector<std::wstring> filelist;
  11. filelist.reserve(argc - );
  12. for (int i = ; i < argc; ++i) {
  13. std::wstring file = argv[i];
  14. if (file.substr(file.length() - , ) == L".h") {
  15. filelist.push_back(argv[i]);
  16. }
  17. }
  18.  
  19. if (filelist.empty())
  20. return ;
  21.  
  22. std::ifstream fs;
  23. fs.open(filelist.front().c_str());
  24. if (!fs.is_open()) {
  25. return ;
  26. }
  27.  
  28. std::stringstream buffer;
  29. buffer << fs.rdbuf();
  30. std::string input = buffer.str();
  31.  
  32. CppClassGrammar gramar;
  33. bool ret = gramar.doParse(input); // 解析后,生成一个class信息树
  34.  
  35. return ;
  36. }

boost.spirit之解析C++头文件的更多相关文章

  1. WOSA/XFS PTR Form解析库—头文件

    class AFX_EX_CLASS CNuXfsForm {public: CNuXfsForm(); ~CNuXfsForm(); /******************************* ...

  2. C++解析头文件-Qt自动生成信号定义

    目录 一.概述 二.实现思路 三.代码讲解 1.类图 2.QtCppDescription 3.测试 四.源代码 一.概述 上一篇文章C++解析头文件-Qt自动生成信号声明我们主要讲解了怎么去解析C+ ...

  3. boost之词法解析器spirit

    摘要:解析器就是编译原理中的语言的词法分析器,可以按照文法规则提取字符或者单词.功能:接受扫描器的输入,并根据语法规则对输入流进行匹配,匹配成功后执行语义动作,进行输入数据的处理. C++ 程序员需要 ...

  4. 单片机中用c编程时头文件reg51.h及reg52.h解析

    单片机中用c编程时头文件reg51.h及reg52.h解析 我们在用c语言编程是往往第一行就是reg51.h或者其他的自定义头文件,我们怎么样来理解呢? 1)“文件包含”处理. 程序的第一行是一个“文 ...

  5. boost::property_tree读取解析.xml文件

    boost::property_tree读取解析.xml文件 1)read_xml 支持中文路径  boost::property_tree::wptree wpt;    std::locale:: ...

  6. boost::property_tree读取解析ini文件--推荐

    boost::property_tree读取解析ini文件 #include "stdafx.h" #include <iostream> #include <b ...

  7. 头文件 boost/cstdint.hpp

    Header boost/cstdint.hpp 头文件 boost/cstdint.hpp  头文件 <boost/cstdint.hpp> 提供了用于编写要求指定整数宽度的可移植代码的 ...

  8. NSObject头文件解析 / 消息机制 / Runtime解读 (一)

    NSObject头文件解析 当我们需要自定义类都会创建一个NSObject子类, 比如: #import <Foundation/Foundation.h> @interface Clas ...

  9. cstring头文件函数解析

    原创作品,转载请注明来源:http://www.cnblogs.com/shrimp-can/p/5643829.html 在使用由字符数组或指针组成的字符串的时候,要用到一些函数,这些函数通常包含在 ...

随机推荐

  1. C# DataRow[]转换DataTable

    DataTable dt = ... DataRow[] dr = dt.Select("ID=14"); dt = dr.CopyToDataTable();

  2. JQuery笔记(一)jq的使用方法

    我用的jq版本是支持pc版为主的最高1版本里最高的1.124版本 官网的链接是只有最新的3下载,我把我在官网下载的jq代码链接发出来,如下 点我获取jq代码 和js不同的是,jq开发者封装了一些方法 ...

  3. 前端用Request Payload方式请求后台

    后台接收方式: InputStream inputStream = request.getInputStream(); byte[] buff = new byte[1024]; int len = ...

  4. nodejs问题整理--fs.exists无法正确判断文件的问题

    fs.exists方法 方法说明: 测试某个路径下的文件是否存在.回调函数包含一个参数exists,true则文件存在,否则是false. 语法: fs.exists(path, callback) ...

  5. JQuery常用API 核心 效果 JQueryHTML 遍历 Event事件

    JQuery 常用API 参考资料:JQuery 官网   jQuery API 中文文档 核心 jQuery 对象 jQuery() 返回匹配的元素集合,无论是通过在DOM的基础上传递的参数还是创建 ...

  6. python操作----Memcached

    Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度.Memcached ...

  7. Mybatis的失误填坑-java.lang.Integer cannot be cast to java.lang.String

    Mybatis的CRUD小Demo 为方便查看每次的增删改结果,封装了查询,用来显示数据库的记录: public static void showInfo(){ SqlSession session ...

  8. js中三目运算符和&& || 符的个人浅见

    这两天看到别人写的代码,感觉很牛逼,如下,大神请忽视 $(".lgn").on("click", function() { var a = {}; a.logi ...

  9. php 5.5 xhprof for windows

    今天看到一个好的性能优软件xhprof(有facebook开发的类库)在国内找了很多网站都没有找到相关php5.5的扩展,只好FQ还是外面的世界精彩一下就找到了link (http://windows ...

  10. 解决ubuntu下的firefox无法在线播放音频和视频的问题

    一贯无视 Linux 平台的腾讯(无贬义)理所当然地没有开发QQ音乐Linux版,于是想尝试QQ音乐网页版,结果发现歌曲无法播放.刚开始以为是腾讯还在网页版上用万恶的 Windows Media Pl ...