/// <summary> /// Updates regexes in collection from the source where the key of the source /// is present in the regex and between braces. /// </summary> /// <returns></returns> private TokenType CompileToken(TokenType token, DefinitionCollection replacementSource, IEnumerable <string> dependencies) { string regex = token.Regex; foreach (string replacementKey in dependencies) { regex = regex.Replace(string.Format("{{{0}}}", replacementKey), string.Format("(?:{0})", replacementSource[replacementKey].Regex)); } return(new TokenType(token.Name, regex, token.IsIgnored)); }
public DefinitionsRegex(DefinitionCollection defs, RegexOptions regexOptions) { Tokenizer = new Regex( string.Join("|", defs .Select(d => string.Format("(?<{0}>{1})", d.Name, d.Regex))), regexOptions); GroupNames = Tokenizer.GetGroupNames().Select((g, i) => new { Name = g, Index = i }) .Where(g => !Regex.Match(g.Name, @"^\d+$").Success) .ToDictionary(g => g.Index, g => g.Name); }
static public DefinitionCollection Parse(string text) { DefinitionCollection col = new DefinitionCollection(); text = Common.StripComments(text); foreach (Match match in definitionRegex.Matches(text)) { TokenType def = TokenType.Parse(match.Groups[1].Value); TokenType existingDef = col.FirstOrDefault(d => d.Name == def.Name); if (existingDef == null) { col.Add(def); } else { existingDef.Regex += "|" + def.Regex; } } return(col); }
/// <summary> /// Runs CompileToken on all regexes, causing all instances {variblename} to be replaced /// if a matching variable is found. /// </summary> /// <param name="replacementSource"> /// Definition collection that has replacement values /// If replacementSource is null, then we use the values already added to compiled /// to update future values. /// </param> /// <returns></returns> public DefinitionCollection Compile(RegexOptions regexOptions, DefinitionCollection replacementSource = null) { DefinitionCollection compiled = new DefinitionCollection(); // self replacement, sort by dependencies if (replacementSource == null) { // add to dependencies all regexes that have {a\w} where a\w exists in this. // those without dependencies will be added as empty items. Dictionary <TokenType, List <string> > dependencies = this.ToDictionary(t => t, t => findReferencesRegex.Matches(t.Regex).OfType <Match>() .Select(m => m.Groups[1].Value) .Where(k => this.Exists(t2 => t2.Name == k)).ToList()); Dictionary <TokenType, List <string> > resolvedDependencies = new Dictionary <TokenType, List <string> >(); /* * ResolvedDependencies are added in order of which they can be replaced. * If nothing has been resolved but some still remain then there is a recursive relationship */ int startingCount; do { startingCount = dependencies.Count; IEnumerable <TokenType> depedencyKeys = dependencies.Keys.ToList(); foreach (TokenType t in depedencyKeys) { // if no instances exists where a dependency does not exist //if (!dependencies[t].Exists( // d => !replacementSource.Exists(r => r.Name == d))) if (!dependencies[t].Exists( d => resolvedDependencies.Keys.FirstOrDefault(r => r.Name == d) == null)) { resolvedDependencies.Add(t, dependencies[t]); dependencies.Remove(t); } } } while (dependencies.Count > 0 && dependencies.Count != startingCount); if (dependencies.Count > 0) { throw new Exception("Recursive dependency error"); } foreach (var dependencyInfo in resolvedDependencies) { compiled.Add(CompileToken(dependencyInfo.Key, compiled, dependencyInfo.Value)); } } else { foreach (TokenType token in this) { IEnumerable <string> dependencies = findReferencesRegex.Matches(token.Regex).OfType <Match>() .Select(m => m.Groups[1].Value) .Where(k => replacementSource.Exists(t2 => t2.Name == k)); compiled.Add(CompileToken(token, replacementSource, dependencies)); } compiled = compiled.Compile(regexOptions); } compiled.RegexInfo = new DefinitionsRegex(compiled, regexOptions); return(compiled); }