Пример #1
0
        public bool Add(Lr1Item <T> item)
        {
            // See if there already exists an item with the same core
            var oldItem = Items.FirstOrDefault(f => f.ProductionRule == item.ProductionRule && f.DotLocation == item.DotLocation);

            if (oldItem != null)
            {
                // There might be lookaheads that needs adding
                bool addedLookahead = false;
                foreach (var lookahead in item.Lookaheads)
                {
                    addedLookahead |= oldItem.Lookaheads.Add(lookahead);
                }
                return(addedLookahead);
            }
            // There's no old item. Add the item and return true to indicate that we've added stuff
            Items.Add(item);
            return(true);
        }
Пример #2
0
        private Lr1ItemSet <T> Closure(IEnumerable <Lr1Item <T> > items, TerminalSet <T> first, ISet <NonTerminal <T> > nullable)
        {
            // The items themselves are always in their own closure set
            Lr1ItemSet <T> closure = new Lr1ItemSet <T>();

            foreach (Lr1Item <T> lr1Item in items)
            {
                closure.Add(lr1Item);
            }

            // This needs to be a normal for loop since we add to the underlying collection
            // as we go along. This avoids investigating the same rule twice
            for (int currentItem = 0; currentItem < closure.Count(); ++currentItem)
            {
                Lr1Item <T> item             = closure[currentItem];
                ISymbol <T> symbolRightOfDot = item.SymbolRightOfDot;

                if (symbolRightOfDot != null)
                {
                    // Generate the lookahead items
                    HashSet <Terminal <T> > lookaheads = new HashSet <Terminal <T> >();
                    bool nonNullableFound = false;

                    for (int i = item.DotLocation + 1; i < item.ProductionRule.Symbols.Length; ++i)
                    {
                        ISymbol <T> symbol = item.ProductionRule.Symbols[i];

                        // If symbol is terminal, just add it
                        if (symbol is Terminal <T> )
                        {
                            lookaheads.Add((Terminal <T>)symbol);

                            // Terminals are not nullable, break out of loop
                            nonNullableFound = true;

                            break;
                        }

                        foreach (Terminal <T> terminal in first[(NonTerminal <T>)symbol])
                        {
                            lookaheads.Add(terminal);
                        }

                        if (!nullable.Contains(symbol))
                        {
                            nonNullableFound = true;

                            break;
                        }
                    }

                    if (!nonNullableFound)
                    {
                        // Add each of the lookahead symbols of the generating rule to the new lookahead set
                        foreach (Terminal <T> lookahead in item.Lookaheads)
                        {
                            lookaheads.Add(lookahead);
                        }
                    }

                    // Create new Lr1 items from all rules where the resulting symbol of the production rule
                    // matches the symbol that was to the right of the dot.
                    foreach (Lr1Item <T> lr1Item in from f in grammar.ProductionRules
                             where f.ResultSymbol == symbolRightOfDot
                             select new Lr1Item <T>(f, 0, lookaheads))
                    {
                        closure.Add(lr1Item);
                    }
                }
            }

            return(closure);
        }