static string HandleAddMethod(ParsedComponent parsedComponent, string add_extension) { var parameters = parsedComponent.Fields .Select(x => x.Type + " " + x.Name) .Aggregate((x, y) => x + ", " + y); var fieldSequence = parsedComponent.Fields .Select(x => "c." + (parsedComponent.IsReactive() ? x.Name.VariateFirstChar() : x.Name.FirstCharToUpper()) + " = " + x.Name + ";") .Aggregate((x, y) => x + Format.NewLine(2) + y); add_extension = add_extension .Replace(ComponentParametersTag, parameters) .Replace(AddingComponentsSequenceTag, fieldSequence); return(add_extension); }
internal void ConnectTo(string senderPort, ParsedComponent receiver, string receiverPort) { senderPort = senderPort.Substring(0, 1).ToUpperInvariant() + senderPort.Substring(1).ToLowerInvariant(); receiverPort = receiverPort.Substring(0, 1).ToUpperInvariant() + receiverPort.Substring(1).ToLowerInvariant(); if (!OutputPorts.Contains(senderPort)) { OutputPorts = OutputPorts.Add(senderPort); } if (!receiver.InputPorts.Contains(receiverPort)) { receiver.InputPorts = receiver.InputPorts.Add(receiverPort); } OutputPortConnections = OutputPortConnections.Add(Tuple.Create(senderPort, receiver, receiverPort)); }
void GenerateComponentReactives(ParsedComponent parsedComponent) { if (!parsedComponent.HasFields) { return; } string result = MayBakeUsings() ? parsedComponent.Usings : string.Empty; var snippet = File.ReadAllText(settings.CodeSnippets.ComponentReactive); var subSnippet = snippet.Split(new string[] { ComponentReactiveBlock }, StringSplitOptions.None)[1]; string members = ""; if (parsedComponent.IsReactive()) { members = parsedComponent.Fields .Select(field => subSnippet .Replace(FieldPascalCaseTag, field.Name.VariateFirstChar()) .Replace(FieldCamelCaseTag, field.Name) .Replace(FieldCamelCase_SetTag, field.Name == "value" ? "this." + field.Name : field.Name) .Replace(FieldTypeTag, field.Type) .Replace(FieldIdTag, field.Index.ToString())) .Aggregate((x, y) => x + Format.NewLine(1) + y); } else { members = parsedComponent.Fields .Select(field => $"public {field.Type} {field.Name.FirstCharToUpper()};") .Aggregate((x, y) => x + Format.NewLine(1) + y); } var componentReactive = snippet .Replace(ComponentNameTag, parsedComponent.ComponentName) .Replace(subSnippet, members) .Replace(ComponentReactiveBlock, ""); if (MayBakeUsings()) { componentReactive = parsedComponent.Usings + componentReactive; } SaveGeneration(componentReactive, new Tag(TagKeys.Component, parsedComponent.ComponentName), new Tag(TagKeys.GenerationType, GenerationTypes.Reactive)); }
static ParsedComponent CreateOrRetrieveComponentFromString(string stringVersionOfComponent, int sourceLineNumber, Dictionary <string, ParsedComponent> components) { string componentName; string typeName = null; if (Regex.IsMatch(stringVersionOfComponent, COMPONENT_WITH_TYPE_DECLARATION)) { var match = Regex.Match(stringVersionOfComponent, COMPONENT_WITH_TYPE_DECLARATION); componentName = match.Groups[1].Value; typeName = match.Groups[2].Value; var metadata = ImmutableDictionary <string, string> .Empty; for (var i = 3; i < match.Groups.Count; i++) { var matchMeta = Regex.Match(match.Groups[i].Value, COMPONENT_METADATA); metadata = metadata.Add(matchMeta.Groups[1].Value, matchMeta.Groups[2].Value); } if (components.ContainsKey(componentName)) { throw new ArgumentException(string.Format("Invalid input on line {0}, process '{1}' has already been declared", sourceLineNumber, componentName)); } var component = new ParsedComponent(componentName, typeName, metadata); component.Setup(); components[componentName] = component; return(component); } else { componentName = stringVersionOfComponent; if (!components.ContainsKey(componentName)) { throw new ArgumentException(string.Format("Invalid input on line {0}, the process '{1}' has not been declared", sourceLineNumber, componentName)); } return(components[componentName]); } }
void GenerateGroupBuilders(ParsedComponent parsedComponent) { var group_builder_snippet = File.ReadAllText(settings.CodeSnippets.Group_Builder); foreach (var context in parsedComponent.Contexts) { var group_builderFile = group_builder_snippet .Replace(ContextNameTag, context) .Replace(ComponentNameTag, parsedComponent.ComponentName); SaveGeneration(group_builderFile, new Tag(TagKeys.Context, context), new Tag(TagKeys.Component, parsedComponent.ComponentName), new Tag(TagKeys.GenerationType, GenerationTypes.GroupBuilder)); if (!parsedComponent.HasFields || !parsedComponent.IsReactive()) { continue; } var snippetPath = parsedComponent.Fields.Length > 1 ? settings.CodeSnippets.Collector : settings.CodeSnippets.CollectorFieldless; var collector_snippet = File.ReadAllText(snippetPath); var componentEnumValues = parsedComponent.Fields .Select(field => field.Name) .Aggregate((x, y) => x + "," + Format.NewLine(1) + y); var collector_File = collector_snippet .Replace(ComponentNameTag, parsedComponent.ComponentName) .Replace(ComponentEnumValuesTag, componentEnumValues) .Replace(ContextNameTag, context); SaveGeneration(collector_File, new Tag(TagKeys.Context, context), new Tag(TagKeys.Component, parsedComponent.ComponentName), new Tag(TagKeys.GenerationType, GenerationTypes.Collector)); } }
private static FbpParseResult Parse(string fbpProgram, Dictionary <string, object> initialData) { var components = new Dictionary <string, ParsedComponent>(); var lines = fbpProgram.Split('\n'); if (initialData == null) { initialData = new Dictionary <string, object>(); } for (var i = 0; i < lines.Length; ++i) { var line = lines[i].Trim(); if (Regex.IsMatch(line, COMMENT)) { continue; } var separatorIndex = line.IndexOf("->"); if (separatorIndex < 0) { continue; } var senderText = line.Substring(0, separatorIndex).Trim(); var receiverText = line.Substring(separatorIndex + 2).Trim(); ParsedComponent receiver = null; string receiverPort = null; if (Regex.IsMatch(receiverText, PORT_AND_COMPONENT)) { var match = Regex.Match(receiverText, PORT_AND_COMPONENT); receiverPort = match.Groups[1].Value; receiver = CreateOrRetrieveComponentFromString(match.Groups[2].Value, i, components); } else if (Regex.IsMatch(receiverText, PORT_AND_COMPONENT_WITH_TYPE)) { var match = Regex.Match(receiverText, PORT_AND_COMPONENT_WITH_TYPE); receiverPort = match.Groups[1].Value; receiver = CreateOrRetrieveComponentFromString(match.Groups[2].Value, i, components); } else { throw new ArgumentException(string.Format("Invalid input on line {0}, receiver declaration is malformed: '{1}'", i, receiverText)); } if (Regex.IsMatch(senderText, COMPONENT_AND_PORT)) { var match = Regex.Match(senderText, COMPONENT_AND_PORT); var sender = CreateOrRetrieveComponentFromString(match.Groups[1].Value, i, components); var senderPort = match.Groups[2].Value; sender.ConnectTo(senderPort, receiver, receiverPort); } else if (Regex.IsMatch(senderText, COMPONENT_AND_PORT_WITH_TYPE)) { var match = Regex.Match(senderText, COMPONENT_AND_PORT_WITH_TYPE); var sender = CreateOrRetrieveComponentFromString(match.Groups[1].Value, i, components); var senderPort = match.Groups[2].Value; sender.ConnectTo(senderPort, receiver, receiverPort); } else if (Regex.IsMatch(senderText, INITIAL_PASSED_IN_DATA)) { var match = Regex.Match(senderText, INITIAL_PASSED_IN_DATA); var key = match.Groups[1].Value; if (initialData.ContainsKey(key)) { receiver.SetInitialData(receiverPort, initialData[key]); } else { throw new ArgumentException(string.Format("Initial data {0} was not found in the provided Dictionary", key)); } } else if (Regex.IsMatch(senderText, INITIAL_BOOL_DATA)) { var match = Regex.Match(senderText, INITIAL_BOOL_DATA); receiver.SetInitialData(receiverPort, bool.Parse(match.Value)); } else if (Regex.IsMatch(senderText, INITIAL_STRING_DATA)) { var match = Regex.Match(senderText, INITIAL_STRING_DATA); /* * var metadata = ImmutableDictionary<string, string>.Empty.Add("value", match.Groups[2].Value); * var component = new ParsedComponent("Value", "string", metadata); * component.Setup(); * components[component.Name] = component; * component.ConnectTo("Value", receiver, receiverPort); */ receiver.SetInitialData(receiverPort, match.Groups[2].Value.Replace("\\'", "'")); } else if (Regex.IsMatch(senderText, INITIAL_FLOAT_DATA)) { var match = Regex.Match(senderText, INITIAL_FLOAT_DATA); receiver.SetInitialData(receiverPort, float.Parse(match.Value)); } else if (Regex.IsMatch(senderText, INITIAL_INT_DATA)) { var match = Regex.Match(senderText, INITIAL_INT_DATA); receiver.SetInitialData(receiverPort, int.Parse(match.Value)); } else { throw new ArgumentException(string.Format("Invalid input on line {0}, sender declaration is malformed: '{1}'", i, senderText)); } } return(new FbpParseResult(ImmutableList <ParsedComponent> .Empty.AddRange(components.Values))); }
ParsedComponent ParseComponent(string component) { // remove all access modifiers component = component.ReplaceAll("", "private", "protected", "internal", "public"); if (component.Contains("namespace")) { var startID = component.IndexOf("namespace"); var fromNamespaceComponent = component.Substring(startID); var OpeningBracketID = fromNamespaceComponent.IndexOf("{"); var ClosingGracketID = fromNamespaceComponent.FindMatchingBracket(OpeningBracketID); component = component.Substring(OpeningBracketID + startID + 1, ClosingGracketID - OpeningBracketID - 1); } var temp = component .AslineArray() .Where(x => x.Contains("class")) .FirstOrDefault(); var id = temp.IndexOf("class"); var temp2 = temp .Substring(id); var name = temp2 .Split(' ') [1]; var attributesTextRaw = component .AslineArray() .Where(line => line.Contains("[") || line.Contains("]")); var attributesText = attributesTextRaw.Count() > 0 ? attributesTextRaw .Aggregate((a, b) => a + b) .RemoveWhitespace() : null; var attributes = attributesText != null? attributesText.ReplaceAll("", "[", "]") .Split(',') .Select(x => { if (x.Contains(".")) { var parts = x.Split('.'); return(parts[parts.Length - 1]); } return(x); }) : new string[] { DefaultContext }; var isUnique = false; if (attributes.Contains(UniqueAttibute)) { attributes = attributes.Where(x => x != UniqueAttibute); isUnique = true; } var usingsLines = component .AslineArray() .Where(x => x.Contains("using")); var usings = usingsLines.Count() > 0 ? usingsLines.Aggregate((a, b) => a + Format.NewLine() + b) : string.Empty; var hasFields = component .Split(new string[] { "{", "}" }, StringSplitOptions.None)[1] .RemoveWhitespace() != ""; var fields = component .Split(new string[] { "{", "}" }, StringSplitOptions.None)[1] .Split(new string[] { ";" }, StringSplitOptions.None) .ToList(); var result = new ParsedComponent(); result.ComponentName = name; result.Attributes = attributes.ToArray(); result.Contexts = attributes.Where(a => state.Contexts.Contains(a)).ToArray(); result.IsUnique = isUnique; result.HasFields = hasFields; result.Usings = usings; if (fields.Any()) { var r = fields .Select(x => x.Split(' ').Where(y => !(y == string.Empty || y == null || y.Contains(" "))).Skip(1).ToList()).ToList(); r = r.Take(r.Count - 1).ToList(); result.Fields = r.Select(fieldPair => new FieldParsed() { Index = r.IndexOf(fieldPair), Type = fieldPair[0], Name = fieldPair[1] }).ToArray(); } if (settings.ForseReactiveComponents) { result.ForseReactive = true; } return(result); }
void GenerateComponentExtensions(ParsedComponent parsedComponent) { foreach (var context in parsedComponent.Contexts) { string result = MayBakeUsings() ? parsedComponent.Usings : string.Empty; // Header var snippetHeader = File.ReadAllText(settings.CodeSnippets.ComponentHeader); var componentHeader = snippetHeader .Replace(ComponentNameTag, parsedComponent.ComponentName); result += Format.NewLine() + componentHeader; // Get Property var snippet_Get = File.ReadAllText(settings.CodeSnippets.ComponentExtensions_Get_Property); var snippet_Fieldless = File.ReadAllText(settings.CodeSnippets.ComponentExtensions_Fieldless); var snippet = parsedComponent.HasFields ? snippet_Get : snippet_Fieldless; var get_extension = snippet .Replace(ComponentNameTag, parsedComponent.ComponentName) .Replace(ContextNameTag, context); result += Format.NewLine() + get_extension; if (parsedComponent.HasFields) { // Add Method var snippet_Add = File.ReadAllText(settings.CodeSnippets.ComponentExtensions_Add_Method); string add_extension = snippet_Add; add_extension = HandleAddMethod(parsedComponent, add_extension); var clearActionsSequence = parsedComponent.Fields .Select(x => string.Format("{0}.On{1}Change = null;", parsedComponent.ComponentName, x.Name.VariateFirstChar())) .Aggregate((x, y) => x + Format.NewLine(2) + y); var NanoListFieldsInitialization = parsedComponent.Fields.ToList() .Where(field => field.Type.Contains("NanoList")) .Select(y => Format.NewLine() + "c." + (parsedComponent.IsReactive() ? y.Name.VariateFirstChar() : y.Name.FirstCharToUpper()) + ".Initialize(c._InternalOnValueChange, " + y.Index + ");" + Format.NewLine() + "if (c." + y.Name.VariateFirstChar() + ".Count > 0) { c._InternalOnValueChange(" + y.Index + "); }" + Format.NewLine()).ToList(); add_extension = add_extension .Replace(ClearingActionsSequenceTag, parsedComponent.IsReactive() ? clearActionsSequence : "") .Replace(ComponentNameTag, parsedComponent.ComponentName) .Replace(ContextNameTag, context); if (NanoListFieldsInitialization.Count > 0) { var marker = "return this;"; NanoListFieldsInitialization.ForEach(x => add_extension = add_extension.Insert(add_extension.IndexOf(marker), x)); } result += Format.NewLine() + add_extension; } result = GenaratedHeader + result; var prefix = state.Contexts.Count > 1 ? context : string.Empty; SaveGeneration(result, new Tag(TagKeys.Context, context), new Tag(TagKeys.GenerationType, GenerationTypes.AddRemove)); } }
void ExtendComponentFieldTypes(ParsedComponent component) { component.Fields.ToList() .Where(field => field.Type.Contains("List")).ToList().ForEach(x => x.Type = string.Format("NanoList<{0}>", x.Type.Extract('<', '>'))); }