예제 #1
0
        public static string Expand(this string source, params string[] args)
        {
            var    output       = source;
            var    tokens       = new List <string>();
            var    pattern      = new Regex(_patternStyle.TokenMatchPattern, RegexOptions.IgnoreCase);
            var    calls        = new Stack <string>();
            string callingToken = null;

            while (pattern.IsMatch(output))
            {
                foreach (Match match in pattern.Matches(output))
                {
                    var token      = _patternStyle.TokenReplaceFilter(match.Value);
                    var tokenIndex = 0;
                    if (!tokens.Contains(token))
                    {
                        tokens.Add(token);
                        tokenIndex = tokens.Count - 1;
                    }
                    else
                    {
                        tokenIndex = tokens.IndexOf(token);
                    }

                    output = Regex.Replace(output, _patternStyle.OutputFilter(match.Value), "{" + tokenIndex + "}");
                }
            }

            var newArgs = new List <string>();

            foreach (var arg in args)
            {
                var newArg       = arg;
                var tokenPattern = new Regex(_patternStyle.TokenFilter(string.Join("|", tokens)));
                while (tokenPattern.IsMatch(newArg))
                {
                    foreach (Match match in tokenPattern.Matches(newArg))
                    {
                        var token = _patternStyle.TokenReplaceFilter(match.Value);
                        if (calls.Contains(string.Format("{0}:{1}", callingToken, token)))
                        {
                            throw new CircularReferenceException(string.Format("Circular Reference Detected for token '{0}'.", callingToken));
                        }

                        calls.Push(string.Format("{0}:{1}", callingToken, token));
                        callingToken = token;
                        newArg       = Regex.Replace(newArg, _patternStyle.OutputFilter(match.Value), args[tokens.IndexOf(token)]);
                    }
                }

                newArgs.Add(newArg);
            }

            return(string.Format(output, newArgs.ToArray()));
        }
예제 #2
0
        private static string Explode(this string source, Regex pattern, PatternStyle patternStyle, Func <string, string> expansionFactory, TreeNode <string> parent)
        {
            var output = source;

            while (output.HasChildren(pattern))
            {
                foreach (Match match in pattern.Matches(source))
                {
                    var child = match.Value;
                    var token = patternStyle.TokenReplaceFilter(match.Value);

                    var thisNode = parent.Children.Add(token);

                    // if we have already encountered this token in this call tree, we have a circular reference
                    if (thisNode.CallTree.Contains(token))
                    {
                        throw new CircularReferenceException(string.Format("Circular Reference Detected for token '{0}'. Call Tree: {1}->{2}",
                                                                           token,
                                                                           string.Join("->", thisNode.CallTree.ToArray().Reverse()),
                                                                           token));
                    }

                    // expand this match
                    var expandedValue = expansionFactory(token);

                    // Replace the match with the expanded value
                    child = Regex.Replace(child, patternStyle.OutputFilter(match.Value), expandedValue);

                    // Recursively expand the child until we no longer encounter nested tokens (or hit a circular reference)
                    child = child.Explode(pattern, patternStyle, expansionFactory, thisNode);

                    // finally, replace the match in the output with the fully-expanded value
                    output = Regex.Replace(output, patternStyle.OutputFilter(match.Value), child);
                }
            }

            return(output);
        }
예제 #3
0
        private static string Explode(this string source, Regex pattern, PatternStyle patternStyle, Func<string, string> expansionFactory, TreeNode<string> parent)
        {
            var output = source;
            while (output.HasChildren(pattern))
            {
                foreach (Match match in pattern.Matches(source))
                {
                    var child = match.Value;
                    var token = patternStyle.TokenReplaceFilter(match.Value);

                    var thisNode = parent.Children.Add(token);

                    // if we have already encountered this token in this call tree, we have a circular reference
                    if (thisNode.CallTree.Contains(token))
                        throw new CircularReferenceException(string.Format("Circular Reference Detected for token '{0}'. Call Tree: {1}->{2}",
                                                                           token,
                                                                           string.Join("->", thisNode.CallTree.ToArray().Reverse()), token));

                    // expand this match
                    var expandedValue = expansionFactory(token);

                    // Replace the match with the expanded value
                    child = Regex.Replace(child, patternStyle.OutputFilter(match.Value), expandedValue);

                    // Recursively expand the child until we no longer encounter nested tokens (or hit a circular reference)
                    child = child.Explode(pattern, patternStyle, expansionFactory, thisNode);

                    // finally, replace the match in the output with the fully-expanded value
                    output = Regex.Replace(output, patternStyle.OutputFilter(match.Value), child);
                }
            }
            return output;
        }