Esempio n. 1
0
        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);
                    }
                }
            }
        }