/// <summary> /// /// </summary> /// <param name="name"></param> /// <param name="text"></param> /// <remarks> /// When parsing text, it is always assumed as the start that the rule is an /// alternating group of groups, and when a grouping token is encountered the same /// is assumed. The simplify method is called at the end /// </remarks> public void AddRule(string name, string text) { int matchedGroup; Grouping currentAlternation = new Grouping(Alternation.Instance) { ProductionName = name }; Grouping currentGroup = new Grouping(Concatenation.Instance); currentAlternation.Add(currentGroup); foreach (Match match in ruleTokenizer.Matches(text)) { matchedGroup = match.Groups.Cast <System.Text.RegularExpressions.Group>() .Select((g, i) => new { Group = g, Index = i }) .FirstOrDefault(g => g.Group.Success && g.Index > 0).Index; switch (matchedGroup) { case 1: currentGroup.Add(new Referrer(match.Value)); break; case 2: currentGroup.Add(Literal.FromQuoted(match.Value)); break; case 3: switch (match.Value) { case "(": currentAlternation = new Grouping(Alternation.Instance); currentGroup.Add(currentAlternation); currentGroup = new Grouping(Concatenation.Instance); currentAlternation.Add(currentGroup); break; case ")": if (currentAlternation.IsException) { currentGroup = currentAlternation.Parent; currentAlternation = currentGroup.Parent; } currentGroup = currentAlternation.Parent; currentAlternation = currentGroup.Parent; break; case "|": if (currentAlternation.IsException) { currentGroup = currentAlternation.Parent; currentAlternation = currentGroup.Parent; } currentGroup = new Grouping(Concatenation.Instance); currentAlternation.Add(currentGroup); break; case "-": currentAlternation = new Grouping(Alternation.Instance) { IsException = true }; currentGroup.Add(currentAlternation); currentGroup = new Grouping(Concatenation.Instance); currentAlternation.Add(currentGroup); break; } break; case 4: currentGroup.Last().Quantifier = match.Value; break; case 6: throw new Exception(String.Format("Invalid token \"{0}\" at {1}", match.Value, match.Index)); } } Add(Simplify(currentAlternation)); }