private void AddZeroRule()
        {
            string    newHead  = beginToken + "'";
            TransRule zeroRule = new TransRule(new TransToken(newHead),
                                               new List <TransToken> {
                new TransToken(beginToken)
            },
                                               (TransRule thisPlaceholder) =>
                                               { thisPlaceholder.head.attrVal = thisPlaceholder.body[0].attrVal; });

            rules.Insert(0, zeroRule);
            beginToken = newHead;
        }
        private HashSet <TransToken> GetNextTokenFirsts(TransRule rule, int nextTokenIndex)
        {
            HashSet <TransToken> result = new HashSet <TransToken> {
            };
            bool containsEpsilon        = true;

            for (int i = nextTokenIndex; i < rule.body.Count; ++i)
            {
                TransToken token = rule.body[i];
                containsEpsilon = false;

                if (terms.Contains(token))
                {
                    result.Add(token);
                    break;
                }

                foreach (TransToken first in firstSets[token])
                {
                    if (first.Equals(new TransToken("")))
                    {
                        containsEpsilon = true;
                    }

                    result.Add(first);
                }

                containsEpsilon |= firstSets[token].Count == 0;

                if (!containsEpsilon)
                {
                    break;
                }
            }

            if (containsEpsilon)
            {
                result.Add(new TransToken(""));
            }

            return(result);
        }
            private Action CreateReduceCallback(int ruleIndex)
            {
                return(() => {
                    TransRule rule = parent.rules[ruleIndex];

                    for (int i = rule.body.Count; i > 0; --i)
                    {
                        stateStack.Pop();
                    }
                    for (int i = rule.body.Count - 1; i >= 0; --i)
                    {
                        rule.body[i] = tokenStack.Pop();
                    }

                    rule.ApplyRule();
                    tokenStack.Push(rule.head);

                    stateStack.Push(GetStateFromGoto(stateStack.Peek(), tokenStack.Peek()));
                });
            }
            private TItemState Goto(TItemState itemState, TransToken nextTerm)
            {
                HashSet <TItem> resultingSet = new HashSet <TItem> {
                };

                foreach (TItem item in itemState.stateItems)
                {
                    TransRule rule = parent.rules[item.ruleNum];
                    if (rule.body.Count == item.dotPos)
                    {
                        continue;
                    }

                    if (rule.body[item.dotPos].token == nextTerm.token)
                    {
                        resultingSet.Add(new TItem(item.ruleNum, item.dotPos + 1));
                    }
                }

                return(new TItemState(resultingSet));
            }
        // If rule contains body other than one empty symbol, create firsts set for it
        private bool ComputeBodyFirstSets(Dictionary <TransToken, HashSet <TransToken> > firstSets, TransRule rule)
        {
            bool notDone         = false;
            bool containsEpsilon = true;

            foreach (TransToken token in rule.body)
            {
                containsEpsilon = false;

                if (terms.Contains(token))
                {
                    notDone |= firstSets[rule.head].Add(token);
                    break;
                }

                foreach (TransToken element in firstSets[token])
                {
                    if (element.Equals(new TransToken("")))
                    {
                        containsEpsilon = true;
                    }

                    notDone |= firstSets[rule.head].Add(element);
                }

                if (!containsEpsilon)
                {
                    break;
                }
            }

            if (containsEpsilon)
            {
                notDone |= firstSets[rule.head].Add(new TransToken(""));
            }

            return(notDone);
        }