LRNode Closure(LRNode node) { bool isChanged = true; while (isChanged) { isChanged = false; int prevCount = node.Elements.Count; HashSet <LRNodeElement> toAdd = new HashSet <LRNodeElement>(); foreach (var element in node.Elements) { var rule = element.GrammarRule; if (rule.DotPos >= rule.ProductionElements.Count) { continue; } var pe = rule.ProductionElements[rule.DotPos]; var next = rule.DotPos + 1 < rule.ProductionElements.Count ? rule.ProductionElements[rule.DotPos + 1] : new EpsilonProduction(); if (pe is NonTerminalProduction) { foreach (var r in grammarBuilder.NonTerminals[pe.Name].GetAllRules()) { foreach (var terminal in CalculateFirst(next, element.TerminalProduction)) { toAdd.Add(new LRNodeElement(r.Clone(), terminal)); } } } } foreach (var e in toAdd) { node.Elements.Add(e); } if (node.Elements.Count != prevCount) { isChanged = true; } } return(node); }
/// <summary> /// GOTO function from dragonbook /// </summary> /// <param name="I"></param> /// <param name="X"></param> /// <returns></returns> LRNode Goto(LRNode I, IProductionElement X) { LRNode node = new LRNode(); foreach (var e in I.Elements) { var rule = e.GrammarRule; var terminal = e.TerminalProduction; if (rule.DotPos < rule.ProductionElements.Count) { var pe = rule.ProductionElements[rule.DotPos]; //TODO : think about removing first part of condition. if (pe.GetType().Equals(X.GetType()) && X.Name.Equals(pe.Name)) { var newRule = rule.Clone(); newRule.DotPos++; node.Elements.Add(new LRNodeElement(newRule, terminal)); } } } return(Closure(node)); }