static ITypeDecleration ReadEnumType(MsgCodeReader reader, string ns, string[] parentTypes, TypeDict typeDict, bool requireEnumKeyWord) { TypeEnum type = null; ShellType ret = null; int requiredChar = -1; string enumName = null; string[] newParentTypes = null; string enumValue = null; bool enumEqual = false; bool isEnumInt = false; int enumInt = -1; bool done = false; while (reader.CanPeek()) { char chr = (char)reader.Peek(); //Debug.Log(chr); if (WHITE_CHARS.IndexOf(chr) >= 0) { reader.Next(); continue; } if (requiredChar >= 0) { if ((char)requiredChar != chr) { throw new Exception(string.Format("'{0}' is required !", (char)requiredChar)); } requiredChar = -1; reader.Next(); continue; } if (chr == '\n') { reader.Next(); continue; } //Debug.LogWarning(chr); if (string.IsNullOrEmpty(enumName)) { enumName = ReadContentWord(reader); if (requireEnumKeyWord && enumName == "enum") { enumName = null; requireEnumKeyWord = false; } continue; } else { if (type == null) { if (chr != '{') { throw new Exception("'{' is required after enum name !"); } if (newParentTypes == null) { if (parentTypes == null) { parentTypes = new string[0]; } newParentTypes = new string[parentTypes.Length + 1]; Array.Copy(parentTypes, 0, newParentTypes, 0, parentTypes.Length); newParentTypes[parentTypes.Length] = enumName; } ret = typeDict.GetType(ns, parentTypes, enumName, false); if (ret != null && ret.type is TypeEnum) { type = ret.type as TypeEnum; } else { if (ret == null) { ret = new ShellType(enumName); } type = new TypeEnum(enumName, false); ret.type = type; } typeDict.AddType(ns, parentTypes, enumName, ret); reader.Next(); } else if (chr == '}') { //TODO is illegal reader.Next(); done = true; break; } else if (string.IsNullOrEmpty(enumValue)) { enumValue = ReadContentWord(reader); if (string.IsNullOrEmpty(enumValue)) { throw new Exception("Enum Value is required !"); } } else if (!enumEqual) { if (chr != '=') { throw new Exception("'=' is required between enum value and its int value !"); } enumEqual = true; reader.Next(); } else if (!isEnumInt) { string v = ReadContentWord(reader); if (!TryParseInt(v, out enumInt)) { throw new Exception(string.Format("Cannot parse enum int value '{0}' into int !", v)); } isEnumInt = true; } else { if (chr != ';') { throw new Exception("';' is required after enum value definition !"); } type.AddEnum(enumValue, reader.LastComment, enumInt); enumValue = null; enumEqual = false; isEnumInt = false; enumInt = -1; reader.Next(); } } } if (!done) { throw new Exception(string.Format("Enum type '{0}' is not completed !", enumName)); } //Debug.Log(ret); return(ret); }
static ITypeDecleration ReadProtoType(MsgCodeReader reader, string ns, string[] parentTypes, TypeDict typeDict, bool requireMsgKeyWord, List <string> usings = null) { string typeName = null; ShellType ret = null; TypeCustom type = null; bool typeExtend = false; string baseType = null; bool done = false; bool isProperty = false; bool isArrayProperty = false; string propertyName = null; string propertyType = null; bool protoMemberEq = false; int protoMember = -1; int hasDefaultVal = 0; string defaultValue = null; string[] newParentTypes = null; string comments = null; while (reader.CanPeek()) { char chr = (char)reader.Peek(); if (chr == '\n') { reader.Next(); continue; } if (WHITE_CHARS.IndexOf(chr) >= 0) { reader.Next(); continue; } //Debug.LogFormat("'{0}' at Line {1} Column {2}", chr, reader.LineCount, reader.Column - 1); if (string.IsNullOrEmpty(typeName)) { typeName = ReadContentWord(reader); if (requireMsgKeyWord && typeName == "message") { typeName = null; requireMsgKeyWord = false; } continue; } else { bool typeDone = false; if (type == null) { if (chr != '{') { string w = ReadContentWord(reader, "."); if (typeExtend) { if (string.IsNullOrEmpty(baseType)) { baseType = w; continue; } } else { if (w == "extend") { typeExtend = true; continue; } } Debug.LogWarning(w); throw new Exception("'{' is required after message name !"); } if (newParentTypes == null) { if (parentTypes == null) { parentTypes = new string[0]; } newParentTypes = new string[parentTypes.Length + 1]; Array.Copy(parentTypes, 0, newParentTypes, 0, parentTypes.Length); newParentTypes[parentTypes.Length] = typeName; } ret = typeDict.GetType(ns, parentTypes, typeName, false, usings); if (ret != null && ret.type is TypeCustom) { type = ret.type as TypeCustom; } else { if (ret == null) { ret = new ShellType(typeName); } type = new TypeCustom(typeName); ret.type = type; } typeDict.AddType(ns, parentTypes, typeName, ret); type.SetTypeExtend(baseType); reader.Next(); } else if (chr == '}') { //TODO is illegal reader.Next(); done = true; break; } else if (!isProperty) { comments = reader.LastComment; string kw = ReadContentWord(reader); if (kw == "optional" || kw == "required") { isProperty = true; isArrayProperty = false; } else if (kw == "repeated") { isProperty = true; isArrayProperty = true; } else if (kw == "message") { isProperty = false; isArrayProperty = false; ITypeDecleration subType = ReadProtoType(reader, ns, newParentTypes, typeDict, false); if (!string.IsNullOrEmpty(comments)) { subType.AddTypeComments(comments); } comments = null; type.AddSubType(subType); } else if (kw == "enum") { ITypeDecleration subType = ReadEnumType(reader, ns, newParentTypes, typeDict, false); if (!string.IsNullOrEmpty(comments)) { subType.AddTypeComments(comments); } comments = null; type.AddSubType(subType); } else { throw new Exception(string.Format("Unknown key word '{0}' !", kw)); } } else if (string.IsNullOrEmpty(propertyType)) { propertyType = ReadContentWord(reader); if (string.IsNullOrEmpty(propertyType)) { throw new Exception("Property Type is required !"); } } else if (string.IsNullOrEmpty(propertyName)) { propertyName = ReadContentWord(reader); if (string.IsNullOrEmpty(propertyName)) { throw new Exception("Property Name is required !"); } } else if (!protoMemberEq) { if (chr != '=') { throw new Exception("'=' is required after property name !"); } protoMemberEq = true; reader.Next(); } else if (protoMember <= 0) { string pm = ReadContentWord(reader); //Debug.LogWarning("pm : " + pm + " char " + reader.Peek()); if (!TryParseInt(pm, out protoMember)) { throw new Exception(string.Format("Cannot parse proto member '{0}' into int !", pm)); } if (protoMember <= 0) { throw new Exception("Proto member should be greater than or equal to 1"); } } else if (hasDefaultVal == 0) { if (chr == ';') { typeDone = true; } else { if (chr != '[') { throw new Exception("';' or '[default=xxx]' is required in property definition !"); } hasDefaultVal = 1; } reader.Next(); } else if (hasDefaultVal == 1) { string def = ReadContentWord(reader); if (def != "default") { Debug.LogError(def); throw new Exception("'[default=xxx]' is required in property definition !"); } hasDefaultVal = 2; } else if (hasDefaultVal == 2) { if (chr != '=') { throw new Exception("'[default=xxx]' is required in property definition !"); } hasDefaultVal = 3; reader.Next(); } else if (hasDefaultVal == 3) { defaultValue = ReadContentString(reader, "]\n"); if (string.IsNullOrEmpty(defaultValue)) { throw new Exception("Illegal default value in property definition !"); } Debug.LogWarning("default value : " + defaultValue); hasDefaultVal = 4; } else if (hasDefaultVal == 4) { if (chr != ']') { throw new Exception("'[default=xxx]' is required in property definition !"); } hasDefaultVal = 5; reader.Next(); } else { if (chr != ';') { throw new Exception("';' is required after property definition !"); } typeDone = true; reader.Next(); } if (typeDone) { TypeBase t = TypeHelper.GetXmlValueType(propertyType); if (t == null) { t = typeDict.GetType(ns, newParentTypes, propertyType, true, usings); } //Debug.LogWarningFormat("\t{0}{1} {2} = {3}", propertyType, isArrayProperty ? "[]" : "", propertyName, protoMember); type.AddField(propertyName, t, isArrayProperty, defaultValue, comments, protoMember); propertyType = null; propertyName = null; protoMemberEq = false; isArrayProperty = false; protoMember = -1; isProperty = false; comments = null; hasDefaultVal = 0; defaultValue = null; } } } if (!done) { throw new Exception(string.Format("message '{0}' is not completed !", typeName)); } //Debug.Log(ret); return(ret); }