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); }
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); }