123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- using System.Data;
- using System.Text.RegularExpressions;
- namespace etoy
- {
- sealed class MetadataTableCsvParser
- {
- const int START_ROW = 1;
- // 正则解析Metadata结构体
- Regex _structRegex = new Regex(@"(?<quote>""?)(\w+)\s*?{([\w\s:;\[\]]+)}(\k<quote>)");
- Regex _structFieldRegex = new Regex(@"(\w+)\s*?:\s*?([\w]+?)\s*?(\[\])?\s*?(;|$)");
- // 正则解析Metadata枚举
- Regex _enumRegex = new Regex(@"(?<quote>""?)(\w+)\s*?{([\w\s=,]+)}(\k<quote>)");
- Regex _enumFieldRegex = new Regex(@"(\w+)\s*?(=\s*?(\d+))?\s*?,?");
- public MetadataTable Parser(DataTable dt, string file)
- {
- int rowCount = dt.Rows.Count;
- int colCount = dt.Columns.Count;
- if (rowCount <= 0 || colCount < 3)
- throw new Exception($"Metadata表结构不合法, Row: {rowCount}, Column: {colCount}");
- Dictionary<string, MetadataStruct> structs = new Dictionary<string, MetadataStruct>();
- List<MetadataRow> rows = new List<MetadataRow>();
- for (int i = START_ROW; i < rowCount; i++)
- {
- MetadataRow row = new MetadataRow();
- row.Row = i;
- for (int j = 0; j < colCount; j++)
- {
- var cellvalue = dt.Rows[i][j].ToString().ToCellValue();
- MetadataColumnType type = (MetadataColumnType)j;
- switch (type)
- {
- case MetadataColumnType.Type:
- row.Type = cellvalue.ToFieldType();
- break;
- case MetadataColumnType.Value:
- row.Value = cellvalue;
- break;
- case MetadataColumnType.Description:
- row.Description = cellvalue;
- break;
- default:
- throw new Exception();
- }
- }
- rows.Add(row);
- }
- // 解析Struct & Enum
- for (int i = 0, length = rows.Count; i < length; i++)
- {
- var row = rows[i];
- if (string.IsNullOrEmpty(row.Type))
- throw new Exception($"Metadata 类型为空(行:{i}) {file}");
- if (Enum.TryParse<MetadataStructType>(row.Type, true, out var structType))
- {
- if (TryParseMetadata(structType, row.Value, out var @struct))
- {
- if (structs.ContainsKey(@struct.Name))
- throw new Exception($"Metadata 类型重复定义了(行:{i}) ({row.Value}) {file}");
- @struct.StructType = structType;
- @struct.Description = row.Description;
- // 两个地方都存, 方便生成代码使用
- row.Struct = @struct;
- structs[@struct.Name] = @struct;
- }
- else
- throw new Exception($"Metadata 类型解析失败(行:{i}) ({row.Value}) {file}");
- }
- else
- throw new Exception($"Metadata 不支持类型({row.Type}), 请修改 {file}");
- }
- MetadataTable table = new MetadataTable();
- table.Structs = structs;
- table.Rows = rows.ToArray();
- table.Path = file;
- table.Name = Path.GetFileNameWithoutExtension(file).ToTableName();
- return table;
- }
- bool TryParseMetadata(MetadataStructType type, string metadata, out MetadataStruct @struct)
- {
- @struct = default;
- bool bRet = false;
- switch (type)
- {
- case MetadataStructType.Struct:
- bRet = ParseStruct(metadata, out @struct);
- break;
- case MetadataStructType.Enum:
- bRet = ParseEnum(metadata, out @struct);
- break;
- }
- return bRet;
- }
- bool Parse(string metadata, Regex regex, out string typeName, out string typeBody)
- {
- typeName = typeBody = string.Empty;
- Match match = regex.Match(metadata);
- if (!match.Success) return false;
- typeName = match.Groups[1].Value;
- typeBody = match.Groups[2].Value;
- return true;
- }
- bool ParseStruct(string metadata, out MetadataStruct @struct)
- {
- @struct = new MetadataStruct();
- if (!Parse(metadata, _structRegex, out string typeName, out string typeBody)) return false;
- @struct.Name = typeName;
- MatchCollection collection = _structFieldRegex.Matches(typeBody);
- if (null == collection || collection.Count == 0) return false;
- int length = collection.Count;
- @struct.Fields = new MetadataField[length];
- for (int i = 0; i < length; i++)
- {
- var groups = collection[i].Groups;
- var fieldInfo = new MetadataField();
- fieldInfo.Name = groups[1].Value;
- fieldInfo.FieldType = groups[2].Value;
- fieldInfo.StructRepeated = !string.IsNullOrEmpty(groups[3].Value);
- @struct.Fields[i] = fieldInfo;
- }
- return true;
- }
- bool ParseEnum(string metadata, out MetadataStruct @struct)
- {
- @struct = new MetadataStruct();
- if (!Parse(metadata, _enumRegex, out string typeName, out string typeBody)) return false;
- @struct.Name = typeName;
- MatchCollection collection = _enumFieldRegex.Matches(typeBody);
- if (null == collection || collection.Count == 0) return false;
- int length = collection.Count;
- @struct.Fields = new MetadataField[length];
- for (int i = 0; i < length; i++)
- {
- var groups = collection[i].Groups;
- var fieldInfo = new MetadataField();
- fieldInfo.Name = groups[1].Value;
- var enumValue = groups[3].Value;
- fieldInfo.EnumValue = enumValue;
- var enumIntVal = 0;
- if (string.IsNullOrEmpty(enumValue) || int.TryParse(enumValue, out enumIntVal) == false)
- {
- if (i == 0)
- { //
- enumIntVal = 0;
- }
- else
- { // 上一个枚举值加一
- enumIntVal = @struct.Fields[i - 1].EnumIntVal + 1;
- }
- }
- fieldInfo.EnumIntVal = enumIntVal;
- @struct.Fields[i] = fieldInfo;
- }
- return true;
- }
- }
- }
|