func parseStruct(fd *model.FieldDescriptor, value string, fileD *model.FileDescriptor, node *model.Node) bool { p := newStructParser(value) // 检查字段有没有重复 fieldByFD := make(map[*model.FieldDescriptor]bool) return p.Run(fd, func(key, value string) bool { bnField := fd.Complex.FieldByValueAndMeta(key) if bnField == nil { log.Errorf("%s, '%s'", i18n.String(i18n.StructParser_FieldNotFound), key) return false } if _, ok := fieldByFD[bnField]; ok { log.Errorf("%s, '%s'", i18n.String(i18n.StructParser_DuplicateFieldInCell), key) return false } fieldByFD[bnField] = true // 添加类型节点 fieldNode := node.AddKey(bnField) // 在类型节点下添加值节点 _, ok := ConvertValue(bnField, value, fileD, fieldNode) return ok }) }
func dataProcessor(file *File, fd *model.FieldDescriptor, raw string, node *model.Node) bool { // 列表 if fd.IsRepeated { spliter := fd.ListSpliter() // 使用多格子实现的repeated if spliter == "" { if _, ok := filter.ConvertValue(fd, raw, file.GlobalFD, node); !ok { goto ConvertError } } else { // 一个格子切割的repeated valueList := strings.Split(raw, spliter) for _, v := range valueList { if _, ok := filter.ConvertValue(fd, v, file.GlobalFD, node); !ok { goto ConvertError } } } } else { // 单值 if cv, ok := filter.ConvertValue(fd, raw, file.GlobalFD, node); !ok { goto ConvertError } else { // 值重复检查 if fd.Meta.RepeatCheck && !file.checkValueRepeat(fd, cv) { log.Errorf("%s, %s raw: '%s'", i18n.String(i18n.DataSheet_ValueRepeated), fd.String(), cv) return false } } } return true ConvertError: log.Errorf("%s, %s raw: '%s'", i18n.String(i18n.DataSheet_ValueConvertError), fd.String(), raw) return false }
// bool表示是否有错 func findlocalFieldType(localFD *model.FileDescriptor, rawFieldType string) (model.FieldType, *model.Descriptor, bool) { // 解析普通类型 if ft, ok := model.ParseFieldType(rawFieldType); ok { return ft, nil, true } // 解析内建类型 if desc, ok := localFD.DescriptorByName[rawFieldType]; ok { // 只有枚举( 结构体不允许再次嵌套, 增加理解复杂度 ) if desc.Kind != model.DescriptorKind_Enum { log.Errorf("%s, '%s'", i18n.String(i18n.TypeSheet_StructFieldCanNotBeStruct), rawFieldType) return model.FieldType_None, nil, false } return model.FieldType_Enum, desc, true } // 没找到类型, 待二次pass return model.FieldType_None, nil, true }
func (self *typeModelRoot) ParsePragma(localFD *model.FileDescriptor) bool { if err := proto.UnmarshalText(self.pragma, &localFD.Pragma); err != nil { log.Errorf("%s, '%s'", i18n.String(i18n.TypeSheet_PragmaParseFailed), self.pragma) return false } if localFD.Pragma.TableName == "" { log.Errorf("%s", i18n.String(i18n.TypeSheet_TableNameIsEmpty)) return false } if localFD.Pragma.Package == "" { log.Errorf("%s", i18n.String(i18n.TypeSheet_PackageIsEmpty)) return false } return true }
func (self *File) ExportLocalType() bool { var sheetCount int // 解析类型表 for _, rawSheet := range self.coreFile.Sheets { if isTypeSheet(rawSheet.Name) { if sheetCount > 0 { log.Errorf("%s", i18n.String(i18n.File_TypeSheetKeepSingleton)) return false } typeSheet := newTypeSheet(NewSheet(self, rawSheet)) // 从cell添加类型 if !typeSheet.Parse(self.LocalFD, self.GlobalFD) { return false } sheetCount++ } } // 解析表头 for _, rawSheet := range self.coreFile.Sheets { // 是数据表 if !isTypeSheet(rawSheet.Name) { dSheet := newDataSheet(NewSheet(self, rawSheet)) if !dSheet.Valid() { continue } log.Infof(" %s", rawSheet.Name) dataHeader := newDataHeadSheet() // 检查引导头 if !dataHeader.ParseProtoField(len(self.dataSheets), dSheet.Sheet, self.LocalFD, self.GlobalFD) { return false } if self.Header == nil { self.Header = dataHeader } self.dataSheets = append(self.dataSheets, dSheet) } } return true }
func (self *Globals) AddTypes(localFD *model.FileDescriptor) bool { // 将行定义结构也添加到文件中 for _, d := range localFD.Descriptors { if !self.FileDescriptor.Add(d) { log.Errorf("%s, %s", i18n.String(i18n.Globals_DuplicateTypeName), d.Name) return false } } return true }
func (self *TypeSheet) ParseTable(root *typeModelRoot) bool { var readingLine bool = true root.pragma = self.GetCellData(TypeSheetRow_Pragma, 0) for row := TypeSheetRow_DataBegin; readingLine; row++ { tm := newTypeModel() tm.row = row for col := 0; ; col++ { // 头 typeDeclare := self.GetCellData(TypeSheetRow_FieldDesc, col) // 头已经读完 if typeDeclare == "" { break } if _, ok := typeHeader[typeDeclare]; !ok { self.Row = TypeSheetRow_FieldDesc self.Column = col log.Errorf("%s, '%s'", i18n.String(i18n.TypeSheet_UnexpectedTypeHeader), typeDeclare) return false } // 值 typeValue := self.GetCellData(row, col) // 类型空表示停止解析 if typeDeclare == "ObjectType" && typeValue == "" { readingLine = false break } tm.colData[typeDeclare] = &typeCell{ value: typeValue, col: col, } } if len(tm.colData) > 0 { root.models = append(root.models, tm) } } return true }
func (self *structParser) Run(fd *model.FieldDescriptor, callback func(string, string) bool) (ok bool) { defer golexer.ErrorCatcher(func(err error) { log.Errorf("%s, '%s' '%v'", i18n.String(i18n.StructParser_LexerError), fd.Name, err.Error()) }) self.NextToken() for self.TokenID() != Token_EOF { if self.TokenID() != Token_Identifier { log.Errorf("%s, '%s'", i18n.String(i18n.StructParser_ExpectField), fd.Name) return false } key := self.TokenValue() self.NextToken() if self.TokenID() != Token_Comma { log.Errorf("%s, '%s'", i18n.String(i18n.StructParser_UnexpectedSpliter), key) return false } self.NextToken() value := self.TokenValue() if !callback(key, value) { return false } self.NextToken() } return true }
func (self *Globals) Print() bool { log.Infof("==========%s==========", i18n.String(i18n.Globals_OutputCombineData)) for _, p := range self.Printers { if !p.Start(self) { return false } } return true }
// 检查protobuf兼容性 func (self *TypeSheet) checkProtobufCompatibility(fileD *model.FileDescriptor) bool { for _, bt := range fileD.Descriptors { if bt.Kind == model.DescriptorKind_Enum { // proto3 需要枚举有0值 if _, ok := bt.FieldByNumber[0]; !ok { log.Errorf("%s, '%s'", i18n.String(i18n.TypeSheet_FirstEnumValueShouldBeZero), bt.Name) return false } } } return true }
func (self *Globals) PreExport() bool { // 当合并结构名没有指定时, 对于代码相关的输出器, 要报错 if self.CombineStructName == "" && self.hasAnyPrinter(".proto", ".cs") { log.Errorf("%s", i18n.String(i18n.Globals_CombineNameLost)) return false } // 添加XXConfig全局结构 self.CombineStruct.Name = self.CombineStructName self.CombineStruct.Kind = model.DescriptorKind_Struct self.CombineStruct.Usage = model.DescriptorUsage_CombineStruct self.FileDescriptor.Name = self.CombineStructName self.FileDescriptor.Add(self.CombineStruct) return true }
func parseFieldValue(rawFieldValue string) (model.DescriptorKind, int32, bool) { // 非空值是枚举 if rawFieldValue != "" { v, err := strconv.Atoi(rawFieldValue) // 解析枚举值 if err != nil { log.Errorf("%s, %s", i18n.String(i18n.TypeSheet_EnumValueParseFailed), err.Error()) return model.DescriptorKind_None, 0, false } return model.DescriptorKind_Enum, int32(v), true } return model.DescriptorKind_Struct, 0, true }
func (self *TypeSheet) Parse(localFD *model.FileDescriptor, globalFD *model.FileDescriptor) bool { var root typeModelRoot if !self.ParseTable(&root) { goto ErrorStop } if !root.ParsePragma(localFD) { self.Row = TypeSheetRow_Pragma self.Column = 0 log.Errorf("%s", i18n.String(i18n.TypeSheet_PackageIsEmpty)) goto ErrorStop } if !root.ParseData(localFD, globalFD) { self.Row = root.Row self.Column = root.Col goto ErrorStop } if !root.SolveUnknownModel(localFD, globalFD) { self.Row = root.Row self.Column = root.Col goto ErrorStop } return self.checkProtobufCompatibility(localFD) ErrorStop: r, c := self.GetRC() log.Errorf("%s|%s(%s)", self.file.FileName, self.Name, util.ConvR1C1toA1(r, c)) return false }
func (self *typeModelRoot) SolveUnknownModel(localFD *model.FileDescriptor, globalFD *model.FileDescriptor) bool { for _, m := range self.unknownModel { self.Row = m.row self.Col = self.fieldTypeCol fieldType, complexType, ok := findFieldType(localFD, globalFD, m.rawFieldType) if !ok { return false } // 实在是找不到了, 没辙了 if fieldType == model.FieldType_None { log.Errorf("%s, '%s'", i18n.String(i18n.TypeSheet_FieldTypeNotFound), m.rawFieldType) return false } m.fd.Type = fieldType m.fd.Complex = complexType } return true }
func (self *DataHeader) makeRowDescriptor(fileD *model.FileDescriptor, rootField []*model.FieldDescriptor) bool { rowType := model.NewDescriptor() rowType.Usage = model.DescriptorUsage_RowType rowType.Name = fmt.Sprintf("%sDefine", fileD.Pragma.TableName) rowType.Kind = model.DescriptorKind_Struct // 类型已经存在, 说明是自己定义的 XXDefine, 不允许 if _, ok := fileD.DescriptorByName[rowType.Name]; ok { log.Errorf("%s '%s'", i18n.String(i18n.DataHeader_UseReservedTypeName), rowType.Name) return false } fileD.Add(rowType) // 将表格中的列添加到类型中, 方便导出 for _, field := range rootField { rowType.Add(field) } return true }
// 从单元格原始数据到最终输出的数值, 检查并转换, 处理默认值及根据meta转换情况 func ConvertValue(fd *model.FieldDescriptor, value string, fileD *model.FileDescriptor, node *model.Node) (ret string, ok bool) { // 空格, 且有默认值时, 使用默认值 if value == "" { value = fd.DefaultValue() } switch fd.Type { case model.FieldType_Int32: _, err := strconv.ParseInt(value, 10, 32) if err != nil { log.Debugln(err) return "", false } ret = value node.AddValue(ret) case model.FieldType_Int64: _, err := strconv.ParseInt(value, 10, 64) if err != nil { log.Debugln(err) return "", false } ret = value node.AddValue(ret) case model.FieldType_UInt32: _, err := strconv.ParseUint(value, 10, 32) if err != nil { log.Debugln(err) return "", false } ret = value node.AddValue(ret) case model.FieldType_UInt64: _, err := strconv.ParseUint(value, 10, 64) if err != nil { log.Debugln(err) return "", false } ret = value node.AddValue(ret) case model.FieldType_Float: _, err := strconv.ParseFloat(value, 32) if err != nil { log.Debugln(err) return "", false } ret = value node.AddValue(ret) case model.FieldType_Bool: for { if value == "是" { ret = "true" break } else if value == "否" { ret = "false" break } v, err := strconv.ParseBool(value) if err != nil { log.Debugln(err) return "", false } if v { ret = "true" } else { ret = "false" } break } node.AddValue(ret) case model.FieldType_String: ret = value node.AddValue(ret) case model.FieldType_Enum: if fd.Complex == nil { log.Errorf("%s, '%s'", i18n.String(i18n.ConvertValue_EnumTypeNil), fd.Name) return "", false } evd := fd.Complex.FieldByValueAndMeta(value) if evd == nil { log.Errorf("%s, '%s' '%s'", i18n.String(i18n.ConvertValue_EnumValueNotFound), value, fd.Complex.Name) return "", false } // 使用枚举的英文字段名输出 ret = evd.Name node.AddValue(ret).EnumValue = evd.EnumValue case model.FieldType_Struct: if fd.Complex == nil { log.Errorf("%s, '%s'", i18n.String(i18n.ConvertValue_StructTypeNil), fd.Name) return "", false } if !parseStruct(fd, value, fileD, node) { return "", false } default: log.Errorf("%s, '%s' '%s'", i18n.String(i18n.ConvertValue_UnknownFieldType), fd.Name, fd.Name) return "", false } ok = true return }
// 检查字段行的长度 func (self *DataHeader) ParseProtoField(index int, sheet *Sheet, localFD *model.FileDescriptor, globalFD *model.FileDescriptor) bool { var def *model.FieldDescriptor // 遍历列 for sheet.Column = 0; ; sheet.Column++ { def = new(model.FieldDescriptor) // ====================解析字段==================== def.Name = sheet.GetCellData(DataSheetRow_FieldName, sheet.Column) if def.Name == "" { break } // #开头表示注释, 跳过 if strings.Index(def.Name, "#") != 0 { // ====================解析类型==================== testFileD := localFD rawFieldType := sheet.GetCellData(DataSheetRow_FieldType, sheet.Column) for { if def.ParseType(testFileD, rawFieldType) { break } if testFileD == localFD { testFileD = globalFD continue } break } // 依然找不到, 报错 if def.Type == model.FieldType_None { sheet.Row = DataSheetRow_FieldType log.Errorf("%s, '%s' (%s) raw: %s", i18n.String(i18n.DataHeader_TypeNotFound), def.Name, model.FieldTypeToString(def.Type), rawFieldType) goto ErrorStop } // ====================解析特性==================== metaString := sheet.GetCellData(DataSheetRow_FieldMeta, sheet.Column) if err := proto.UnmarshalText(metaString, &def.Meta); err != nil { sheet.Row = DataSheetRow_FieldMeta log.Errorf("%s '%s'", i18n.String(i18n.DataHeader_MetaParseFailed), err) goto ErrorStop } def.Comment = sheet.GetCellData(DataSheetRow_Comment, sheet.Column) // 根据字段名查找, 处理repeated字段case exist, ok := self.HeaderByName[def.Name] if ok { // 多个同名字段只允许repeated方式的字段 if !exist.IsRepeated { sheet.Row = DataSheetRow_FieldName log.Errorf("%s '%s'", i18n.String(i18n.DataHeader_DuplicateFieldName), def.Name) goto ErrorStop } // 多个repeated描述类型不一致 if exist.Type != def.Type { sheet.Row = DataSheetRow_FieldType log.Errorf("%s '%s' '%s' '%s'", i18n.String(i18n.DataHeader_RepeatedFieldTypeNotSameInMultiColumn), def.Name, model.FieldTypeToString(exist.Type), model.FieldTypeToString(def.Type)) goto ErrorStop } // 多个repeated描述内建类型不一致 if exist.Complex != def.Complex { sheet.Row = DataSheetRow_FieldType log.Errorf("%s '%s'", i18n.String(i18n.DataHeader_RepeatedFieldTypeNotSameInMultiColumn), def.Name) goto ErrorStop } // 多个repeated描述的meta不一致 if proto.CompactTextString(&exist.Meta) != proto.CompactTextString(&def.Meta) { sheet.Row = DataSheetRow_FieldMeta log.Errorf("%s '%s'", i18n.String(i18n.DataHeader_RepeatedFieldMetaNotSameInMultiColumn), def.Name) goto ErrorStop } def = exist } else { self.HeaderByName[def.Name] = def self.headerFields = append(self.headerFields, def) } } // 有注释字段, 但是依然要放到这里来进行索引 self.rawHeaderFields = append(self.rawHeaderFields, def) } if len(self.rawHeaderFields) == 0 { return false } if index == 0 { // 添加第一个数据表的定义 if !self.makeRowDescriptor(localFD, self.headerFields) { goto ErrorStop } } return true ErrorStop: r, c := sheet.GetRC() log.Errorf("%s|%s(%s)", sheet.file.FileName, sheet.Name, util.ConvR1C1toA1(r, c)) return false }
func Run(g *printer.Globals) bool { if !g.PreExport() { return false } fileObjList := make([]interface{}, 0) log.Infof("==========%s==========", i18n.String(i18n.Run_CollectTypeInfo)) // 合并类型 for _, in := range g.InputFileList { inputFile := in.(string) file := NewFile(inputFile) if file == nil { return false } log.Infoln(filepath.Base(inputFile)) file.GlobalFD = g.FileDescriptor // 电子表格数据导出到Table对象 if !file.ExportLocalType() { return false } // 整合类型信息和数据 if !g.AddTypes(file.LocalFD) { return false } // 没有 if file.Header != nil { fileObjList = append(fileObjList, file) } } log.Infof("==========%s==========", i18n.String(i18n.Run_ExportSheetData)) // 导出表格 if !util.ParallelWorker(fileObjList, false, func(in interface{}) bool { file := in.(*File) log.Infoln(filepath.Base(file.FileName)) // 电子表格数据导出到Table对象 tab := file.ExportData() if tab == nil { return false } // 整合类型信息和数据 return g.AddContent(tab) }) { return false } // 根据各种导出类型, 调用各导出器导出 return g.Print() }
// 合并每个表带的类型 func (self *Globals) AddContent(tab *model.Table) bool { localFD := tab.LocalFD self.guard.Lock() defer self.guard.Unlock() // 有表格里描述的包名不一致, 无法合成最终的文件 if self.Pragma.Package == "" { self.Pragma.Package = localFD.Pragma.Package } else if self.Pragma.Package != localFD.Pragma.Package { log.Errorf("%s, '%s' '%s'", i18n.String(i18n.Globals_PackageNameDiff), self.Pragma.Package, localFD.Pragma.Package) return false } if _, ok := self.tableByName[localFD.Name]; ok { log.Errorf("%s, '%s'", i18n.String(i18n.Globals_TableNameDuplicated), localFD.Name) return false } // 表的全局类型信息与合并信息一致 tab.GlobalFD = self.FileDescriptor self.tableByName[localFD.Name] = tab self.Tables = append(self.Tables, tab) // 每个表在结构体里的字段 var rowFD model.FieldDescriptor rowFD.Name = localFD.Name rowFD.Type = model.FieldType_Struct rowFD.Complex = localFD.RowDescriptor() rowFD.IsRepeated = true rowFD.Order = int32(len(self.CombineStruct.Fields) + 1) rowFD.Comment = localFD.Name self.CombineStruct.Add(&rowFD) if localFD.RowDescriptor() == nil { panic("row field null:" + localFD.Name) } for _, d := range localFD.Descriptors { // 非行类型的, 全部忽略 if d.Usage != model.DescriptorUsage_RowType { continue } for _, indexFD := range d.Indexes { key := TableIndex{ Row: &rowFD, Index: indexFD, } self.GlobalIndexes = append(self.GlobalIndexes, key) } } return true }
func (self *typeModelRoot) ParseData(localFD *model.FileDescriptor, globalFD *model.FileDescriptor) bool { var td *model.Descriptor reservedRowFieldTypeName := localFD.Pragma.TableName + "Define" // 每一行 for _, m := range self.models { self.Row = m.row var rawTypeName string rawTypeName, self.Col = m.getValue("ObjectType") if rawTypeName == reservedRowFieldTypeName { log.Errorf("%s '%s'", i18n.String(i18n.DataHeader_UseReservedTypeName), rawTypeName) return false } existType, ok := localFD.DescriptorByName[rawTypeName] if ok { td = existType } else { td = model.NewDescriptor() td.Name = rawTypeName localFD.Add(td) } // 字段名 m.fd.Name, self.Col = m.getValue("FieldName") // 解析类型 m.rawFieldType, self.Col = m.getValue("FieldType") self.fieldTypeCol = self.Col fieldType, complexType, ok := findFieldType(localFD, globalFD, m.rawFieldType) if !ok { return false } if fieldType == model.FieldType_None { self.unknownModel = append(self.unknownModel, m) } m.fd.Type = fieldType m.fd.Complex = complexType var rawFieldValue string // 解析值 rawFieldValue, self.Col = m.getValue("Value") kind, enumvalue, ok := parseFieldValue(rawFieldValue) if !ok { return false } if td.Kind == model.DescriptorKind_None { td.Kind = kind // 一些字段有填值, 一些没填值 } else if td.Kind != kind { log.Errorf("%s", i18n.String(i18n.TypeSheet_DescriptorKindNotSame)) return false } if td.Kind == model.DescriptorKind_Enum { if _, ok := td.FieldByNumber[enumvalue]; ok { log.Errorf("%s %d", i18n.String(i18n.TypeSheet_DuplicatedEnumValue), enumvalue) return false } } m.fd.EnumValue = enumvalue m.fd.Comment, self.Col = m.getValue("Comment") var rawMeta string rawMeta, self.Col = m.getValue("Meta") if err := proto.UnmarshalText(rawMeta, &m.fd.Meta); err != nil { log.Errorf("%s, '%s'", i18n.String(i18n.TypeSheet_FieldMetaParseFailed), err.Error()) return false } td.Add(&m.fd) } return true }