/// <summary> /// 计算指定 LR(1) 项集的闭包。 /// </summary> /// <param name="items">要计算闭包的项集。</param> /// <param name="first">非终结符号的 FIRST 集合。</param> private static void LR1Closure(LRItemCollection <T> items, Dictionary <Symbol <T>, HashSet <Terminal <T> > > first) { bool changed = true; while (changed) { changed = false; for (int i = 0; i < items.Count; i++) { LRItem <T> item = items[i]; // 项的定点右边是非终结符。 NonTerminal <T> nextSym = item.SymbolAtIndex as NonTerminal <T>; if (nextSym == null) { continue; } int index = item.Index + 1; Production <T> production = item.Production; HashSet <Terminal <T> > forwards = null; if (index < production.Body.Count) { forwards = new HashSet <Terminal <T> >(); Symbol <T> nNextSym = production.Body[index]; Terminal <T> tSym = nNextSym as Terminal <T>; if (tSym != null) { forwards.Add(tSym); } else { forwards.UnionWith(first[nNextSym]); if (forwards.Contains(Empty)) { // FIRST 中包含 ε,需要被替换为 item 的向前看符号。 forwards.Remove(Empty); forwards.UnionWith(item.Forwards); } } } else { forwards = item.Forwards; } int pCnt = nextSym.Productions.Count; for (int j = 0; j < pCnt; j++) { LRItem <T> newItem = items.AddOrGet(nextSym.Productions[j], 0); if (newItem.AddForwards(forwards) && !changed) { changed = true; } } } } }
/// <summary> /// 对向前看符号进行传播,生成 LALR(1) 项集族。 /// </summary> /// <param name="grammar">语法规则。</param> /// <param name="itemsets">LR(0) 项集族。</param> /// <param name="first">非终结符号的 FIRST 集。</param> private static void SpreadForward(Grammar <T> grammar, List <LRItemset <T> > itemsets, Dictionary <Symbol <T>, HashSet <Terminal <T> > > first) { // LALR 向前看符号的传播规则。 List <Tuple <LRItem <T>, LRItem <T> > > forwardSpread = new List <Tuple <LRItem <T>, LRItem <T> > >(); int cnt = itemsets.Count; for (int i = 0; i < cnt; i++) { LRItemset <T> itemset = itemsets[i]; // 计算向前看符号的传播和自发生。 foreach (LRItem <T> item in itemset.Items) { // 为 item 临时添加传递标志。 item.Forwards.Add(SpreadFlag); // 当前项的集合。 LRItemCollection <T> closure = new LRItemCollection <T>() { item }; LR1Closure(closure, first); foreach (LRItem <T> closureItem in closure) { // 仅对定点右边有符号的项进行处理。 Symbol <T> sym = closureItem.SymbolAtIndex; if (sym == null) { continue; } LRItemCollection <T> gotoTarget = itemsets[itemset.Goto[sym]].Items; LRItem <T> gotoItem = gotoTarget.AddOrGet(closureItem.Production, closureItem.Index + 1); // 自发生成的向前看符号。 gotoItem.AddForwards(closureItem.Forwards); // 传播的向前看符号。 if (gotoItem.Forwards.Contains(SpreadFlag)) { forwardSpread.Add(new Tuple <LRItem <T>, LRItem <T> >(item, gotoItem)); gotoItem.Forwards.Remove(SpreadFlag); } } // 移除 item 的传递标志。 item.Forwards.Remove(SpreadFlag); } } // 为起始符号添加向前看符号 EOF itemsets[0].Items[0].Forwards.Add(EndOfFile); // 需要继续传播向前看符号。 bool continueSpread = true; while (continueSpread) { continueSpread = false; foreach (Tuple <LRItem <T>, LRItem <T> > tuple in forwardSpread) { int oldCnt = tuple.Item2.Forwards.Count; tuple.Item2.Forwards.UnionWith(tuple.Item1.Forwards); if (oldCnt < tuple.Item2.Forwards.Count) { continueSpread = true; } } } // 根据核心项构造完整项集。 for (int i = 0; i < cnt; i++) { LR1Closure(itemsets[i].Items, first); } }