private bool AddStructFieldDef( ProtocolDescriptor.ProtocolDef protoDef, ProtocolDescriptor.StructDef structDef, XElement element) { // check name attr string name; { XAttribute attr = element.Attribute("name"); if (attr == null) { PrintLineError(protoDef, element, "`{0}` node must contain a `name` attribute", element.Name); return(false); } name = attr.Value; } if (Regex.IsMatch(name, @"^[a-zA-Z_]\w*$") == false) { PrintLineError(protoDef, element, "`{0}` node `name` attribute is invalid", element.Name); return(false); } if (structDef.FieldNameIndex.ContainsKey(name)) { PrintLineError(protoDef, element, "`{0}` node `name` attribute duplicated", element.Name); return(false); } // check type attr string type; { XAttribute attr = element.Attribute("type"); if (attr == null) { PrintLineError(protoDef, element, "`{0}` node must contain a `type` attribute", element.Name); return(false); } type = attr.Value; } ProtocolDescriptor.StructDef.FieldDef def = new ProtocolDescriptor.StructDef.FieldDef(); def.ParentRef = structDef; def.Name = name; def.LineNumber = GetLineNumber(element); // get type info string fieldTypeStr = type; { Match m = Regex.Match(type, @"^list{(.+)}$"); if (m.Success) { fieldTypeStr = m.Groups[1].Value; def.Type = ProtocolDescriptor.StructDef.FieldType.List; } } ProtocolDescriptor.StructDef.FieldType fieldType = ProtocolDescriptor.StructDef.FieldType.None; if (fieldTypeStr == "i8") { fieldType = ProtocolDescriptor.StructDef.FieldType.I8; } else if (fieldTypeStr == "u8") { fieldType = ProtocolDescriptor.StructDef.FieldType.U8; } else if (fieldTypeStr == "i16") { fieldType = ProtocolDescriptor.StructDef.FieldType.I16; } else if (fieldTypeStr == "u16") { fieldType = ProtocolDescriptor.StructDef.FieldType.U16; } else if (fieldTypeStr == "i32") { fieldType = ProtocolDescriptor.StructDef.FieldType.I32; } else if (fieldTypeStr == "u32") { fieldType = ProtocolDescriptor.StructDef.FieldType.U32; } else if (fieldTypeStr == "i64") { fieldType = ProtocolDescriptor.StructDef.FieldType.I64; } else if (fieldTypeStr == "u64") { fieldType = ProtocolDescriptor.StructDef.FieldType.U64; } else if (fieldTypeStr == "i16v") { fieldType = ProtocolDescriptor.StructDef.FieldType.I16V; } else if (fieldTypeStr == "u16v") { fieldType = ProtocolDescriptor.StructDef.FieldType.U16V; } else if (fieldTypeStr == "i32v") { fieldType = ProtocolDescriptor.StructDef.FieldType.I32V; } else if (fieldTypeStr == "u32v") { fieldType = ProtocolDescriptor.StructDef.FieldType.U32V; } else if (fieldTypeStr == "i64v") { fieldType = ProtocolDescriptor.StructDef.FieldType.I64V; } else if (fieldTypeStr == "u64v") { fieldType = ProtocolDescriptor.StructDef.FieldType.U64V; } else if (fieldTypeStr == "string") { fieldType = ProtocolDescriptor.StructDef.FieldType.String; } else if (fieldTypeStr == "bytes") { fieldType = ProtocolDescriptor.StructDef.FieldType.Bytes; } else if (fieldTypeStr == "bool") { fieldType = ProtocolDescriptor.StructDef.FieldType.Bool; } else { ProtocolDescriptor.ProtocolDef refProtoDef = null; string refDefName = ""; string[] parts = fieldTypeStr.Split('.'); if (parts.Length == 1) { // in same file refProtoDef = protoDef; refDefName = parts[0]; } else if (parts.Length == 2) { // in other file string refProtoDefName = parts[0]; if (this.descriptor.ImportedProtos.TryGetValue( refProtoDefName, out refProtoDef) == false) { PrintLineError(protoDef, element, "protocol `{0}` is undefined", refProtoDefName); return(false); } refDefName = parts[1]; } else { PrintLineError(protoDef, element, "type `{0}` is invalid", fieldTypeStr); return(false); } for (;;) { // check is enum ProtocolDescriptor.EnumDef refEnumDef = null; if (refProtoDef.EnumNameIndex.TryGetValue( refDefName, out refEnumDef)) { fieldType = ProtocolDescriptor.StructDef.FieldType.Enum; def.RefEnumDef = refEnumDef; break; } // check is struct ProtocolDescriptor.StructDef refStructDef = null; if (refProtoDef.StructNameIndex.TryGetValue( refDefName, out refStructDef)) { fieldType = ProtocolDescriptor.StructDef.FieldType.Struct; def.RefStructDef = refStructDef; break; } PrintLineError(protoDef, element, "type `{0}` is undefined", refDefName); return(false); } } if (def.Type == ProtocolDescriptor.StructDef.FieldType.List) { def.ListType = fieldType; } else { def.Type = fieldType; } // optional if (element.Name == "optional") { def.IsOptional = true; def.OptionalFieldIndex = structDef.OptionalFieldCount++; } structDef.Fields.Add(def); structDef.FieldNameIndex.Add(def.Name, def); return(true); }
private void ProcessImportedProtocols( ProtocolDescriptor.ProtocolDef protoDef) { Dictionary <string, ProtocolDescriptor.ProtocolDef> usedProtos = new Dictionary <string, ProtocolDescriptor.ProtocolDef>(); Dictionary <string, ProtocolDescriptor.ProtocolDef> enumRefProtos = new Dictionary <string, ProtocolDescriptor.ProtocolDef>(); Dictionary <string, ProtocolDescriptor.ProtocolDef> structRefProtos = new Dictionary <string, ProtocolDescriptor.ProtocolDef>(); Dictionary <string, ProtocolDescriptor.ProtocolDef> enumMapRefProtos = new Dictionary <string, ProtocolDescriptor.ProtocolDef>(); // collect enum ref protocols for (int i = 0; i < protoDef.Enums.Count; ++i) { ProtocolDescriptor.EnumDef enumDef = protoDef.Enums[i]; for (int j = 0; j < enumDef.Items.Count; ++j) { ProtocolDescriptor.EnumDef.ItemDef def = enumDef.Items[j]; if (def.RefEnumItemDef != null) { ProtocolDescriptor.ProtocolDef refProtoDef = def.RefEnumItemDef.ParentRef.ParentRef; usedProtos[refProtoDef.Name] = refProtoDef; enumRefProtos[refProtoDef.Name] = refProtoDef; } } } // collect struct ref protocols for (int i = 0; i < protoDef.Structs.Count; ++i) { ProtocolDescriptor.StructDef structDef = protoDef.Structs[i]; for (int j = 0; j < structDef.Fields.Count; ++j) { ProtocolDescriptor.StructDef.FieldDef def = structDef.Fields[j]; if (def.RefEnumDef != null) { ProtocolDescriptor.ProtocolDef refProtoDef = def.RefEnumDef.ParentRef; usedProtos[refProtoDef.Name] = refProtoDef; structRefProtos[refProtoDef.Name] = refProtoDef; } if (def.RefStructDef != null) { ProtocolDescriptor.ProtocolDef refProtoDef = def.RefStructDef.ParentRef; usedProtos[refProtoDef.Name] = refProtoDef; structRefProtos[refProtoDef.Name] = refProtoDef; } } } // collect enum map ref protocols for (int i = 0; i < protoDef.EnumMaps.Count; ++i) { ProtocolDescriptor.EnumMapDef enumMapDef = protoDef.EnumMaps[i]; for (int j = 0; j < enumMapDef.Items.Count; ++j) { ProtocolDescriptor.EnumMapDef.ItemDef def = enumMapDef.Items[j]; if (def.RefEnumItemDef != null) { ProtocolDescriptor.ProtocolDef refProtoDef = def.RefEnumItemDef.ParentRef.ParentRef; usedProtos[refProtoDef.Name] = refProtoDef; enumMapRefProtos[refProtoDef.Name] = refProtoDef; } if (def.RefStructDef != null) { ProtocolDescriptor.ProtocolDef refProtoDef = def.RefStructDef.ParentRef; usedProtos[refProtoDef.Name] = refProtoDef; enumMapRefProtos[refProtoDef.Name] = refProtoDef; } } } for (int i = 0; i < protoDef.Imports.Count; ++i) { ProtocolDescriptor.ImportDef importDef = protoDef.Imports[i]; // check imported protocol is used if (usedProtos.ContainsKey(importDef.ProtoDef.Name) == false) { Console.Error.WriteLine(string.Format( "warning:{0}:{1}: protocol `{2}` " + "is not used but imported", protoDef.FilePath, importDef.LineNumber, importDef.Name)); } if (enumRefProtos.ContainsKey(importDef.ProtoDef.Name)) { importDef.IsRefByEnum = true; } if (structRefProtos.ContainsKey(importDef.ProtoDef.Name)) { importDef.IsRefByStruct = true; } if (enumMapRefProtos.ContainsKey(importDef.ProtoDef.Name)) { importDef.IsRefByEnumMap = true; } } }