MetadataTableCsvParser.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. using System.Data;
  2. using System.Text.RegularExpressions;
  3. namespace etoy
  4. {
  5. sealed class MetadataTableCsvParser
  6. {
  7. const int START_ROW = 1;
  8. // 正则解析Metadata结构体
  9. Regex _structRegex = new Regex(@"(?<quote>""?)(\w+)\s*?{([\w\s:;\[\]]+)}(\k<quote>)");
  10. Regex _structFieldRegex = new Regex(@"(\w+)\s*?:\s*?([\w]+?)\s*?(\[\])?\s*?(;|$)");
  11. // 正则解析Metadata枚举
  12. Regex _enumRegex = new Regex(@"(?<quote>""?)(\w+)\s*?{([\w\s=,]+)}(\k<quote>)");
  13. Regex _enumFieldRegex = new Regex(@"(\w+)\s*?(=\s*?(\d+))?\s*?,?");
  14. public MetadataTable Parser(DataTable dt, string file)
  15. {
  16. int rowCount = dt.Rows.Count;
  17. int colCount = dt.Columns.Count;
  18. if (rowCount <= 0 || colCount < 3)
  19. throw new Exception($"Metadata表结构不合法, Row: {rowCount}, Column: {colCount}");
  20. Dictionary<string, MetadataStruct> structs = new Dictionary<string, MetadataStruct>();
  21. List<MetadataRow> rows = new List<MetadataRow>();
  22. for (int i = START_ROW; i < rowCount; i++)
  23. {
  24. MetadataRow row = new MetadataRow();
  25. row.Row = i;
  26. for (int j = 0; j < colCount; j++)
  27. {
  28. var cellvalue = dt.Rows[i][j].ToString().ToCellValue();
  29. MetadataColumnType type = (MetadataColumnType)j;
  30. switch (type)
  31. {
  32. case MetadataColumnType.Type:
  33. row.Type = cellvalue.ToFieldType();
  34. break;
  35. case MetadataColumnType.Value:
  36. row.Value = cellvalue;
  37. break;
  38. case MetadataColumnType.Description:
  39. row.Description = cellvalue;
  40. break;
  41. default:
  42. throw new Exception();
  43. }
  44. }
  45. rows.Add(row);
  46. }
  47. // 解析Struct & Enum
  48. for (int i = 0, length = rows.Count; i < length; i++)
  49. {
  50. var row = rows[i];
  51. if (string.IsNullOrEmpty(row.Type))
  52. throw new Exception($"Metadata 类型为空(行:{i}) {file}");
  53. if (Enum.TryParse<MetadataStructType>(row.Type, true, out var structType))
  54. {
  55. if (TryParseMetadata(structType, row.Value, out var @struct))
  56. {
  57. if (structs.ContainsKey(@struct.Name))
  58. throw new Exception($"Metadata 类型重复定义了(行:{i}) ({row.Value}) {file}");
  59. @struct.StructType = structType;
  60. @struct.Description = row.Description;
  61. // 两个地方都存, 方便生成代码使用
  62. row.Struct = @struct;
  63. structs[@struct.Name] = @struct;
  64. }
  65. else
  66. throw new Exception($"Metadata 类型解析失败(行:{i}) ({row.Value}) {file}");
  67. }
  68. else
  69. throw new Exception($"Metadata 不支持类型({row.Type}), 请修改 {file}");
  70. }
  71. MetadataTable table = new MetadataTable();
  72. table.Structs = structs;
  73. table.Rows = rows.ToArray();
  74. table.Path = file;
  75. table.Name = Path.GetFileNameWithoutExtension(file).ToTableName();
  76. return table;
  77. }
  78. bool TryParseMetadata(MetadataStructType type, string metadata, out MetadataStruct @struct)
  79. {
  80. @struct = default;
  81. bool bRet = false;
  82. switch (type)
  83. {
  84. case MetadataStructType.Struct:
  85. bRet = ParseStruct(metadata, out @struct);
  86. break;
  87. case MetadataStructType.Enum:
  88. bRet = ParseEnum(metadata, out @struct);
  89. break;
  90. }
  91. return bRet;
  92. }
  93. bool Parse(string metadata, Regex regex, out string typeName, out string typeBody)
  94. {
  95. typeName = typeBody = string.Empty;
  96. Match match = regex.Match(metadata);
  97. if (!match.Success) return false;
  98. typeName = match.Groups[1].Value;
  99. typeBody = match.Groups[2].Value;
  100. return true;
  101. }
  102. bool ParseStruct(string metadata, out MetadataStruct @struct)
  103. {
  104. @struct = new MetadataStruct();
  105. if (!Parse(metadata, _structRegex, out string typeName, out string typeBody)) return false;
  106. @struct.Name = typeName;
  107. MatchCollection collection = _structFieldRegex.Matches(typeBody);
  108. if (null == collection || collection.Count == 0) return false;
  109. int length = collection.Count;
  110. @struct.Fields = new MetadataField[length];
  111. for (int i = 0; i < length; i++)
  112. {
  113. var groups = collection[i].Groups;
  114. var fieldInfo = new MetadataField();
  115. fieldInfo.Name = groups[1].Value;
  116. fieldInfo.FieldType = groups[2].Value;
  117. fieldInfo.StructRepeated = !string.IsNullOrEmpty(groups[3].Value);
  118. @struct.Fields[i] = fieldInfo;
  119. }
  120. return true;
  121. }
  122. bool ParseEnum(string metadata, out MetadataStruct @struct)
  123. {
  124. @struct = new MetadataStruct();
  125. if (!Parse(metadata, _enumRegex, out string typeName, out string typeBody)) return false;
  126. @struct.Name = typeName;
  127. MatchCollection collection = _enumFieldRegex.Matches(typeBody);
  128. if (null == collection || collection.Count == 0) return false;
  129. int length = collection.Count;
  130. @struct.Fields = new MetadataField[length];
  131. for (int i = 0; i < length; i++)
  132. {
  133. var groups = collection[i].Groups;
  134. var fieldInfo = new MetadataField();
  135. fieldInfo.Name = groups[1].Value;
  136. var enumValue = groups[3].Value;
  137. fieldInfo.EnumValue = enumValue;
  138. var enumIntVal = 0;
  139. if (string.IsNullOrEmpty(enumValue) || int.TryParse(enumValue, out enumIntVal) == false)
  140. {
  141. if (i == 0)
  142. { //
  143. enumIntVal = 0;
  144. }
  145. else
  146. { // 上一个枚举值加一
  147. enumIntVal = @struct.Fields[i - 1].EnumIntVal + 1;
  148. }
  149. }
  150. fieldInfo.EnumIntVal = enumIntVal;
  151. @struct.Fields[i] = fieldInfo;
  152. }
  153. return true;
  154. }
  155. }
  156. }