续上篇:http://www.cnblogs.com/qianqians/p/4168332.html
现在来个清晰的语法分析讲解:
为了保持函数声明的上下文语境比如声明与全局,namespace,class之中,我定义了一个简单的状态机
class state(object): STATENONE = 0 STATENORMALFUNC = 1.1 STATECLASSFUNC = 1.2 STATESTATICCLASSFUNC = 1.3 STATEFUNCARGVPAIRBEGIN = 11 STATEFUNCARGVPAIREND = 13 STATEFUNCDEFINE = 14 STATEFUNCACHIVEBEGIN = 15 STATEFUNCACHIVEEND = 16 STATECLASS = 2 STATECLASSACHIVEBEGIN = 21 STATECLASSACHIVEEND = 22 STATECLASSDEFINEEND = 23 STATENAMESPACE = 6 STATENAMESPACEACHIVEBEGIN = 61 STATENAMESPACEACHIVEEND = 62 STATENAMESPACEDEFINEEND = 63 STATESTATIC = 3 STATESECTIONEND = 4 STATERPCCALL = 5 STATEPREPROCESS = 7 def __init__(self, parentstate): self.pairstate = 0 self.attachstate = state.STATENONE self.state = state.STATENONE self.rpcstate = state.STATENONE self.achivestate = state.STATENONE self.statechange = False self.clearcache = False self.parentstate = parentstate def pop(self): if self.parentstate != None: return self.parentstate self.pairstate = 0 self.state = state.STATENONE self.attachstate = state.STATENONE self.state = state.STATENONE self.rpcstate = state.STATENONE self.achivestate = state.STATENONE return self def is_need_clear(self): return self.clearcache def is_func(self): return self.state == state.STATECLASSFUNC or self.state == state.STATESTATICCLASSFUNC or self.state == state.STATENORMALFUNC def is_change(self): return self.statechange def is_pair(self): return self.pairstate > 0 def is_wait_check(self): return self.state == state.STATENONE or (self.state == state.STATECLASS and self.achivestate == state.STATECLASSACHIVEBEGIN) or (self.state == state.STATENAMESPACE and self.achivestate == state.STATENAMESPACEACHIVEBEGIN)
这个状态机就保存了上级的语境,并且在语境变换的时候,生成一个下级的状态机
if keyword == v[‘key‘]: if _state.state != state.STATENONE: _state = state(_state)
如代码所见,在语境变换的时候,定义了一个下级的状态机_state = state(_state)
然后在当前语境结束,比如函数声明结束,class namespace定义结束,则pop到上级语境
if s.achivestate == ruletable.state.STATESECTIONEND: _statemachine.state = _statemachine.state.pop() tempkeywork = []
对语境的判断,属于语法分析的范围,我定义了一个简单的c++语法规则如下:
preprocessrule = {‘key‘:‘#‘, ‘end‘:‘\n‘, ‘keyword‘:{‘include‘:{‘pairbegin‘:‘<‘, ‘pairend‘:‘>‘}, ‘pragma‘:{}, ‘if‘:{‘endkey‘:‘endif‘}, ‘endif‘:{}, ‘define‘:{}}} pair = {‘pairbegin‘:‘<‘, ‘pairend‘:‘>‘} rule = {‘namespace‘:{‘key‘:‘namespace‘, ‘achivebegin‘:‘{‘, ‘achiveend‘:‘}‘, ‘defineend‘:‘}‘}, ‘class‘:{‘key‘:‘class‘, ‘achivebegin‘:‘{‘, ‘achiveend‘:‘}‘, ‘defineend‘:‘;‘}, ‘func‘:{‘key‘:‘(‘, ‘argvbegin‘:‘(‘, ‘argvend‘:‘)‘, ‘argvsplit‘:‘,‘, ‘defineend‘:‘;‘, ‘achivebegin‘:‘{‘, ‘achiveend‘:‘}‘, ‘achivedefineend‘:‘}‘, ‘rpc‘:‘RPCCALL‘}, ‘template‘:{‘key‘:‘template‘, ‘templateargvbegin‘:‘<‘, ‘templateargvend‘:‘>‘}, ‘preprocessrule‘:preprocessrule}
在检查到defineend之类的关键字,且状态在该语法语境类,则切换到语境结束状态
if k == ‘defineend‘ and state.achivestate == state.STATEFUNCARGVPAIREND: state.achivestate = state.STATESECTIONEND if k == ‘defineend‘ and state.achivestate == state.STATENAMESPACEACHIVEEND: state.achivestate = state.STATENAMESPACEDEFINEEND if k == ‘defineend‘ and state.achivestate == state.STATECLASSACHIVEEND: state.achivestate = state.STATESECTIONEND
基于这样一个词法和语法分析的过程,最终可以分析出代码中的函数声明如下:
{‘acceptservice.h‘: {‘templateclassfunc‘: {}, ‘classfunc‘: {‘acceptservice‘: [[‘std::tuple<int, std::string, float>‘, ‘run_network‘, ‘int count‘], [‘std::pair<int, int>‘, ‘run_network‘, ‘int count‘, ‘int count1‘]]}, ‘globalfunc‘: [[‘std::string‘, ‘init‘]], ‘templateglobalfunc‘: []}}
然后基于这样一组关键字表,即可用于代码生成。
def codegenclient(rpcsysmbal): if not os.path.isdir(build_path): os.mkdir(build_path) for k,v in rpcsysmbal.items(): code = ‘#include <IRemoteEndpoint.h>\n\n‘ for sysmbal in v[‘globalfunc‘]: code += sysmbal[0] + ‘ ‘ + sysmbal[1] + ‘(IRemoteEndpoint ep‘ funcsys = sysmbal[1] avgr = sysmbal[2:] for i in xrange(len(avgr)): code += ‘, ‘ + avgr[i] code += ‘){\n‘ code += ‘ boost::shared_ptr<session> s = GetSession(ep);\n\n‘ code += ‘ Json::Value value;\n‘ code += ‘ value[\‘epuuid\‘] = ‘ + ‘s.enppui();\n‘ code += ‘ value[\‘suuid\‘] = UUID();\n‘ code += ‘ value[\‘eventtype\‘] = \‘rpc_event\‘;\n‘ code += ‘ value[\‘rpc_event_type\‘] = \‘call_rpc_mothed\‘;\n‘ code += ‘ value[\‘fnargv\‘] = Json::Value(Json::objectValue) ;\n‘ for sys in xrange(len(avgr)): syss = avgr[sys].split(‘ ‘) funcsys += ‘_‘ + syss[0] code += ‘ value[\‘fnargv\‘][\‘‘ + syss[1] + ‘\‘] = ‘ + syss[1] + ‘;‘ code += ‘ value[\‘fnname\‘] = \‘‘ + funcsys + ‘\‘;\n‘ code += ‘ s->do_push(s, value);\n\n‘ code += ‘ Json::Value ret = _service_handle->wait(value[\‘suuid\‘].asString(), 1);\n‘ code += ‘ if (ret[\‘suuid\‘] != value[\‘suuid\‘]){\n throw std::exception(\"error suuid\")\n }\n‘ if sysmbal[0] != ‘void‘: code += ‘\n return ‘ if sysmbal[0].find(‘std::pair‘) != -1 or sysmbal[0].find(‘pair‘) != -1: index = sysmbal[0].find(‘std::pair‘) if index == -1: index = sysmbal[0].find(‘pair‘) temavgr = sysmbal[0][index + 6: -1].split(‘,‘) code += ‘std::make_pair(‘ for i in xrange(len(temavgr)): code += ‘ret[\‘rpcret\‘][ret‘ + str(i) + ‘].‘ + returntype(temavgr[i]) code += ‘);\n‘ elif sysmbal[0] is ‘std::tuple‘ or sysmbal[0] is ‘tuple‘: index = sysmbal[0].find(‘std::tuple‘) if index == -1: index = sysmbal[0].find(‘tuple‘) temavgr = sysmbal[0][index + 6: -1].split(‘,‘) code += ‘std::make_tuple(‘ for i in xrange(len(temavgr)): code += ‘ret[\‘rpcret\‘][ret‘ + str(i) + ‘].‘ + returntype(temavgr[i]) code += ‘);\n‘ else: code += ‘ ret[\‘rpcret\‘].‘ + returntype(sysmbal[0]) + ‘;\n‘ code += ‘}\n\n‘ for classname, sysmbal in v[‘classfunc‘].items(): code += ‘class ‘ + classname + ‘{\n‘ + ‘private:\n‘ + ‘ IRemoteEndpoint ep;\n\n‘ code += ‘ ‘ + classname + ‘(IRemoteEndpoint _ep){\n ep = _ep;\n }\n\n‘ code += ‘public:\n‘ for func in sysmbal: code += ‘ ‘ + func[0] + ‘ ‘ + func[1] + ‘(‘ funcsys = func[1] avgr = func[3:] code += func[2] for i in xrange(len(avgr)): code += ‘, ‘ + avgr[i] code += ‘){\n‘ code += ‘ boost::shared_ptr<session> s = GetSession(ep);\n\n‘ code += ‘ Json::Value value;\n‘ code += ‘ value[\‘epuuid\‘] = ‘ + ‘s.enppui();\n‘ code += ‘ value[\‘suuid\‘] = UUID();\n‘ code += ‘ value[\‘eventtype\‘] = \‘rpc_event\‘;\n‘ code += ‘ value[\‘rpc_event_type\‘] = \‘call_rpc_mothed\‘;\n‘ code += ‘ value[\‘fnargv\‘] = Json::Value(Json::objectValue) ;\n‘ avgr = func[2:] for sys in xrange(len(avgr)): syss = avgr[sys].split(‘ ‘) funcsys += ‘_‘ + syss[0] code += ‘ value[\‘fnargv\‘][\‘‘ + syss[1] + ‘\‘] = ‘ + syss[1] + ‘;\n‘ code += ‘ value[\‘fnname\‘] = \‘‘ + funcsys + ‘\‘;\n‘ code += ‘ s->do_push(s, value);\n\n‘ code += ‘ Json::Value ret = _service_handle->wait(value[\‘suuid\‘].asString(), 1);\n‘ code += ‘ if (ret[\‘suuid\‘] != value[\‘suuid\‘]){\n throw std::exception(\"error suuid\")\n }\n‘ if func[0] != ‘void‘: code += ‘\n return ‘ if func[0].find(‘std::pair‘) != -1 or func[0].find(‘pair‘) != -1: temavgr = func[0][func[0].find(‘<‘) + 1: -1].split(‘,‘) code += ‘std::make_pair(‘ for i in xrange(len(temavgr)): if i != len(temavgr) - 1: code += ‘ret[\‘rpcret\‘][ret‘ + str(i) + ‘].‘ + returntype(deleteNoneSpacelstrip(temavgr[i])) + ‘, ‘ else: code += ‘ret[\‘rpcret\‘][ret‘ + str(i) + ‘].‘ + returntype(deleteNoneSpacelstrip(temavgr[i])) code += ‘);\n‘ elif func[0].find(‘std::tuple‘) != -1 or func[0].find(‘tuple‘) != -1: temavgr = func[0][func[0].find(‘<‘) + 1: -1].split(‘,‘) code += ‘std::make_tuple(‘ for i in xrange(len(temavgr)): if i != len(temavgr) - 1: code += ‘ret[\‘rpcret\‘][‘ + str(i) + ‘].‘ + returntype(deleteNoneSpacelstrip(temavgr[i])) + ‘, ‘ else: code += ‘ret[\‘rpcret\‘][‘ + str(i) + ‘].‘ + returntype(deleteNoneSpacelstrip(temavgr[i])) code += ‘);\n‘ else: code += ‘ ret[\‘rpcret\‘];\n‘ code += ‘ }\n\n‘ code += ‘};\n\n‘ if code != ‘#include <IRemoteEndpoint.h>\n\n‘: file = open(build_path + k, ‘w‘) file.write(code)
最后生成的代码如下:
#include <IRemoteEndpoint.h> std::string init(IRemoteEndpoint ep){ boost::shared_ptr<session> s = GetSession(ep); Json::Value value; value[‘epuuid‘] = s.enppui(); value[‘suuid‘] = UUID(); value[‘eventtype‘] = ‘rpc_event‘; value[‘rpc_event_type‘] = ‘call_rpc_mothed‘; value[‘fnargv‘] = Json::Value(Json::objectValue) ; value[‘fnname‘] = ‘init‘; s->do_push(s, value); Json::Value ret = _service_handle->wait(value[‘suuid‘].asString(), 1); if (ret[‘suuid‘] != value[‘suuid‘]){ throw std::exception("error suuid") } return ret[‘rpcret‘].asString(); } class acceptservice{ private: IRemoteEndpoint ep; acceptservice(IRemoteEndpoint _ep){ ep = _ep; } public: std::tuple<int, std::string, float> run_network(int count){ boost::shared_ptr<session> s = GetSession(ep); Json::Value value; value[‘epuuid‘] = s.enppui(); value[‘suuid‘] = UUID(); value[‘eventtype‘] = ‘rpc_event‘; value[‘rpc_event_type‘] = ‘call_rpc_mothed‘; value[‘fnargv‘] = Json::Value(Json::objectValue) ; value[‘fnargv‘][‘count‘] = count; value[‘fnname‘] = ‘run_network_int‘; s->do_push(s, value); Json::Value ret = _service_handle->wait(value[‘suuid‘].asString(), 1); if (ret[‘suuid‘] != value[‘suuid‘]){ throw std::exception("error suuid") } return std::make_tuple(ret[‘rpcret‘][0].asInt(), ret[‘rpcret‘][1].asString(), ret[‘rpcret‘][2].asFloat()); } std::pair<int, int> run_network(int count, int count1){ boost::shared_ptr<session> s = GetSession(ep); Json::Value value; value[‘epuuid‘] = s.enppui(); value[‘suuid‘] = UUID(); value[‘eventtype‘] = ‘rpc_event‘; value[‘rpc_event_type‘] = ‘call_rpc_mothed‘; value[‘fnargv‘] = Json::Value(Json::objectValue) ; value[‘fnargv‘][‘count‘] = count; value[‘fnargv‘][‘count1‘] = count1; value[‘fnname‘] = ‘run_network_int_int‘; s->do_push(s, value); Json::Value ret = _service_handle->wait(value[‘suuid‘].asString(), 1); if (ret[‘suuid‘] != value[‘suuid‘]){ throw std::exception("error suuid") } return std::make_pair(ret[‘rpcret‘][ret0].asInt(), ret[‘rpcret‘][ret1].asInt()); } };
然后大致如此: 这次就不要求抄对了,因为看懂都蛮难的:)
然后开始骂人:),赏给在tx的前同事 什么 陈磊(qq 110086478, 手机 13524139363),什么钱陈(手机 18603014436,qq 281795034)啥的,为了防搞错人,附上QQ,手机!直接附上真名实性嘛,是因为你们长的丑,我讨厌你们
先盘点下这几年做的东西:
https://github.com/qianqians/tstates/tree/master/symbol_analytical tstate在tx做的监控采集工具
傻B你做了啥!
https://github.com/qianqians/vchat 在冰冻做的语音聊天框架
傻B你做了啥!
https://github.com/qianqians/Hemsleya/tree/master/Hemsleya/base/active 基于协程的任务调度框架
傻B你做了啥!
https://github.com/qianqians/Hemsleya/tree/master/Hemsleya/base/concurrent/pool 内存池
傻B你做了啥!
https://github.com/qianqians/Fossilizid/tree/master/reliably-%20transmission 在冰冻做的udp可靠性传输
傻B你做了啥!
https://github.com/qianqians/Fossilizid/tree/master/remote-queue 一个长的好看的网络库
傻B你做了啥!
https://github.com/qianqians/Fossilizid/tree/master/reduce-rpc/service 服务器框架
傻B你做了啥!
https://github.com/qianqians/Fossilizid/tree/master/reduce-rpc/rpcmake 一个codegen
傻B 你codegen都写不出来 就滚回家做编译原理的大作业去吧!