private HashSet <uint> FindFirst(Grammar grammar, uint symbolIndex) { var set = _terminalSets[symbolIndex]; if (set == null) { set = _terminalSets[symbolIndex] = new HashSet <uint>(); foreach (var rule in grammar.Where(x => x.Left.Id == symbolIndex)) { if (rule.IsEpsilon) { set.Add(0); } else { foreach (var symbol in rule.Right) { if (symbol.Id != symbolIndex) { var rightSet = FindFirst(grammar, symbol.Id); set.UnionWith(rightSet); if (!rightSet.Contains(0)) { break; } } } } } } return(set); }
public State Closure(Grammar grammar) { var queue = new Queue <LR1Item>(this); while (queue.Count > 0) { var item = queue.Dequeue(); var currentRule = item.Production; var pos = item.Position; if (pos >= currentRule.Right.Length) { continue; } var B = currentRule.Right[pos]; if (B.IsTerminal) { continue; } //else if (grammar.TerminalSets.HasEmpty(B.Id)) //{ // var newItem = new LR1Item(item.Production, pos + 1, item.Lookahead); // if (Add(newItem)) // queue.Enqueue(newItem); //} var firstSet = currentRule.FindFirst(pos + 1, item.Lookahead); foreach (var production in grammar.Where(x => x.Left == B)) { foreach (var term in firstSet) { var newItem = new LR1Item(production, 0, grammar.Symbols[(int)term]); if (Add(newItem)) { queue.Enqueue(newItem); } } } } return(this); }