Пример #1
0
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()
Пример #2
0
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()
Пример #3
0
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()
Пример #4
0
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()
Пример #5
0
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()
Пример #6
0
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 ''
Пример #7
0
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()
Пример #8
0
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 ''