public List <TableRule> CreateTable() { var tableRules = new List <TableRule>(); var keyQueue = new Queue <RuleItems>(); var queueBlackList = new HashSet <RuleItems>(); { var itemId = new RuleItemId(0, -1); var tableRule = new TableRule(_rules[itemId.RuleIndex].NonTerminal, _valueKeys); AddNext(tableRule, itemId); AddToQueue(tableRule); tableRules.Add(tableRule); } while (keyQueue.Count > 0) { var items = keyQueue.Dequeue(); queueBlackList.Add(items); var key = string.Join("", items.Select(x => x.ToString())); if (tableRules.Any(x => x.Key == key)) { continue; } var tableRule = new TableRule(key, _valueKeys); foreach (var item in items) { if (_rules[item.Id.RuleIndex].Items.Count <= item.Id.ItemIndex + 1) { var nextItems = FindNextRecursive(_rules[item.Id.RuleIndex].NonTerminal); foreach (var nextItem in nextItems) { AddFold(tableRule, new RuleItemId(nextItem.Id.RuleIndex, nextItem.Id.ItemIndex - 1), new RuleItem("R" + (item.Id.RuleIndex + 1))); } } else if (_rules[item.Id.RuleIndex].Items[item.Id.ItemIndex + 1].Value == Constants.EndSymbol) { tableRule.Values[Constants.EndSymbol].Add(new RuleItem("R" + (item.Id.RuleIndex + 1))); } else { AddNext(tableRule, item.Id); } } tableRules.Add(tableRule); AddToQueue(tableRule); } return(tableRules); void AddNext(TableRule tableRule, RuleItemId itemId) { var next = _rules[itemId.RuleIndex].Items[itemId.ItemIndex + 1]; tableRule.QuickAdd(next); foreach (var rule in _rules.Where(x => x.NonTerminal == next.Value)) { if (next.Value != rule.Items[0].Value && !rule.Items[0].IsTerminal) { AddNext(tableRule, new RuleItemId(rule.Items[0].Id.RuleIndex, rule.Items[0].Id.ItemIndex - 1)); } else if (rule.Items[0].Value == Constants.EmptySymbol) { var nextItems = FindNextRecursive(rule.NonTerminal); foreach (var nItem in nextItems) { if (nItem.IsTerminal) { tableRule.Values[nItem.Value].Add(new RuleItem("R" + (rule.Items[0].Id.RuleIndex + 1))); } else { AddFold(tableRule, new RuleItemId(nItem.Id.RuleIndex, nItem.Id.ItemIndex - 1), new RuleItem("R" + (rule.Items[0].Id.RuleIndex + 1))); } } } else { tableRule.QuickAdd(rule.Items[0]); } } } void AddFold(TableRule tableRule, RuleItemId itemId, RuleItem ruleItem) { var next = _rules[itemId.RuleIndex].Items[itemId.ItemIndex + 1]; tableRule.QuickFold(next, ruleItem); foreach (var rule in _rules.Where(x => x.NonTerminal == next.Value)) { if (next.Value != rule.Items[0].Value && !rule.Items[0].IsTerminal) { AddFold(tableRule, new RuleItemId(rule.Items[0].Id.RuleIndex, rule.Items[0].Id.ItemIndex - 1), ruleItem); } else if (rule.Items[0].Value == Constants.EmptySymbol) { var nextItems = FindNextRecursive(rule.NonTerminal); foreach (var nItem in nextItems) { if (nItem.IsTerminal) { tableRule.Values[nItem.Value].Add(ruleItem); } else { AddFold(tableRule, new RuleItemId(nItem.Id.RuleIndex, nItem.Id.ItemIndex - 1), ruleItem); } } } else { tableRule.QuickFold(rule.Items[0], ruleItem); } } } void AddToQueue(TableRule tableRule) { foreach (var item in tableRule.Values .Where(x => x.Value.Count > 0)) { var value = item.Value; if (!queueBlackList.Contains(value) && !(value[0].Value.StartsWith("R") && char.IsDigit(value[0].Value[1]))) { keyQueue.Enqueue(value); } } } }