def DumpDirExt(file_ext, input_path, hrl_target_path, erl_target_path, func): filelist = [] if os.path.isfile(input_path): filelist.append(input_path) elif os.path.isdir(input_path): filelist = glob.glob(input_path + "//*" + file_ext) assert len(filelist) > 0 def mkdir(path): target_path = os.path.dirname(path) if not os.path.isdir(target_path): os.mkdir(target_path) mkdir(hrl_target_path) mkdir(erl_target_path) erl_printer = Printer(erl_target_path) hrl_printer = Printer(hrl_target_path) module_name = os.path.basename(os.path.splitext(erl_target_path)[0]) GenerateHeader(erl_printer, module_name) for filename in filelist: func(filename, erl_printer, hrl_printer) GenerateTailor(erl_printer) erl_printer.Flush() hrl_printer.Flush()
def Transform(filename, out): lines = open(filename).readlines() printer = Printer(out) printer.AppendLine("// Generated by inltoas.py. DO NOT EDIT!") printer.AppendLine("namespace GameProtocol") printer.AppendLine("{") printer.IncIndent() printer.AppendLine("public sealed class MessageType") printer.AppendLine("{") printer.IncIndent() re_assign = re.compile("MSGTYPE_DECLARE_ASSIGN\((\S+),\s*(\d+)\)") re_declare = re.compile("MSGTYPE_DECLARE\(\s*(\S+)\s*\)") index = 0 for line in lines: if "MSGTYPE_BEGIN_BLOCK" in line: pass # prase assign state what = re_assign.match(line) if what != None: msgName = what.groups()[0] assIndex = what.groups()[1] comment = GetComment(line) printer.AppendLine( "public const short %s = %s; // %s" % (msgName, assIndex, comment.decode("gbk").encode("utf8"))) index = int(assIndex) continue # parse declcare statements what = re_declare.match(line) if what != None: msgName = what.groups()[0] comment = GetComment(line) assIndex = index + 1 printer.AppendLine( "public const short %s = %s; // %s" % (msgName, assIndex, comment.decode("gbk").encode("utf8"))) index = assIndex continue line = line.strip() if line.startswith("//") or len(line) == 0: printer.AppendLine("%s" % line.decode("gbk").encode("utf8")) else: printer.AppendLine("// %s" % line.decode("gbk").encode("utf8")) printer.DecIndent() printer.AppendLine("}") printer.DecIndent() printer.AppendLine("}") printer.Flush()
def Transform(filename, out): lines = open(filename).readlines() printer = Printer(out) printer.AppendLine("# -*- coding: utf8 -*-") printer.AppendLine("# Generated by inltoas.py. DO NOT EDIT!") re_assign = re.compile("MSGTYPE_DECLARE_ASSIGN\((\S+),\s*(\d+)\)") re_declare = re.compile("MSGTYPE_DECLARE\(\s*(\S+)\s*\)") index = 0 for line in lines: if "MSGTYPE_BEGIN_BLOCK" in line: pass # prase assign state what = re_assign.match(line) if what != None: msgName = what.groups()[0] assIndex = what.groups()[1] comment = GetComment(line) printer.AppendLine("%s = %s # %s" % (msgName, assIndex, ToCode(comment))) index = int(assIndex) continue # parse declcare statements what = re_declare.match(line) if what != None: msgName = what.groups()[0] comment = GetComment(line) assIndex = index + 1 printer.AppendLine("%s = %s; # %s" % (msgName, assIndex, ToCode(comment))) index = assIndex continue line = line.strip() if line.startswith("//") or len(line) == 0: printer.AppendLine("# %s" % ToCode(line)) else: printer.AppendLine("# %s" % ToCode(line)) printer.Flush()
def Transform(filename, out): parsed = [] lines = open(filename).readlines() printer = Printer(out) printer.AppendLine("package SystemErr") printer.AppendLine("") printer.AppendLine("// Generated by errinltogo.py. DO NOT EDIT!") printer.AppendLine("") printer.AppendLine("const ( // SystemErr") printer.IncIndent() re_declare = re.compile("ERR_MSG_DECLARE\((\S+),\s*(\d+),\s*\"(.+)\"\)") index = 0 for line in lines: # prase assign state what = re_declare.match(line) if what is not None: msgName = what.groups()[0] assIndex = what.groups()[1] comment = what.groups()[2].decode("gbk", "ignore").encode('utf8') printer.AppendLine("%s int32 = %s // %s" % (msgName, assIndex, comment)) index = int(assIndex) continue line = line.strip() if line.startswith("//") or len(line) == 0: printer.AppendLine("%s" % line.decode("gbk", "ignore").encode('utf8')) else: printer.AppendLine("// %s" % line.decode("gbk", "ignore").encode('utf8')) printer.DecIndent() printer.AppendLine(")") printer.AppendLine("") printer.Flush()
def Transform(filename, out): lines = open(filename).readlines() printer = Printer(out) printer.AppendLine("// Generated by inltoas.py. DO NOT EDIT!") printer.AppendLine("package client.model") printer.AppendLine("{") printer.IncIndent() printer.AppendLine("public final class WindowId") printer.AppendLine("{") printer.IncIndent() re_declare = re.compile("WINDOW_ID\(\s*(\S+)\s*\)") index = 0 for line in lines: if "WID_BEGIN_BLOCK" in line: pass # parse declcare statements what = re_declare.match(line) if what != None: msgName = what.groups()[0] comment = GetComment(line) assIndex = index + 1 printer.AppendLine( 'public static const %s:int = %s; // %s' % (msgName, assIndex, comment.decode("gbk").encode("utf8"))) index = assIndex continue line = line.strip() if line.startswith("//") or len(line) == 0: printer.AppendLine("%s" % line.decode("gbk").encode("utf8")) else: printer.AppendLine("// %s" % line.decode("gbk").encode("utf8")) printer.DecIndent() printer.AppendLine("}") printer.DecIndent() printer.AppendLine("}") printer.Flush()
def Transform(filename, out): lines = open(filename).readlines() printer = Printer(out) printer.AppendLine("// Generated by inltoas.py. DO NOT EDIT!") printer.AppendLine("package sixcube.protocol") printer.AppendLine("{") printer.IncIndent() printer.AppendLine("public final class MessageType") printer.AppendLine("{") printer.IncIndent() re_assign = re.compile("MSGTYPE_DECLARE_ASSIGN\((\S+),\s*(\d+)\)") re_declare = re.compile("MSGTYPE_DECLARE\(\s*(\S+)\s*\)") msgIdCheck = {} index = 0 for line in lines: if "MSGTYPE_BEGIN_BLOCK" in line: pass # prase assign state what = re_assign.match(line) if what != None: msgName = what.groups()[0] assIndex = what.groups()[1] comment = GetComment(line) index = int(assIndex) if msgIdCheck.has_key(index): print "[ERROR]same msg id: \n\t[%s = %s]\n\t[%s = %s]" % ( msgIdCheck[index], index, msgName, index) sys.exit(-1) printer.AppendLine("public static var %s:int = %s; // %s" % (msgName, assIndex, comment)) msgIdCheck[index] = msgName continue # parse declcare statements what = re_declare.match(line) if what != None: msgName = what.groups()[0] comment = GetComment(line) assIndex = index + 1 if msgIdCheck.has_key(assIndex): print "[ERROR]same msg id = %s: [%s][%s]\%s" % ( assIndex, msgIdCheck[assIndex], msgName) sys.exit(-1) printer.AppendLine("public static const %s:int = %s; // %s" % (msgName, assIndex, comment)) msgIdCheck[assIndex] = msgName index = assIndex continue line = line.strip() line = line.decode('gbk', 'ignore').encode('utf8') if line.startswith("//") or len(line) == 0: printer.AppendLine("%s" % line) else: printer.AppendLine("// %s" % line) printer.DecIndent() printer.AppendLine("}") printer.DecIndent() printer.AppendLine("}") printer.Flush()
def Transform(filename, out): lines = open(filename).readlines() printer = Printer(out) printer.AppendLine("// Generated by inltoas.py. DO NOT EDIT!") printer.AppendLine("package client.message") printer.AppendLine("{") printer.IncIndent() printer.AppendLine("import flash.events.Event;") printer.AppendLine("public class Message extends Event") printer.AppendLine("{") printer.IncIndent() re_assign = re.compile("MSGTYPE_DECLARE_ASSIGN\((\S+),\s*(\d+)\)") re_declare = re.compile("MSGTYPE_DECLARE\(\s*(\S+)\s*\)") index = 0 for line in lines: if "MSGTYPE_BEGIN_BLOCK" in line: pass # prase assign state what = re_assign.match(line) if what != None: msgName = what.groups()[0] assIndex = what.groups()[1] comment = GetComment(line) printer.AppendLine( 'public var %s:Object = new Object; //%s %s;' % (msgName, assIndex, comment.decode("gbk").encode("utf8"))) index = int(assIndex) continue # parse declcare statements what = re_declare.match(line) if what != None: msgName = what.groups()[0] comment = GetComment(line) assIndex = index + 1 printer.AppendLine( 'public static const %s:String = "%s"; // %s' % (msgName, assIndex, comment.decode("gbk").encode("utf8"))) index = assIndex continue line = line.strip() if line.startswith("//") or len(line) == 0: printer.AppendLine("%s" % line.decode("gbk").encode("utf8")) else: printer.AppendLine("// %s" % line.decode("gbk").encode("utf8")) printer.DecIndent() printer.IncIndent() printer.AppendLine( "public function Message(type:String, bubbles:Boolean=false, cancelable:Boolean=false)" ) printer.AppendLine("{") printer.IncIndent() printer.AppendLine("super(type, bubbles, cancelable);") printer.DecIndent() printer.AppendLine("}") printer.DecIndent() printer.AppendLine("}") printer.DecIndent() printer.AppendLine("}") printer.Flush()
class CppGenerator: def __init__(self, outdir): self.enum_list = set() self.class_list = [] self.package_list = [] self.has_namespace = False self.namespace_name = '' self.offset = 0 self.printer = Printer() self.buildin_type = [ "int", "char", "short", "UINT32", "INT32", "string", "std::string", "UINT16", "INT16", "BYTE", "ZGID", "bool", "float", "double", "UINT64", "INT64", "CHAR", "INT", "UINT8", "FLOAT" ] self.outdir = outdir def OnAddNode(self, node): if node.token == "package": self.package_list.append(node) elif node.token == "enum_stmt": self.enum_list.add(node) elif node.token == "message_stmt": self.class_list.append(node) def IsEnumType(self, type_name): for enum in self.enum_list: #print "enum:", enum if enum.value == type_name: return True return False def IsMessageType(self, type_name): for type in self.class_list: #print "enum:", enum if type.value == type_name: return True return False def IsValidType(self, type_name): if type_name in self.buildin_type: return True if self.IsEnumType(type_name): return True if self.IsMessageType(type_name): return True return False def GenerateCppHeader(self, filename): self.printer.AppendLine("// This file was generator by proto_to_cpp.py. DO NOT MODIFY MANNUAL.") self.printer.AppendLine("") self.printer.AppendLine("#ifndef __%s__" % filename.replace('.', '_').upper()) self.printer.AppendLine("#define __%s__" % filename.replace('.', '_').upper()) self.printer.AppendLine("") self.printer.AppendLine("#include <net/PacketBase.h>") self.printer.AppendLine("") def GenerateCppTailor(self, filename): self.printer.AppendLine("#endif // %s\n" % filename.replace('.', '_').upper()) def DetermineOuputPath(self, input_file_path): basename = os.path.basename(os.path.splitext(input_file_path)[0]) output_file_name = basename + ".pb.h" if self.outdir != None: output_file_path = os.path.join(self.outdir, output_file_name) else: output_file_path = None return output_file_name, output_file_path def Generate(self, tree, input_file_path): if self.outdir != None and not os.path.exists(self.outdir): os.mkdir(self.outdir) self.input_dir = os.path.dirname(input_file_path) output_file_name, output_file_path = self.DetermineOuputPath(input_file_path) self.printer = Printer(output_file_path) self.GenerateCppHeader(output_file_name) s = tree.Apply(self) if self.has_namespace: s = "namespace %s {\n\n%s}" % (self.namespace_name, s) self.GenerateCppTailor(output_file_name) self.printer.Flush() def GetParamType(self, var_type): """ Convert parameter type to C++ type. now there are two rules: 1. All build-in type pass by value, otherwise pass by refrence. 2. We use std::string to represent string type. """ if var_type in ['int', 'int32', 'uint', 'uint32', 'byte', 'int64', 'UINT32', 'UINT16', 'INT32', 'float']: return var_type elif self.IsEnumType(var_type): return var_type elif FIXSTR_TAG in var_type: return "const std::string&" elif var_type == 'string': return "const std::%s&" % var_type else: return "const %s&" % var_type def GetParamName(self, var_name): if len(var_name) > 2 and var_name[:2] == 'm_': return var_name[2:] else: return '_' + var_name def GeneratePara(self, node): assert node.token == 'field_stmt' var_lable, var_type, var_name = node.value[0:3] if var_lable in ['required', 'optional']: return "%s %s" % (self.GetParamType(var_type), self.GetParamName(var_name)) elif var_lable == 'repeated': return "const std::vector<%s>& %s" % (self.GetCppType(var_type), self.GetParamName(var_name)) else: raise "%s" % var_lable def GenerateReadConstructor(self, node): self.printer.AppendLine("/// constructor ") self.printer.AppendLine("explicit %s(NetMessage* pMsg)" % node.value) self.printer.AppendLine(": PacketBase(pMsg)") self.printer.AppendLine("{") self.printer.IncIndent() self.printer.AppendLine("GetStream() >> *this;") self.printer.DecIndent() self.printer.AppendLine("}\n") return '' def GenerateReadFromStream(self, node): self.printer.AppendLine("/// overload operator>>, read from stream ") self.printer.AppendLine("friend NetMessage& operator>>(NetMessage& inputStream, %s& v)" % node.value) self.printer.AppendLine("{") self.printer.IncIndent() memberCount = 0 for child in node.childs: if child.token != "field_stmt": continue memberCount += 1 field_lable, field_type, field_name, field_index = child.value if field_lable == "required": if self.IsEnumType(field_type): self.printer.AppendLine("v.%s = static_cast<%s>(inputStream.ReadD());" \ % (field_name, field_type)) elif FIXSTR_TAG in field_type: self.printer.AppendLine("{"); self.printer.IncIndent() self.printer.AppendLine("size_t n = inputStream.ReadH();") self.printer.AppendLine("if (n >= sizeof(v.%s)) { n = sizeof(v.%s); } else { v.%s[n] = '\\0'; }" % ( field_name, field_name, field_name)) self.printer.AppendLine("for (size_t i = 0; i < n; ++i) { inputStream >> v.%s[i]; };" % field_name) self.printer.DecIndent() self.printer.AppendLine("}"); else: self.printer.AppendLine("inputStream >> v.%s;" % field_name) elif field_lable == "repeated": self.printer.AppendLine("{") self.printer.IncIndent() self.printer.AppendLine("size_t n = inputStream.ReadH();") self.printer.AppendLine("v.%s.resize(n);" % field_name); self.printer.AppendLine("for (size_t i = 0; i < n; ++i) { inputStream >> v.%s[i]; };" % field_name) self.printer.DecIndent() self.printer.AppendLine("}") if memberCount == 0: self.printer.AppendLine("UNUSED_ARG(v);") self.printer.AppendLine("return inputStream;") self.printer.DecIndent() self.printer.AppendLine("}") def GenerateWriteConstructor(self, node): # Constructor from data result = "" para_list = "" init_list = "" for child in node.childs: if child.token != "field_stmt": continue para_list += (", " + self.GeneratePara(child)) init_list += ", %s(%s)" % (child.value[2], self.GetParamName(child.value[2])) para_list = "ClientId cid" + para_list #参数列表 self.printer.AppendLine("/// constructor ") self.printer.AppendLine("%s(%s)" % (node.value, para_list)) # 基类初始化 self.printer.AppendLine(": PacketBase(THIS_MSG_TYPE, cid, DEFAULT_PACKET_SIZE)") # 类初始化类表 if init_list != "": self.printer.AppendLine("%s" % init_list) self.printer.AppendLine("{") self.printer.IncIndent() self.printer.AppendLine("GetStream() << *this;") self.printer.DecIndent() self.printer.AppendLine("}\n") return result def GenerateRewirteStream(self, node): #参数列表 self.printer.AppendLine("/// rewrite to stream ") self.printer.AppendLine("void RewirteToStream()") self.printer.AppendLine("{") self.printer.IncIndent() self.printer.AppendLine("if (m_pMsg) DestroyMessage(m_pMsg); \n") self.printer.AppendLine("m_pMsg = new NetMessage(DEFAULT_PACKET_SIZE + HDR_LEN, THIS_MSG_TYPE, 0);") self.printer.AppendLine("GetStream() << *this;") self.printer.DecIndent() self.printer.AppendLine("}\n") def GenerateSimpleConstructor(self, node): # Constructor from data result = "" para_list = "" init_list = "" null_init_list = "" assign_list = [] null_assign_list = [] for child in node.childs: if child.token != "field_stmt": continue if para_list != "": para_list += ", " para_list += self.GeneratePara(child) var_lable, var_type, var_name = child.value[0:3] if FIXSTR_TAG in var_type: assign_list.append("strncpy(%s, %s.c_str(), sizeof(%s));" \ % (var_name, self.GetParamName(var_name), var_name)); null_assign_list.append("memset(%s, 0, sizeof(%s));" % (var_name, var_name)); continue if init_list != "": init_list += ", " null_init_list += ", " init_list += "%s(%s)" % (var_name, self.GetParamName(var_name)) null_init_list += "%s()" % var_name #参数列表 self.printer.AppendLine("/// constructor ") self.printer.AppendLine("%s(%s)" % (node.value, para_list)) # 基类初始化 # 类初始化类表 if init_list != "": self.printer.AppendLine(": %s" % init_list) self.printer.AppendLine("{") self.printer.IncIndent() for line in assign_list: self.printer.AppendLine(line) self.printer.DecIndent() self.printer.AppendLine("}\n") # default constrctor self.printer.AppendLine("/// default consturctor") self.printer.AppendLine("%s()" % node.value) if null_init_list != "": self.printer.AppendLine(": %s" % null_init_list) self.printer.AppendLine("{") self.printer.IncIndent() for line in null_assign_list: self.printer.AppendLine(line) self.printer.DecIndent() self.printer.AppendLine("}\n") return result def GenerateWriteToStream(self, node): self.printer.AppendLine("/// overload operator<<, write to stream ") self.printer.AppendLine("friend NetMessage& operator<<(NetMessage& outputStream, %s& v)" % node.value) self.printer.AppendLine("{") self.printer.IncIndent() memberCount = 0 for field in node.childs: if field.token != "field_stmt": continue memberCount += 1 field_lable, field_type, field_name, field_index = field.value if field_lable == "required": if self.IsEnumType(field_type): self.printer.AppendLine("outputStream << static_cast<int>(v.%s);" % field_name) elif FIXSTR_TAG in field_type: self.printer.AppendLine("outputStream << static_cast<UINT16>(sizeof(v.%s));" % field_name); self.printer.AppendLine("for(size_t i = 0; i < sizeof(v.%s);++i) { outputStream << v.%s[i];}" \ % (field_name, field_name)) else: self.printer.AppendLine("outputStream << v.%s;" % field_name) elif field_lable == "repeated": self.printer.AppendLine("outputStream << static_cast<UINT16>(v.%s.size());" % field_name) self.printer.AppendLine("for(size_t i = 0; i < v.%s.size(); ++i) { outputStream << v.%s[i]; }" \ % (field_name, field_name)) if memberCount == 0: self.printer.AppendLine("UNUSED_ARG(v);") self.printer.AppendLine("return outputStream;") self.printer.DecIndent() self.printer.AppendLine("}") def NeedConstructor(self, node): for child in node.childs: if child.token == "enum_stmt": if child.childs[0].value[0] == "THIS_MSG_TYPE": return True return False def GenerateMessageDef(self, node): if self.NeedConstructor(node): self.printer.AppendLine("class %s : public PacketBase" % (node.value)) else: self.printer.AppendLine("class %s" % (node.value)) self.printer.AppendLine("{") self.printer.AppendLine("public:") self.printer.IncIndent() # Constructor from Message def GenerateMessageMethod(self, node): if self.NeedConstructor(node): self.GenerateReadConstructor(node) self.GenerateWriteConstructor(node) self.GenerateRewirteStream(node) else: self.GenerateSimpleConstructor(node) self.GenerateReadFromStream(node) self.GenerateWriteToStream(node) def GetCppType(self, typename): if typename == "string": return "std::string" else: return typename def ImportFile(self, filename): """ Extract all enum and message define from the import file """ import_file_path = os.path.join(self.input_dir, filename + ".proto") enum_list, class_list = FindCachedProtoTypes(import_file_path) self.enum_list = self.enum_list.union(enum_list) self.class_list += class_list def BeginNode(self, node): result = '' if node.token == "import_stmt": self.ImportFile(node.value) self.printer.AppendLine("#include \"%s.pb.h\"" % node.value) elif node.token == "package_stmt": self.namespace_name = node.value self.has_namespace = True elif node.token == "enum_stmt": if node.value == "unnamed": self.printer.AppendLine("enum {") else: self.printer.AppendLine("enum %s {" % (node.value)) self.printer.IncIndent() elif node.token == "enum_field_stmt": self.printer.AppendLine("%s = %s," % (node.value[0], node.value[1])) self.printer.sameLine = True elif node.token == "comment": self.printer.AppendComment(node.value) elif node.token in ["root", "option_stmt"]: pass elif node.token == "message_stmt": self.GenerateMessageDef(node) elif node.token == "struct_stmt": self.printer.AppendLine("struct %s {" % (node.value)) self.printer.IncIndent() elif node.token == "struct_field_stmt": if len(node.value) == 2: self.printer.AppendLine("%s %s;\n" % (node.value[0], node.value[1])) else: self.printer.AppendLine("%s %s[%s];\n" % (node.value[0], node.value[1], node.value[2])) self.printer.sameLine = True elif node.token == "field_stmt": #print node.value field_lable = node.value[0] field_type = node.value[1] field_name = node.value[2] if not self.IsValidType(field_type): print "TYPE: %s is not declared" % field_type if field_lable != "repeated": if FIXSTR_TAG not in field_type: self.printer.AppendLine(("%s %s;" % (self.GetCppType(field_type), field_name))) else: self.printer.AppendLine("char %s[%d];" % (field_name, self.GetFixStrLen(field_type))) else: assert FIXSTR_TAG not in field_type self.printer.AppendLine("std::vector<%s> %s;" % (self.GetCppType(field_type), field_name)) self.printer.sameLine = True else: print node.token return result def GetFixStrLen(self, field_type): return int(field_type[len(FIXSTR_TAG):]) def EndNode(self, node): if node.token == "enum_stmt": self.printer.DecIndent() self.printer.AppendLine("};\n") elif node.token in ["message_stmt", "struct_stmt"]: self.GenerateMessageMethod(node) self.printer.DecIndent() self.printer.AppendLine("};\n") return ''
def Transform(filename, out): parsed = [] lines = open(filename).readlines() printer = Printer(out) printer.AppendLine("// Generated by inltogo.py. DO NOT EDIT!") printer.AppendLine("") printer.AppendLine("module MessageType{") printer.AppendLine("") # # printer.AppendLine("import \"uninet/types\"") # printer.AppendLine("") # printer.AppendLine("const ( // Message Type") printer.IncIndent() printer.AppendLine("export var MsgIdMap=[];") re_assign = re.compile("MSGTYPE_DECLARE_ASSIGN\((\S+),\s*(\d+)\)") re_declare = re.compile("MSGTYPE_DECLARE\(\s*(\S+)\s*\)") index = 0 for line in lines: if "MSGTYPE_BEGIN_BLOCK" in line: pass # prase assign state what = re_assign.match(line) if what is not None: msgName = what.groups()[0] assIndex = what.groups()[1] comment = GetComment(line).decode("gbk", "ignore").encode('utf8') printer.AppendLine("export var %s:number = %s; // %s" % (msgName, assIndex, comment)) if msgName == "MSG_LAST": parsed.append("MsgIdMap[%s] = \"%s\"; } // %s" % (assIndex, msgName, comment)) else: parsed.append("MsgIdMap[%s] = \"%s\"; // %s" % (assIndex, msgName, comment)) index = int(assIndex) continue # parse declcare statements what = re_declare.match(line) if what != None: msgName = what.groups()[0] comment = GetComment(line).decode("gbk", "ignore").encode('utf8') assIndex = index + 1 printer.AppendLine("export var %s:number = %s; // %s" % (msgName, assIndex, comment)) if msgName == "MSG_LAST": parsed.append("MsgIdMap[%s] = \"%s\"; } // %s" % (assIndex, msgName, comment)) else: parsed.append("MsgIdMap[%s] = \"%s\"; // %s" % (assIndex, msgName, comment)) index = assIndex continue line = line.strip() if line.startswith("//") or len(line) == 0: printer.AppendLine("%s" % line.decode("gbk", "ignore").encode('utf8')) else: printer.AppendLine("// %s" % line.decode("gbk", "ignore").encode('utf8')) printer.DecIndent() printer.AppendLine("") printer.IncIndent() for parsed_line in parsed: printer.AppendLine(parsed_line) printer.DecIndent() printer.AppendLine("") printer.Flush()
class ProtoGenerator: """ 协议生成工具 此类读取C++语言生产协议定义的一个工具 此工具是为了兼容以前协议 """ def __init__(self): self.offset = 0 self.type_list = [] self.log = logging.getLogger('cpp2proto') self.message2typeDict = LoadMatchesDict("msg2type.txt") self.printer = Printer() def OnAddNode(self, node): pass def Generate(self, root, out_filename): root.Apply(self) self.printer.filename = out_filename self.log.debug(self.type_list) self.printer.Flush() def IsMyLenEnum(self, enum): if enum.value == "": return enum.childs[0].value[0] in ["MY_LEN", "MY_LENGTH", "THIS_LEN", "THIS_LENGTH"]; return False def GenerateEnum(self, enum): if self.IsMyLenEnum(enum): return self.printer.AppendLine('enum %s {' % enum.value) self.printer.IncIndent() def GetPrevEnum(self, node): index = node.parent.childs.index(node) r = range(0, index) r.reverse() for i in r: child = node.parent.childs[i] if isinstance(child, EnumFieldNode): return child return None def GetEnumValue(self, enum_field): prev_enum = self.GetPrevEnum(enum_field) if prev_enum == None: enum_field.enum_value = "0" else: enum_exp = prev_enum.enum_name + " + 1" last_value = prev_enum.enum_value if IsNum(last_value): enum_exp = str(int(last_value) + 1) enum_field.enum_value = enum_exp def GenerateEnumField(self, enum_field): if self.IsMyLenEnum(enum_field.parent): return "" if enum_field.enum_value == None: #print enum_field.value enum_value = self.GetEnumValue(enum_field) self.printer.AppendLine("%s = %s;" % (enum_field.enum_name, enum_field.enum_value)) def GenerateMessage(self, message): if message.token == "class_stmt": self.printer.AppendLine('message %s {' % message.value) self.printer.IncIndent() # add a enum indicate message type self.printer.AppendLine("enum { THIS_MSG_TYPE = %s; }\n" % self.message2typeDict[message.value]) else: self.printer.AppendLine('message %s {' % message.value) self.printer.IncIndent() def GetLableAndType(self, field): if field.array_num == None: field_desc = field.member_type if 'std::vector<' in field_desc: return 'repeated', field_desc.replace('std::vector<', '').replace('>', '') elif 'std::string' == field_desc: return 'required', 'string' else: return 'required', field_desc else: if field.member_type != "char": return 'repeated', field.member_type else: return 'required', 'string' def ComputeFieldIndex(self, field): index = 1 for child in field.parent.childs: if child is field: return index if child.token == "member_data": index+=1 assert False def GenerateField(self, field): index = self.ComputeFieldIndex(field) if field.value[0] not in self.type_list: self.type_list.append(field.value[0]) var_lable, var_type = self.GetLableAndType(field) self.printer.AppendLine('%s %s %s = %d;' % (var_lable, var_type, field.value[1], index)) def GenerateComment(self, node): index = node.parent.childs.index(node) if index > 0: sibling = node.parent.childs[index-1] if hasattr(sibling, "line_no"): if sibling.line_no == node.line_no: self.printer.AppendSameLine(" %s" % node.value) return self.printer.AppendLine("%s" % node.value) def BeginNode(self, node): if node.token in ['class_stmt', 'struct_stmt']: self.GenerateMessage(node) elif node.token == 'member_data': self.GenerateField(node) elif node.token == 'enum_stmt': self.GenerateEnum(node) elif node.token == "enum_field_stmt": self.GenerateEnumField(node) elif node.token == "comment": self.GenerateComment(node) else: self.log.debug("%s %s" % (node.token, node.value)) return '' def EndNode(self, node): if node.token in ['class_stmt', 'struct_stmt']: self.printer.DecIndent() self.printer.AppendLine('}\n\n') elif node.token == 'enum_stmt': if self.IsMyLenEnum(node): return "" self.printer.DecIndent() self.printer.AppendLine('}\n\n') return ''
def Transform(filename, hrlout, erlout): lines = open(filename).readlines() re_assign = re.compile("MSGTYPE_DECLARE_ASSIGN\((\S+),\s*(\d+)\)") re_declare = re.compile("MSGTYPE_DECLARE\(\s*(\S+)\s*\)") declare_list = [] index = 0 for line in lines: if "MSGTYPE_BEGIN_BLOCK" in line: pass # prase assign state what = re_assign.match(line) if what != None: msgName = what.groups()[0] index = int(what.groups()[1]) comment = GetComment(line) declare = ("declare", msgName, index, decode(comment)) declare_list.append(declare) continue # parse declcare statements what = re_declare.match(line) if what != None: msgName=what.groups()[0] comment = GetComment(line) index +=1 declare = ("declare", msgName, index, decode(comment)) declare_list.append(declare) continue line = line.strip() if line.startswith("%%%%") or len(line) == 0: declare = ("comment", "%s" % decode(line)) declare_list.append(declare) else: declare = ("comment", "%%%% %s" % decode(line)) declare_list.append(declare) printer = Printer(hrlout) printer.AppendLine("%%% generated by inltohrl.py. DO NOT EDIT!") for d in declare_list: if d[0] == "declare": msg_name = d[1]; index=d[2]; comment=d[3] printer.AppendLine("-define(%s, %d). %%%s" % \ (msg_name, index, comment)) elif d[0] == "comment": printer.AppendLine("%s" % d[1]) printer.Flush() erl_printer = Printer(erlout) erl_printer.AppendLine("%%% generated by inltohrl.py. DO NOT EDIT!") erl_printer.AppendLine("""\ -module(message_type). -export([atom_to_id/1, id_to_atom/1]). atom_to_id(Atom) -> convert(atom_to_id, Atom). id_to_atom(Id) -> convert(id_to_atom, Id). """) for d in declare_list: if d[0] == "declare": msg_name = d[1]; index=d[2]; comment=d[3] erl_printer.AppendLine("%%%%%s" % comment) erl_printer.AppendLine( """convert(id_to_atom, %d) -> '%s';""" % (index, msg_name)) erl_printer.AppendLine( """convert(atom_to_id, '%s') -> %d;""" % (msg_name, index)) erl_printer.AppendLine("convert(D, V) -> {unknown_convert, {D, V}}. ") erl_printer.Flush()