public List <TypeDef> GetCompatibleTypes(List <KeyValuePair <String, Schema> > VersionAndSchemaList) { var ResultTypes = new List <TypeDef> { }; foreach (var k in Enumerable.Range(0, VersionAndSchemaList.Count - 1)) { var Old = VersionAndSchemaList[k]; var New = VersionAndSchemaList[k + 1]; var AddtionalTypesToBePreserved = Generate(Old.Value, New.Value).Revert; var h = new HashSet <String>(AddtionalTypesToBePreserved.Types.Select(t => t.VersionedName()), StringComparer.OrdinalIgnoreCase); var MapConf = new TypeMapConfiguration { MapTypeSpecKernel = (d, ts) => { if (ts.OnTypeRef && h.Contains(ts.TypeRef.VersionedName())) { return(TypeSpec.CreateTypeRef(new TypeRef { Name = ts.TypeRef.Name, Version = Old.Key })); } else { return(ts); } } }; ResultTypes = ResultTypes.Select(t => t.MapType(MapConf)).Concat(AddtionalTypesToBePreserved.GetTypesVersioned(Old.Key).Types).ToList(); } return(ResultTypes); }
public static FileParserResult ParseFile(Text Text) { var TypeFunctions = new HashSet <String>() { "Primitive", "Alias", "Record", "TaggedUnion", "Enum", "ClientCommand", "ServerCommand" }; var Functions = new HashSet <String>(TypeFunctions.Concat(new List <String>() { "Namespace", "Import" })); var ps = new TreeFormatParseSetting() { IsTableParameterFunction = Name => Functions.Contains(Name), IsTableContentFunction = Name => Functions.Contains(Name), IsTreeParameterFunction = Name => false, IsTreeContentFunction = Name => false }; var sp = new TreeFormatSyntaxParser(ps, Text); var ParserResult = sp.Parse(); var ts = new TreeSerializer(); var Types = new List <TypeDef>(); var TypeRefs = new List <TypeDef>(); var Imports = new List <String>(); var TypeToNamespace = new Dictionary <TypeDef, List <String> >(); var TypeToNamespaceImports = new Dictionary <TypeDef, List <List <String> > >(); var CurrentNamespace = new List <String>(); var CurrentNamespaceImports = new List <List <String> >(); var Positions = new Dictionary <Object, TextRange>(); foreach (var TopNode in ParserResult.Value.MultiNodesList) { if (TopNode.OnFunctionNodes) { var pr = new TreeFormatParseResult { Value = new Forest { MultiNodesList = new List <MultiNodes> { TopNode } }, Text = Text, Positions = ParserResult.Positions, RawFunctionCalls = ParserResult.RawFunctionCalls }; var es = new TreeFormatEvaluateSetting { FunctionCallEvaluator = (f, nm) => { Action <Object, Object> Mark = (SemanticsObj, SyntaxObj) => { var Range = nm.GetRange(SyntaxObj); if (Range.OnSome) { Positions.Add(SemanticsObj, Range.Value); } }; Func <TFSemantics.Node, List <String> > ExtractNamespaceParts = Node => { var Namespace = GetLeafNodeValue(Node, nm, "InvalidName"); var NamespaceParts = new List <String>(); int InvalidCharIndex; var osml = TokenParser.TrySplitSymbolMemberChain(Namespace, out InvalidCharIndex); if (osml.OnNone) { var Range = nm.GetRange(Node); var InvalidChar = Namespace.Substring(InvalidCharIndex, 1); if (Range.OnSome) { Range = new TextRange { Start = nm.Text.Calc(Range.Value.Start, InvalidCharIndex), End = nm.Text.Calc(Range.Value.Start, InvalidCharIndex + 1) }; } throw new InvalidTokenException("InvalidChar", new FileTextRange { Text = nm.Text, Range = Range }, InvalidChar); } foreach (var p in osml.Value) { if (p.Parameters.Count > 0) { var Range = nm.GetRange(Node); var Part = Namespace.Substring(p.SymbolStartIndex, p.SymbolEndIndex); if (Range.OnSome) { Range = new TextRange { Start = nm.Text.Calc(Range.Value.Start, p.SymbolStartIndex), End = nm.Text.Calc(Range.Value.Start, p.SymbolEndIndex) }; } throw new InvalidTokenException("InvalidNamespacePart", new FileTextRange { Text = nm.Text, Range = Range }, Part); } int LocalInvalidCharIndex; var oName = TokenParser.TryUnescapeSymbolName(p.Name, out LocalInvalidCharIndex); if (oName.OnNone) { InvalidCharIndex = p.NameStartIndex + LocalInvalidCharIndex; var Range = nm.GetRange(Node); var InvalidChar = Namespace.Substring(InvalidCharIndex, 1); if (Range.OnSome) { Range = new TextRange { Start = nm.Text.Calc(Range.Value.Start, InvalidCharIndex), End = nm.Text.Calc(Range.Value.Start, InvalidCharIndex + 1) }; } throw new InvalidTokenException("InvalidChar", new FileTextRange { Text = nm.Text, Range = Range }, InvalidChar); } NamespaceParts.Add(p.Name); } return(NamespaceParts); }; if (TypeFunctions.Contains(f.Name.Text)) { if (f.Parameters.Count < 1 || f.Parameters.Count > 2) { throw new InvalidEvaluationException("InvalidParameterCount", nm.GetFileRange(f), f); } var TypeRef = ParseTypeRef(f.Parameters[0], nm, Positions); var Name = TypeRef.Name; var Version = TypeRef.Version; var Attributes = new List <KeyValuePair <String, List <String> > >(); var Description = ""; if (f.Parameters.Count >= 2) { var DescriptionParameter = f.Parameters[1]; if (!DescriptionParameter.OnLeaf) { throw new InvalidEvaluationException("InvalidDescription", nm.GetFileRange(DescriptionParameter), DescriptionParameter); } var c = TokenParser.DecomposeDescription(DescriptionParameter.Leaf); Attributes = c.Attributes; Mark(Attributes, f.Parameters[1]); Description = c.Description; } var ContentLines = new List <FunctionCallTableLine> { }; if (f.Content.OnSome) { var ContentValue = f.Content.Value; if (!ContentValue.OnTableContent) { throw new InvalidEvaluationException("InvalidContent", nm.GetFileRange(ContentValue), ContentValue); } ContentLines = ContentValue.TableContent; } switch (f.Name.Text) { case "Primitive": { if (Version != "") { throw new InvalidEvaluationException("InvalidName", nm.GetFileRange(f.Parameters[0]), f.Parameters[0]); } var GenericParameters = new List <VariableDef>(); foreach (var Line in ContentLines) { String cName = null; TypeSpec cType = null; var cAttributes = new List <KeyValuePair <String, List <String> > >(); var cDescription = ""; if (Line.Nodes.Count == 2) { cName = GetLeafNodeValue(Line.Nodes[0], nm, "InvalidFieldName"); cType = ParseTypeSpec(Line.Nodes[1], nm, Positions); } else if (Line.Nodes.Count == 3) { cName = GetLeafNodeValue(Line.Nodes[0], nm, "InvalidFieldName"); cType = ParseTypeSpec(Line.Nodes[1], nm, Positions); var c = TokenParser.DecomposeDescription(GetLeafNodeValue(Line.Nodes[2], nm, "InvalidDescription")); cAttributes = c.Attributes; Mark(cAttributes, Line.Nodes[2]); cDescription = c.Description; } else if (Line.Nodes.Count == 0) { continue; } else { throw new InvalidEvaluationException("InvalidLineNodeCount", nm.GetFileRange(Line), Line); } if (cName.StartsWith("'")) { cName = new String(cName.Skip(1).ToArray()); var gp = new VariableDef { Name = cName, Type = cType, Attributes = cAttributes, Description = cDescription }; Mark(gp, Line); GenericParameters.Add(gp); } else { throw new InvalidEvaluationException("InvalidLine", nm.GetFileRange(Line), Line); } } var p = new PrimitiveDef { Name = Name, GenericParameters = GenericParameters, Attributes = Attributes, Description = Description }; Mark(p, f); var t = TypeDef.CreatePrimitive(p); Mark(t, f); Types.Add(t); TypeToNamespace.Add(t, CurrentNamespace); TypeToNamespaceImports.Add(t, CurrentNamespaceImports); return(new List <TFSemantics.Node> { }); } case "Alias": { var GenericParameters = new List <VariableDef>(); TypeSpec Type = null; foreach (var Line in ContentLines) { String cName = null; TypeSpec cType = null; var cAttributes = new List <KeyValuePair <String, List <String> > >(); var cDescription = ""; if (Line.Nodes.Count == 1) { if (Type != null) { throw new InvalidEvaluationException("InvalidLine", nm.GetFileRange(Line), Line); } Type = ParseTypeSpec(Line.Nodes[0], nm, Positions); continue; } else if (Line.Nodes.Count == 2) { cName = GetLeafNodeValue(Line.Nodes[0], nm, "InvalidFieldName"); cType = ParseTypeSpec(Line.Nodes[1], nm, Positions); } else if (Line.Nodes.Count == 3) { cName = GetLeafNodeValue(Line.Nodes[0], nm, "InvalidFieldName"); cType = ParseTypeSpec(Line.Nodes[1], nm, Positions); var c = TokenParser.DecomposeDescription(GetLeafNodeValue(Line.Nodes[2], nm, "InvalidDescription")); cAttributes = c.Attributes; Mark(cAttributes, Line.Nodes[2]); cDescription = c.Description; } else if (Line.Nodes.Count == 0) { continue; } else { throw new InvalidEvaluationException("InvalidLineNodeCount", nm.GetFileRange(Line), Line); } if (cName.StartsWith("'")) { cName = new String(cName.Skip(1).ToArray()); var gp = new VariableDef { Name = cName, Type = cType, Attributes = cAttributes, Description = cDescription }; Mark(gp, Line); GenericParameters.Add(gp); } else { throw new InvalidEvaluationException("InvalidLine", nm.GetFileRange(Line), Line); } } if (Type == null) { throw new InvalidEvaluationException("InvalidContent", nm.GetFileRange(ContentLines), ContentLines); } var a = new AliasDef { Name = Name, Version = Version, GenericParameters = GenericParameters, Type = Type, Attributes = Attributes, Description = Description }; Mark(a, f); var t = TypeDef.CreateAlias(a); Mark(t, f); Types.Add(t); TypeToNamespace.Add(t, CurrentNamespace); TypeToNamespaceImports.Add(t, CurrentNamespaceImports); return(new List <TFSemantics.Node> { }); } case "Record": { var GenericParameters = new List <VariableDef>(); var Fields = new List <VariableDef>(); foreach (var Line in ContentLines) { String cName = null; TypeSpec cType = null; var cAttributes = new List <KeyValuePair <String, List <String> > >(); var cDescription = ""; if (Line.Nodes.Count == 2) { cName = GetLeafNodeValue(Line.Nodes[0], nm, "InvalidFieldName"); cType = ParseTypeSpec(Line.Nodes[1], nm, Positions); } else if (Line.Nodes.Count == 3) { cName = GetLeafNodeValue(Line.Nodes[0], nm, "InvalidFieldName"); cType = ParseTypeSpec(Line.Nodes[1], nm, Positions); var c = TokenParser.DecomposeDescription(GetLeafNodeValue(Line.Nodes[2], nm, "InvalidDescription")); cAttributes = c.Attributes; Mark(cAttributes, Line.Nodes[2]); cDescription = c.Description; } else if (Line.Nodes.Count == 0) { continue; } else { throw new InvalidEvaluationException("InvalidLineNodeCount", nm.GetFileRange(Line), Line); } if (cName.StartsWith("'")) { cName = new String(cName.Skip(1).ToArray()); var gp = new VariableDef { Name = cName, Type = cType, Attributes = cAttributes, Description = cDescription }; Mark(gp, Line); GenericParameters.Add(gp); } else { var p = new VariableDef { Name = cName, Type = cType, Attributes = cAttributes, Description = cDescription }; Mark(p, Line); Fields.Add(p); } } var r = new RecordDef { Name = Name, Version = Version, GenericParameters = GenericParameters, Fields = Fields, Attributes = Attributes, Description = Description }; Mark(r, f); var t = TypeDef.CreateRecord(r); Mark(t, f); Types.Add(t); TypeToNamespace.Add(t, CurrentNamespace); TypeToNamespaceImports.Add(t, CurrentNamespaceImports); return(new List <TFSemantics.Node> { }); } case "TaggedUnion": { var GenericParameters = new List <VariableDef>(); var Alternatives = new List <VariableDef>(); foreach (var Line in ContentLines) { String cName = null; TypeSpec cType = null; var cAttributes = new List <KeyValuePair <String, List <String> > >(); var cDescription = ""; if (Line.Nodes.Count == 2) { cName = GetLeafNodeValue(Line.Nodes[0], nm, "InvalidAlternativeName"); cType = ParseTypeSpec(Line.Nodes[1], nm, Positions); } else if (Line.Nodes.Count == 3) { cName = GetLeafNodeValue(Line.Nodes[0], nm, "InvalidAlternativeName"); cType = ParseTypeSpec(Line.Nodes[1], nm, Positions); var c = TokenParser.DecomposeDescription(GetLeafNodeValue(Line.Nodes[2], nm, "InvalidDescription")); cAttributes = c.Attributes; Mark(cAttributes, Line.Nodes[2]); cDescription = c.Description; } else if (Line.Nodes.Count == 0) { continue; } else { throw new InvalidEvaluationException("InvalidLineNodeCount", nm.GetFileRange(Line), Line); } if (cName.StartsWith("'")) { cName = new String(cName.Skip(1).ToArray()); var gp = new VariableDef { Name = cName, Type = cType, Attributes = cAttributes, Description = cDescription }; Mark(gp, Line); GenericParameters.Add(gp); } else { var p = new VariableDef { Name = cName, Type = cType, Attributes = cAttributes, Description = cDescription }; Mark(p, Line); Alternatives.Add(p); } } var tu = new TaggedUnionDef { Name = Name, Version = Version, GenericParameters = GenericParameters, Alternatives = Alternatives, Attributes = Attributes, Description = Description }; Mark(tu, f); var t = TypeDef.CreateTaggedUnion(tu); Mark(t, f); Types.Add(t); TypeToNamespace.Add(t, CurrentNamespace); TypeToNamespaceImports.Add(t, CurrentNamespaceImports); return(new List <TFSemantics.Node> { }); } case "Enum": { var Literals = new List <LiteralDef>(); Int64 NextValue = 0; foreach (var Line in ContentLines) { String cName = null; Int64 cValue = NextValue; var cAttributes = new List <KeyValuePair <String, List <String> > >(); var cDescription = ""; if (Line.Nodes.Count == 1) { cName = GetLeafNodeValue(Line.Nodes[0], nm, "InvalidLiteralName"); cValue = NextValue; } else if (Line.Nodes.Count == 2) { cName = GetLeafNodeValue(Line.Nodes[0], nm, "InvalidLiteralName"); cValue = NumericStrings.InvariantParseInt64(GetLeafNodeValue(Line.Nodes[1], nm, "InvalidLiteralValue")); } else if (Line.Nodes.Count == 3) { cName = GetLeafNodeValue(Line.Nodes[0], nm, "InvalidLiteralName"); cValue = NumericStrings.InvariantParseInt64(GetLeafNodeValue(Line.Nodes[1], nm, "InvalidLiteralValue")); var c = TokenParser.DecomposeDescription(GetLeafNodeValue(Line.Nodes[2], nm, "InvalidDescription")); cAttributes = c.Attributes; Mark(cAttributes, Line.Nodes[2]); cDescription = c.Description; } else if (Line.Nodes.Count == 0) { continue; } else { throw new InvalidEvaluationException("InvalidLineNodeCount", nm.GetFileRange(Line), Line); } NextValue = cValue + 1; var ltl = new LiteralDef { Name = cName, Value = cValue, Attributes = cAttributes, Description = cDescription }; Mark(ltl, Line); Literals.Add(ltl); } var IntTypeName = new List <String> { "Int" }; Mark(IntTypeName, f); var r = new TypeRef { Name = IntTypeName, Version = "" }; Mark(r, f); var UnderlyingType = TypeSpec.CreateTypeRef(r); Mark(UnderlyingType, f); var ed = new EnumDef { Name = Name, Version = Version, UnderlyingType = UnderlyingType, Literals = Literals, Attributes = Attributes, Description = Description }; Mark(ed, f); var t = TypeDef.CreateEnum(ed); Mark(t, f); Types.Add(t); TypeToNamespace.Add(t, CurrentNamespace); TypeToNamespaceImports.Add(t, CurrentNamespaceImports); return(new List <TFSemantics.Node> { }); } case "ClientCommand": { var OutParameters = new List <VariableDef>(); var InParameters = new List <VariableDef>(); Boolean IsInParameter = false; foreach (var Line in ContentLines) { String cName = null; TypeSpec cType = null; var cAttributes = new List <KeyValuePair <String, List <String> > >(); var cDescription = ""; if (Line.Nodes.Count == 1) { if (GetLeafNodeValue(Line.Nodes[0], nm, "InvalidFieldName") == ">") { IsInParameter = true; continue; } else { throw new InvalidEvaluationException("InvalidLine", nm.GetFileRange(Line), Line); } } else if (Line.Nodes.Count == 2) { cName = GetLeafNodeValue(Line.Nodes[0], nm, "InvalidFieldName"); cType = ParseTypeSpec(Line.Nodes[1], nm, Positions); } else if (Line.Nodes.Count == 3) { cName = GetLeafNodeValue(Line.Nodes[0], nm, "InvalidFieldName"); cType = ParseTypeSpec(Line.Nodes[1], nm, Positions); var c = TokenParser.DecomposeDescription(GetLeafNodeValue(Line.Nodes[2], nm, "InvalidDescription")); cAttributes = c.Attributes; Mark(cAttributes, Line.Nodes[2]); cDescription = c.Description; } else if (Line.Nodes.Count == 0) { continue; } else { throw new InvalidEvaluationException("InvalidLineNodeCount", nm.GetFileRange(Line), Line); } var p = new VariableDef { Name = cName, Type = cType, Attributes = cAttributes, Description = cDescription }; Mark(p, Line); if (IsInParameter) { InParameters.Add(p); } else { OutParameters.Add(p); } } var cc = new ClientCommandDef { Name = Name, Version = Version, OutParameters = OutParameters, InParameters = InParameters, Attributes = Attributes, Description = Description }; Mark(cc, f); var t = TypeDef.CreateClientCommand(cc); Mark(t, f); Types.Add(t); TypeToNamespace.Add(t, CurrentNamespace); TypeToNamespaceImports.Add(t, CurrentNamespaceImports); return(new List <TFSemantics.Node> { }); } case "ServerCommand": { var OutParameters = new List <VariableDef>(); foreach (var Line in ContentLines) { String cName = null; TypeSpec cType = null; var cAttributes = new List <KeyValuePair <String, List <String> > >(); var cDescription = ""; if (Line.Nodes.Count == 2) { cName = GetLeafNodeValue(Line.Nodes[0], nm, "InvalidFieldName"); cType = ParseTypeSpec(Line.Nodes[1], nm, Positions); } else if (Line.Nodes.Count == 3) { cName = GetLeafNodeValue(Line.Nodes[0], nm, "InvalidFieldName"); cType = ParseTypeSpec(Line.Nodes[1], nm, Positions); var c = TokenParser.DecomposeDescription(GetLeafNodeValue(Line.Nodes[2], nm, "InvalidDescription")); cAttributes = c.Attributes; Mark(cAttributes, Line.Nodes[2]); cDescription = c.Description; } else if (Line.Nodes.Count == 0) { continue; } else { throw new InvalidEvaluationException("InvalidLineNodeCount", nm.GetFileRange(Line), Line); } var p = new VariableDef { Name = cName, Type = cType, Attributes = cAttributes, Description = cDescription }; Mark(p, Line); OutParameters.Add(p); } var sc = new ServerCommandDef { Name = Name, Version = Version, OutParameters = OutParameters, Attributes = Attributes, Description = Description }; Mark(sc, f); var t = TypeDef.CreateServerCommand(sc); Mark(t, f); Types.Add(t); TypeToNamespace.Add(t, CurrentNamespace); TypeToNamespaceImports.Add(t, CurrentNamespaceImports); return(new List <TFSemantics.Node> { }); } default: { throw new InvalidEvaluationException("UnknownFunction", nm.GetFileRange(f), f); } } } else if (f.Name.Text == "Namespace") { if (f.Parameters.Count != 1) { throw new InvalidEvaluationException("InvalidParameterCount", nm.GetFileRange(f), f); } var NamespaceParts = ExtractNamespaceParts(f.Parameters[0]); Mark(NamespaceParts, f); CurrentNamespace = NamespaceParts; return(new List <TFSemantics.Node> { }); } else if (f.Name.Text == "Import") { if (f.Parameters.Count != 0) { throw new InvalidEvaluationException("InvalidParameterCount", nm.GetFileRange(f), f); } var ContentLines = new List <FunctionCallTableLine> { }; if (f.Content.OnSome) { var ContentValue = f.Content.Value; if (!ContentValue.OnTableContent) { throw new InvalidEvaluationException("InvalidContent", nm.GetFileRange(ContentValue), ContentValue); } ContentLines = ContentValue.TableContent; } var NamespaceImports = new List <List <String> >(); foreach (var Line in ContentLines) { if (Line.Nodes.Count == 1) { var NamespaceParts = ExtractNamespaceParts(Line.Nodes[0]); Mark(NamespaceParts, Line.Nodes[0]); NamespaceImports.Add(NamespaceParts); } else if (Line.Nodes.Count == 0) { continue; } else { throw new InvalidEvaluationException("InvalidLineNodeCount", nm.GetFileRange(Line), Line); } } CurrentNamespaceImports = CurrentNamespaceImports.Concat(NamespaceImports).ToList(); return(new List <TFSemantics.Node> { }); } else { throw new InvalidEvaluationException("UnknownFunction", nm.GetFileRange(f), f); } } }; var e = new TreeFormatEvaluator(es, pr); e.Evaluate(); } else { var pr = new TreeFormatParseResult { Value = new Forest { MultiNodesList = new List <MultiNodes> { TopNode } }, Text = Text, Positions = ParserResult.Positions, RawFunctionCalls = ParserResult.RawFunctionCalls }; var es = new TreeFormatEvaluateSetting { }; var e = new TreeFormatEvaluator(es, pr); var er = e.Evaluate(); if (er.Value.Nodes.Count > 0) { var ReadResult = ts.Read <Schema>(CollectionOperations.CreatePair(er.Value, er.Positions)); Types.AddRange(ReadResult.Key.Types); TypeRefs.AddRange(ReadResult.Key.TypeRefs); Imports.AddRange(ReadResult.Key.Imports); foreach (var p in ReadResult.Value) { if (p.Value.Range.OnSome) { Positions.Add(p.Key, p.Value.Range.Value); } } } } } return(new FileParserResult { Text = Text, Positions = Positions, Types = Types, TypeRefs = TypeRefs, Imports = Imports, TypeToNamespace = TypeToNamespace, TypeToNamespaceImports = TypeToNamespaceImports }); }
private void ResolveNamespaces() { var TypeDictionary = new HashSet <String>(); List <String> ResolveTypeDefName(TypeDef t, List <String> Name, String Version) { var FullName = Name; if (TypeToNamespace.ContainsKey(t)) { FullName = TypeToNamespace[t].Concat(Name).ToList(); } TypeDictionary.Add((new TypeRef { Name = FullName, Version = Version }).VersionedName()); return(FullName); } List <String> ResolveTypeRefName(TypeDef t, TypeRef Ref, List <String> Name, String Version) { if (TypeToNamespace.ContainsKey(t)) { var CandidateFullName = TypeToNamespace[t].Concat(Name).ToList(); if (TypeDictionary.Contains((new TypeRef { Name = CandidateFullName, Version = Version }).VersionedName())) { return(CandidateFullName); } } if (TypeToNamespaceImports.ContainsKey(t)) { foreach (var Namespace in TypeToNamespaceImports[t]) { var CandidateFullName = Namespace.Concat(Name).ToList(); if (TypeDictionary.Contains((new TypeRef { Name = CandidateFullName, Version = Version }).VersionedName())) { return(CandidateFullName); } } } return(Name); } var conf = new TypeMapConfiguration { MapTypeDefKernel = t => { if (t.OnPrimitive) { var p = t.Primitive; return(TypeDef.CreatePrimitive(new PrimitiveDef { Name = ResolveTypeDefName(t, p.Name, ""), GenericParameters = p.GenericParameters, Attributes = p.Attributes, Description = p.Description })); } else if (t.OnAlias) { var a = t.Alias; return(TypeDef.CreateAlias(new AliasDef { Name = ResolveTypeDefName(t, a.Name, a.Version), Version = a.Version, GenericParameters = a.GenericParameters, Type = a.Type, Attributes = a.Attributes, Description = a.Description })); } else if (t.OnRecord) { var r = t.Record; return(TypeDef.CreateRecord(new RecordDef { Name = ResolveTypeDefName(t, r.Name, r.Version), Version = r.Version, GenericParameters = r.GenericParameters, Fields = r.Fields, Attributes = r.Attributes, Description = r.Description })); } else if (t.OnTaggedUnion) { var tu = t.TaggedUnion; return(TypeDef.CreateTaggedUnion(new TaggedUnionDef { Name = ResolveTypeDefName(t, tu.Name, tu.Version), Version = tu.Version, GenericParameters = tu.GenericParameters, Alternatives = tu.Alternatives, Attributes = tu.Attributes, Description = tu.Description })); } else if (t.OnEnum) { var e = t.Enum; return(TypeDef.CreateEnum(new EnumDef { Name = ResolveTypeDefName(t, e.Name, e.Version), Version = e.Version, UnderlyingType = e.UnderlyingType, Literals = e.Literals, Attributes = e.Attributes, Description = e.Description })); } else if (t.OnClientCommand) { var cc = t.ClientCommand; return(TypeDef.CreateClientCommand(new ClientCommandDef { Name = ResolveTypeDefName(t, cc.Name, cc.Version), Version = cc.Version, OutParameters = cc.OutParameters, InParameters = cc.InParameters, Attributes = cc.Attributes, Description = cc.Description })); } else if (t.OnServerCommand) { var sc = t.ServerCommand; return(TypeDef.CreateServerCommand(new ServerCommandDef { Name = ResolveTypeDefName(t, sc.Name, sc.Version), Version = sc.Version, OutParameters = sc.OutParameters, Attributes = sc.Attributes, Description = sc.Description })); } else { throw new InvalidOperationException(); } }, TypeDefMarker = MarkTypeDef, TypeSpecMarker = Mark, VariableDefMarker = Mark }; Types = Types.Select(t => t.MapType(conf)).ToList(); TypeRefs = TypeRefs.Select(t => t.MapType(conf)).ToList(); var confTypeSpec = new TypeMapConfiguration { MapTypeSpecKernel = (t, ts) => { if (ts.OnTypeRef) { return(TypeSpec.CreateTypeRef(new TypeRef { Name = ResolveTypeRefName(t, ts.TypeRef, ts.TypeRef.Name, ts.TypeRef.Version), Version = ts.TypeRef.Version })); } else if (ts.OnGenericParameterRef) { return(ts); } else if (ts.OnTuple) { return(ts); } else if (ts.OnGenericTypeSpec) { return(ts); } else { throw new InvalidOperationException(); } }, TypeDefMarker = Mark, TypeSpecMarker = Mark, VariableDefMarker = Mark }; Types = Types.Select(t => t.MapType(confTypeSpec)).ToList(); TypeRefs = TypeRefs.Select(t => t.MapType(confTypeSpec)).ToList(); TypeToNamespace = new Dictionary <TypeDef, List <String> >(); TypeToNamespaceImports = new Dictionary <TypeDef, List <List <String> > >(); }
public static Optional <TypeSpec> TryParseTypeSpec(String TypeString, Action <Object, int, int> Mark, out int InvalidCharIndex) { var osml = TokenParser.TrySplitSymbolMemberChain(TypeString, out InvalidCharIndex); if (osml.OnNone) { return(Optional <TypeSpec> .Empty); } var sml = osml.Value; var tTotal = Optional <TypeSpec> .Empty; var FirstStart = 0; foreach (var s in sml) { var LocalInvalidCharIndex = 0; var oName = TokenParser.TryUnescapeSymbolName(s.Name, out LocalInvalidCharIndex); if (oName.OnNone) { InvalidCharIndex = s.NameStartIndex + LocalInvalidCharIndex; return(Optional <TypeSpec> .Empty); } var Name = oName.Value; var l = new List <TypeSpec>(); foreach (var p in s.Parameters) { var LocalLocalInvalidCharIndex = 0; var ov = TryParseTypeSpec(p.Key, (o, Start, End) => Mark(o, p.Value + Start, p.Value + End), out LocalLocalInvalidCharIndex); if (ov.OnNone) { InvalidCharIndex = p.Value + LocalLocalInvalidCharIndex; return(Optional <TypeSpec> .Empty); } l.Add(ov.Value); } Mark(l, s.NameEndIndex, s.SymbolEndIndex); TypeSpec t; if (Name.StartsWith("'")) { Name = new String(Name.Skip(1).ToArray()); t = TypeSpec.CreateGenericParameterRef(Name); } else { if (tTotal.OnSome) { if (!tTotal.Value.OnTypeRef || (tTotal.Value.TypeRef.Version != "")) { InvalidCharIndex = s.NameStartIndex; return(Optional <TypeSpec> .Empty); } } String Version; ParseNameAndVersion(Name, out Name, out Version); var NameList = tTotal.OnSome ? tTotal.Value.TypeRef.Name.Concat(new List <String> { Name }).ToList() : new List <String> { Name }; var Ref = new TypeRef { Name = NameList, Version = Version }; Mark(NameList, s.NameStartIndex, s.NameStartIndex + Name.Length); Mark(Ref, s.NameStartIndex, s.NameEndIndex); t = TypeSpec.CreateTypeRef(Ref); } Mark(t, s.NameStartIndex, s.NameEndIndex); if (s.Parameters.Count > 0) { if (tTotal.OnNone && String.Equals(Name, "Tuple", StringComparison.OrdinalIgnoreCase)) { t = TypeSpec.CreateTuple(l); } else { if (!t.OnTypeRef) { InvalidCharIndex = s.NameStartIndex; return(Optional <TypeSpec> .Empty); } var gts = new GenericTypeSpec { TypeSpec = t, ParameterValues = l }; Mark(gts, s.SymbolStartIndex, s.SymbolEndIndex); t = TypeSpec.CreateGenericTypeSpec(gts); } Mark(t, s.SymbolStartIndex, s.SymbolEndIndex); } if (tTotal.OnNone) { tTotal = t; FirstStart = s.SymbolStartIndex; } else { if (!tTotal.Value.OnTypeRef || !t.OnTypeRef) { InvalidCharIndex = s.NameStartIndex; return(Optional <TypeSpec> .Empty); } tTotal = t; } } return(tTotal); }