// [Sec 4, ES2008] private void BuildTree(Dictionary <SppfNode, SppfNode> nodes, HashSet <Item> processed, InteriorNode node, Item item) { processed.Add(item); if (item.Production.Rhs.Count == 0) { var i = node.EndPosition; var v = NewOrExistingNode(nodes, new SymbolNode(item.Production.Lhs, i, i)); //if there is no SPPF node v labeled (A, i, i) //create one with child node ϵ v.AddFamily(new Family(new EpsilonNode(i, i))); // basically, SymbolNodes with no children have empty children } else if (item.CurrentPosition == 1) { var prevWord = item.PrevWord; if (prevWord.IsTerminal) { var a = (Terminal)prevWord; var i = node.EndPosition; var v = NewOrExistingNode(nodes, new TerminalNode(a, i - 1, i)); node.AddFamily(new Family(v)); } else { var C = (Nonterminal)prevWord; var j = node.StartPosition; var i = node.EndPosition; var v = NewOrExistingNode(nodes, new SymbolNode(C, j, i)); node.AddFamily(new Family(v)); foreach (var reduction in item.Reductions) { if (reduction.Label != j) { continue; } var q = reduction.Item; if (!processed.Contains(q)) { BuildTree(nodes, processed, v, q); } } } } else if (item.PrevWord.IsTerminal) { var a = (Terminal)item.PrevWord; var j = node.StartPosition; var i = node.EndPosition; var v = NewOrExistingNode(nodes, new TerminalNode(a, i - 1, i)); var w = NewOrExistingNode(nodes, new IntermediateNode(item.Decrement(), j, i - 1)); foreach (var predecessor in item.Predecessors) { if (predecessor.Label != i - 1) { continue; } var pPrime = predecessor.Item; if (!processed.Contains(pPrime)) { BuildTree(nodes, processed, w, pPrime); } } node.AddFamily(new Family(w, v)); } else { var C = (Nonterminal)item.PrevWord; foreach (var reduction in item.Reductions) { var l = reduction.Label; var q = reduction.Item; var j = node.StartPosition; var i = node.EndPosition; var v = NewOrExistingNode(nodes, new SymbolNode(C, l, i)); if (!processed.Contains(q)) { BuildTree(nodes, processed, v, q); } var w = NewOrExistingNode(nodes, new IntermediateNode(item.Decrement(), j, l)); foreach (var predecessor in item.Predecessors) { if (predecessor.Label != l) { continue; } var pPrime = predecessor.Item; if (!processed.Contains(pPrime)) { BuildTree(nodes, processed, w, pPrime); } } node.AddFamily(new Family(w, v)); } } }