/// <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> /// 确定指定的 <see cref="System.Object"/> 是否等于当前的 <see cref="LRItemCollection<T>"/>。 /// </summary> /// <param name="obj">与当前的 <see cref="LRItemCollection<T>"/> 进行比较的 object。</param> /// <returns>如果指定的 <see cref="System.Object"/> 等于当前的 <see cref="LRItemCollection<T>"/>, /// 则为 <c>true</c>;否则为 <c>false</c>。</returns> public override bool Equals(object obj) { LRItemCollection <T> col = obj as LRItemCollection <T>; if (col == null) { return(false); } return(this.Equals(col)); }
/// <summary> /// 构建 LR(0) 项集族。 /// </summary> /// <param name="grammar">语法规则。</param> private static List <LRItemset <T> > BuildLR0Itemsets(Grammar <T> grammar) { // LR(0) 项集族(现在只包含核心项)。 List <LRItemset <T> > itemsets = new List <LRItemset <T> >(); // LR(0) 项集的索引字典。 Dictionary <LRItemCollection <T>, int> itemsIndexMap = new Dictionary <LRItemCollection <T>, int>(); // 从增广文法的起始符号的产生式开始遍历。 itemsets.Add(new LRItemset <T>()); // 添加初始项集。 itemsets[0].Items.Add(grammar.AugmentedStart.Productions[0], 0); itemsIndexMap.Add(itemsets[0].Items, 0); // 项集的临时 GOTO 函数。 Dictionary <Symbol <T>, LRItemCollection <T> > tempGoto = new Dictionary <Symbol <T>, LRItemCollection <T> >(); for (int i = 0; i < itemsets.Count; i++) { LRItemset <T> itemset = itemsets[i]; // 在计算 GOTO 之前计算闭包。 LRItemCollection <T> closure = LR0Closure(itemset.Items); tempGoto.Clear(); foreach (LRItem <T> tmpItem in closure) { // 仅对定点右边有符号的项进行处理。 Symbol <T> sym = tmpItem.SymbolAtIndex; if (sym == null) { continue; } LRItemCollection <T> collection = null; if (!tempGoto.TryGetValue(sym, out collection)) { collection = new LRItemCollection <T>(); tempGoto.Add(sym, collection); } collection.Add(tmpItem.Production, tmpItem.Index + 1); } // 设置项集族的 GOTO 函数。 foreach (KeyValuePair <Symbol <T>, LRItemCollection <T> > pair in tempGoto) { // 用于识别项的集合。 LRItemCollection <T> items = pair.Value; int index; if (!itemsIndexMap.TryGetValue(items, out index)) { index = itemsets.Count; itemsets.Add(new LRItemset <T>(pair.Value)); itemsIndexMap.Add(items, index); } itemset.Goto.Add(pair.Key, index); } } return(itemsets); }
/// <summary> /// 计算指定 LR(0) 项集的闭包。 /// </summary> /// <param name="items">要计算闭包的项集。</param> /// <returns>计算得到的闭包。</returns> private static LRItemCollection <T> LR0Closure(IEnumerable <LRItem <T> > items) { LRItemCollection <T> list = new LRItemCollection <T>(items); for (int i = 0; i < list.Count; i++) { NonTerminal <T> nextSym = list[i].SymbolAtIndex as NonTerminal <T>; if (nextSym == null) { continue; } int cnt = nextSym.Productions.Count; for (int j = 0; j < cnt; j++) { list.Add(nextSym.Productions[j], 0); } } return(list); }
/// <summary> /// 指示当前对象是否等于同一类型的另一个对象。 /// </summary> /// <param name="other">与此对象进行比较的对象。</param> /// <returns>如果当前对象等于 <c>true</c> 参数,则为 <c>true</c>; /// 否则为 <c>false</c>。</returns> public bool Equals(LRItemCollection <T> other) { if (other == null) { return(false); } if (this.Count != other.Count) { return(false); } if (this.itemDict.Count != other.itemDict.Count) { return(false); } foreach (KeyValuePair <Production <T>, LRItem <T>[]> pair in this.itemDict) { LRItem <T>[] otherItems; if (!other.itemDict.TryGetValue(pair.Key, out otherItems)) { return(false); } int cnt = otherItems.Length; if (cnt != pair.Value.Length) { return(false); } for (int i = 0; i < cnt; i++) { if (otherItems[i] != pair.Value[i]) { return(false); } } } return(true); }
/// <summary> /// 使用指定的项集合初始化 <see cref="LRItemset<T>"/> 类的新实例。 /// </summary> /// <param name="items">当前项集中包含的项。</param> internal LRItemset(LRItemCollection <T> items) { this.Items = items; this.Goto = new Dictionary <Symbol <T>, int>(); }
/// <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); } }