private object LocalValueExpected(LocalTypeMd typeMd) { object value; TextSpan textSpan; if (!LocalValue(typeMd, out value, out textSpan)) { ErrorAndThrow(new DiagMsg(DiagnosticCode.ValueExpected)); } return value; }
private bool LocalValue(LocalTypeMd typeMd, out object result, out TextSpan textSpan) { Token token; if (Null(out token)) { if (typeMd != null && !typeMd.IsNullable) { ErrorAndThrow(new DiagMsg(DiagnosticCode.NullNotAllowed), token.TextSpan); } result = null; textSpan = token.TextSpan; return true; } if (AtomValue(out token)) { if (typeMd != null) { var nonNullableTypeMd = typeMd.NonNullableType; var typeKind = nonNullableTypeMd.Kind; if (!typeKind.IsAtom()) { if (typeKind == TypeKind.Enum) { typeKind = nonNullableTypeMd.TryGetGlobalType<EnumTypeMd>().UnderlyingType.Kind; } else { ErrorAndThrow(new DiagMsg(DiagnosticCode.SpecificValueExpected, typeKind.ToString()), token.TextSpan); } } result = AtomExtensions.TryParse(typeKind, token.Value); if (result == null) { ErrorAndThrow(new DiagMsg(DiagnosticCode.InvalidAtomValue, typeKind.ToString(), token.Value), token.TextSpan); } } else { result = token.Value; } textSpan = token.TextSpan; return true; } if (PeekToken('(', '{', '<')) {//class value if (typeMd != null) { var nonNullableTypeMd = typeMd.NonNullableType; var typeKind = nonNullableTypeMd.Kind; if (typeKind != TypeKind.Class) { ErrorAndThrow(new DiagMsg(DiagnosticCode.SpecificValueExpected, typeKind.ToString())); } return ClassValue(nonNullableTypeMd.TryGetGlobalType<ClassTypeMd>(), out result, out textSpan); } else { return ClassValue(null, out result, out textSpan); } } if (Name(out token)) {//enum value TokenExpected((int)TokenKind.ColonColon, ":: expected."); var nameToken = NameExpected(); var fullName = new FullName(GetUri(token), nameToken.Value); EnumTypeMd enumMd = null; if (typeMd != null) { var nonNullableTypeMd = typeMd.NonNullableType; var typeKind = nonNullableTypeMd.Kind; if (typeKind != TypeKind.Enum) { ErrorAndThrow(new DiagMsg(DiagnosticCode.SpecificValueExpected, typeKind.ToString()), nameToken.TextSpan); } enumMd = ProgramMd.TryGetGlobalType<EnumTypeMd>(fullName); if (enumMd == null) { ErrorAndThrow(new DiagMsg(DiagnosticCode.InvalidEnumReference, fullName.ToString()), nameToken.TextSpan); } var declaredEnumMd = nonNullableTypeMd.TryGetGlobalType<EnumTypeMd>(); if (enumMd != declaredEnumMd) { ErrorAndThrow(new DiagMsg(DiagnosticCode.EnumNotEqualToTheDeclared, fullName.ToString(), declaredEnumMd.FullName.ToString()), nameToken.TextSpan); } } TokenExpected('.'); var memberNameToken = NameExpected(); if (enumMd != null) { if (!enumMd._members.TryGetValue(memberNameToken.Value, out result)) { ErrorAndThrow(new DiagMsg(DiagnosticCode.InvalidEnumMemberName, memberNameToken.Value), memberNameToken.TextSpan); } } else { result = new UntypedEnumValue(fullName, memberNameToken.Value); } textSpan = memberNameToken.TextSpan; return true; } if (Token('[', out token)) { if (typeMd != null) { var nonNullableTypeMd = typeMd.NonNullableType; var typeKind = nonNullableTypeMd.Kind; var isSet = typeKind == TypeKind.Set; if (typeKind != TypeKind.List && !isSet) { ErrorAndThrow(new DiagMsg(DiagnosticCode.SpecificValueExpected, typeKind.ToString()), token.TextSpan); } var collTypeMd = (CollectionTypeMd)nonNullableTypeMd; var collObj = collTypeMd.CreateInstance(); var itemMd = collTypeMd.ItemOrValueType; object itemObj; TextSpan ts; while (true) { if (LocalValue(itemMd, out itemObj, out ts)) { if (isSet) { if (!collTypeMd.InvokeBoolAdd(collObj, itemObj)) { ErrorAndThrow(new DiagMsg(DiagnosticCode.DuplicateSetItem), ts); } } else { collTypeMd.InvokeAdd(collObj, itemObj); } if (!Token(',')) { break; } } else { break; } } TokenExpected(']'); result = collObj; } else { var listObj = new List<object>(); object itemObj; TextSpan ts; while (true) { if (LocalValue(null, out itemObj, out ts)) { listObj.Add(itemObj); if (!Token(',')) { break; } } else { break; } } TokenExpected(']'); result = listObj; } textSpan = token.TextSpan; return true; } if (Token((int)TokenKind.DollarOpenBracket, out token)) { if (typeMd != null) { var nonNullableTypeMd = typeMd.NonNullableType; var typeKind = nonNullableTypeMd.Kind; if (typeKind != TypeKind.Map) { ErrorAndThrow(new DiagMsg(DiagnosticCode.SpecificValueExpected, typeKind.ToString()), token.TextSpan); } var collTypeMd = (CollectionTypeMd)nonNullableTypeMd; var collObj = collTypeMd.CreateInstance(); var keyMd = collTypeMd.MapKeyType; var valueMd = collTypeMd.ItemOrValueType; object keyObj; TextSpan ts; while (true) { if (LocalValue(keyMd, out keyObj, out ts)) { if (collTypeMd.InvokeContainsKey(collObj, keyObj)) { ErrorAndThrow(new DiagMsg(DiagnosticCode.DuplicateMapKey), ts); } TokenExpected('='); collTypeMd.InvokeAdd(collObj, keyObj, LocalValueExpected(valueMd)); if (!Token(',')) { break; } } else { break; } } TokenExpected(']'); result = collObj; } else { var mapObj = new Dictionary<object, object>(); object keyObj; TextSpan ts; while (true) { if (LocalValue(null, out keyObj, out ts)) { TokenExpected('='); mapObj.Add(keyObj, LocalValueExpected(null)); if (!Token(',')) { break; } } else { break; } } TokenExpected(']'); result = mapObj; } textSpan = token.TextSpan; return true; } result = null; textSpan = default(TextSpan); return false; }