private bool ParsingUnit(string filePath, TextReader reader, LoadingContext context, ClassTypeMd classTypeMd, out object result) { try { Init(filePath, reader, context); object obj; TextSpan textSpan; if (ClassValue(classTypeMd, out obj, out textSpan)) { EndOfFileExpected(); result = obj; return true; } else { ErrorAndThrow("Class value expected."); } } catch (LoadingException) { } finally { Clear(); } result = null; return false; }
private bool ClassValue(ClassTypeMd declaredClsMd, out object result, out TextSpan textSpan) { var hasAliasUriList = false; if (Token('<')) { List<AliasUri> auList = null; while (true) { Token aliasToken; if (Name(out aliasToken)) { var alias = aliasToken.Value; if (auList == null) { auList = new List<AliasUri>(); } else { foreach (var item in auList) { if (item.Alias == alias) { ErrorAndThrow(new DiagMsg(DiagnosticCode.DuplicateUriAlias, alias), aliasToken.TextSpan); } } } TokenExpected('='); auList.Add(new AliasUri(alias, StringExpected().Value)); if (!Token(',')) { break; } } else { break; } } TokenExpected('>'); if (auList != null) { _aliasUriListStack.Push(auList); hasAliasUriList = true; } } var hasTypeIndicator = false; ClassTypeMd clsMd = null; var fullName = default(FullName); if (Token('(')) { hasTypeIndicator = true; var aliasToken = NameExpected(); TokenExpected((int)TokenKind.ColonColon, ":: expected."); var nameToken = NameExpected(); TokenExpected(')'); fullName = new FullName(GetUri(aliasToken), nameToken.Value); textSpan = nameToken.TextSpan; if (declaredClsMd != null) { clsMd = ProgramMd.TryGetGlobalType<ClassTypeMd>(fullName); if (clsMd == null) { ErrorAndThrow(new DiagMsg(DiagnosticCode.InvalidClassReference, fullName.ToString()), textSpan); } if (!clsMd.IsEqualToOrDeriveFrom(declaredClsMd)) { ErrorAndThrow(new DiagMsg(DiagnosticCode.ClassNotEqualToOrDeriveFromTheDeclared, fullName.ToString(), declaredClsMd.FullName.ToString()), textSpan); } } } else { textSpan = default(TextSpan); } Token openBraceToken; if (Token('{', out openBraceToken)) { if (!hasTypeIndicator) { textSpan = openBraceToken.TextSpan; } } else { if (hasAliasUriList || hasTypeIndicator) { ErrorAndThrow("{ expected."); } result = null; return false; } if (declaredClsMd != null) { if (!hasTypeIndicator) { clsMd = declaredClsMd; fullName = declaredClsMd.FullName; } if (clsMd.IsAbstract) { ErrorAndThrow(new DiagMsg(DiagnosticCode.ClassIsAbstract, fullName.ToString()), textSpan); } var obj = clsMd.CreateInstance(); if (!clsMd.InvokeOnLoad(true, obj, _context, textSpan)) { Throw(); } var propMdMap = clsMd._propertyMap; HashSet<string> propNameSet = null; Dictionary<string, object> unknownPropMap = null; while (true) { Token propNameToken; if (Name(out propNameToken)) { var propName = propNameToken.Value; if (propNameSet == null) { propNameSet = new HashSet<string>(); } else if (propNameSet.Contains(propName)) { ErrorAndThrow(new DiagMsg(DiagnosticCode.DuplicatePropertyName, propName), propNameToken.TextSpan); } propNameSet.Add(propName); TokenExpected('='); PropertyMd propMd; if (propMdMap.TryGetValue(propName, out propMd)) { propMd.SetValue(obj, LocalValueExpected(propMd.Type)); } else { if (unknownPropMap == null) { unknownPropMap = new Dictionary<string, object>(); } unknownPropMap.Add(propName, LocalValueExpected(null)); } if (!Token(',')) { break; } } else { break; } } var closeBraceToken = TokenExpected('}'); if (propMdMap.Count > 0) { var needThrow = false; foreach (var propMd in propMdMap.Values) { if (!propMd.Type.IsNullable && (propNameSet == null || !propNameSet.Contains(propMd.Name))) { Error(new DiagMsg(DiagnosticCode.PropertyMissing, propMd.Name), closeBraceToken.TextSpan); needThrow = true; } } if (needThrow) { Throw(); } } if (unknownPropMap != null) { clsMd.SetUnknownProperties(obj, unknownPropMap); } if (!clsMd.InvokeOnLoad(false, obj, _context, textSpan)) { Throw(); } result = obj; } else { Dictionary<string, object> propMap = null; while (true) { Token propNameToken; if (Name(out propNameToken)) { var propName = propNameToken.Value; if (propMap == null) { propMap = new Dictionary<string, object>(); } else if (propMap.ContainsKey(propName)) { ErrorAndThrow(new DiagMsg(DiagnosticCode.DuplicatePropertyName, propName), propNameToken.TextSpan); } TokenExpected('='); propMap.Add(propName, LocalValueExpected(null)); if (!Token(',')) { break; } } else { break; } } TokenExpected('}'); result = new UntypedObject(fullName, propMap); } if (hasAliasUriList) { _aliasUriListStack.Pop(); } return true; }
public static bool Parse(string filePath, TextReader reader, LoadingContext context, ClassTypeMd classTypeMd, out object result) { if (classTypeMd == null) throw new ArgumentNullException("classTypeMd"); return Instance.ParsingUnit(filePath, reader, context, classTypeMd, out result); }