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 bool AddEnumDef( ProtocolDescriptor.ProtocolDef protoDef, XElement element) { // check name attr string name; { XAttribute attr = element.Attribute("name"); if (attr == null) { PrintLineError(protoDef, element, "`enum` node must contain a `name` attribute"); return(false); } name = attr.Value; } if (Regex.IsMatch(name, @"^[a-zA-Z_]\w*$") == false) { PrintLineError(protoDef, element, "`enum` node `name` attribute is invalid"); return(false); } if (protoDef.EnumNameIndex.ContainsKey(name) || protoDef.StructNameIndex.ContainsKey(name) || protoDef.EnumMapNameIndex.ContainsKey(name)) { PrintLineError(protoDef, element, "`enum` node `name` attribute duplicated"); return(false); } ProtocolDescriptor.EnumDef def = new ProtocolDescriptor.EnumDef(); def.ParentRef = protoDef; def.Name = name; def.LineNumber = GetLineNumber(element); // parse items { IEnumerator <XElement> iter = element.Elements().GetEnumerator(); while (iter.MoveNext()) { XElement childElement = iter.Current; if (childElement.Name != "item") { PrintLineError(protoDef, childElement, "expect a `item` node"); return(false); } if (AddEnumItemDef(protoDef, def, childElement) == false) { return(false); } } } protoDef.Enums.Add(def); protoDef.EnumNameIndex.Add(def.Name, def); return(true); }
private bool AddEnumItemDef( ProtocolDescriptor.ProtocolDef protoDef, ProtocolDescriptor.EnumDef enumDef, XElement element) { // check name attr string name; { XAttribute attr = element.Attribute("name"); if (attr == null) { PrintLineError(protoDef, element, "`item` node must contain a `name` attribute"); return(false); } name = attr.Value; } if (Regex.IsMatch(name, @"^[a-zA-Z_]\w*$") == false) { PrintLineError(protoDef, element, "`item` node `name` attribute is invalid"); return(false); } if (enumDef.ItemNameIndex.ContainsKey(name)) { PrintLineError(protoDef, element, "`item` node `name` attribute duplicated"); return(false); } // check value attr string val = ""; { XAttribute attr = element.Attribute("value"); if (attr != null) { val = attr.Value; } } ProtocolDescriptor.EnumDef.ItemDef def = new ProtocolDescriptor.EnumDef.ItemDef(); def.ParentRef = enumDef; def.Name = name; def.LineNumber = GetLineNumber(element); if (val == "") { // default def.Type = ProtocolDescriptor.EnumDef.ItemType.Default; if (enumDef.Items.Count == 0) { def.IntValue = 0; } else { def.IntValue = enumDef.Items[enumDef.Items.Count - 1].IntValue + 1; } } else if (Regex.IsMatch(val, @"^(-)?[0-9]+$")) { // int def.Type = ProtocolDescriptor.EnumDef.ItemType.Int; def.IntValue = int.TryParse(val, out def.IntValue) ? def.IntValue : 0; } else { string[] parts = val.Split('.'); if (parts.Length == 1) { // current enum string refDefName = parts[0]; ProtocolDescriptor.EnumDef.ItemDef refDef = null; if (enumDef.ItemNameIndex.TryGetValue( refDefName, out refDef) == false) { PrintLineError(protoDef, element, "enum item `{0}` is undefined", refDefName); return(false); } def.Type = ProtocolDescriptor.EnumDef.ItemType.CurrentEnumRef; def.IntValue = refDef.IntValue; def.RefEnumItemDef = refDef; } else if (parts.Length == 2) { // other enum in same file string refEnumDefName = parts[0]; string refDefName = parts[1]; ProtocolDescriptor.EnumDef refEnumDef = null; if (protoDef.EnumNameIndex.TryGetValue( refEnumDefName, out refEnumDef) == false) { PrintLineError(protoDef, element, "enum `{0}` is undefined", refEnumDefName); return(false); } ProtocolDescriptor.EnumDef.ItemDef refDef = null; if (refEnumDef.ItemNameIndex.TryGetValue( refDefName, out refDef) == false) { PrintLineError(protoDef, element, "enum item `{0}` is undefined", refDefName); return(false); } def.Type = ProtocolDescriptor.EnumDef.ItemType.OtherEnumRef; def.IntValue = refDef.IntValue; def.RefEnumItemDef = refDef; } else if (parts.Length == 3) { // other enum in other file string refProtoDefName = parts[0]; string refEnumDefName = parts[1]; string refDefName = parts[2]; ProtocolDescriptor.ProtocolDef refProtoDef = null; if (this.descriptor.ImportedProtos.TryGetValue( refProtoDefName, out refProtoDef) == false) { PrintLineError(protoDef, element, "protocol `{0}` is undefined", refProtoDefName); return(false); } ProtocolDescriptor.EnumDef refEnumDef = null; if (refProtoDef.EnumNameIndex.TryGetValue( refEnumDefName, out refEnumDef) == false) { PrintLineError(protoDef, element, "enum `{0}` is undefined", refEnumDefName); return(false); } ProtocolDescriptor.EnumDef.ItemDef refDef = null; if (refEnumDef.ItemNameIndex.TryGetValue( refDefName, out refDef) == false) { PrintLineError(protoDef, element, "enum item `{0}` is undefined", refDefName); return(false); } def.Type = ProtocolDescriptor.EnumDef.ItemType.OtherEnumRef; def.IntValue = refDef.IntValue; def.RefEnumItemDef = refDef; } else { PrintLineError(protoDef, element, "enum value `{0}` is invalid", val); return(false); } } enumDef.Items.Add(def); enumDef.ItemNameIndex.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; } } }