/// <summary>
 /// 如果指定的 LR 项在当前集合中不存在,则添加到当前集合中。
 /// </summary>
 /// <param name="item">要添加的 LR 项。</param>
 public void Add(LRItem <T> item)
 {
     LRItem <T>[] items = GetItems(item.Production);
     if (items[item.Index] == null)
     {
         items[item.Index] = item;
         base.Items.Add(item);
     }
 }
Esempio n. 2
0
        /// <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;
                        }
                    }
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// 确定指定的 <see cref="System.Object"/> 是否等于当前的 <see cref="LRItem&lt;T&gt;"/>。
        /// </summary>
        /// <param name="obj">与当前的 <see cref="LRItem&lt;T&gt;"/> 进行比较的 object。</param>
        /// <returns>如果指定的 <see cref="System.Object"/> 等于当前的 <see cref="LRItem&lt;T&gt;"/>,
        /// 则为 <c>true</c>;否则为 <c>false</c>。</returns>
        public override bool Equals(object obj)
        {
            LRItem <T> item = obj as LRItem <T>;

            if (item == null)
            {
                return(false);
            }
            return(this.Equals(item));
        }
 /// <summary>
 /// 如果指定的 LR 项在当前集合中不存在,则添加到当前集合中。
 /// </summary>
 /// <param name="production">LR 项对应的产生式。</param>
 /// <param name="index">LR 项的定点。</param>
 public void Add(Production <T> production, int index)
 {
     LRItem <T>[] items = GetItems(production);
     if (items[index] == null)
     {
         LRItem <T> item = new LRItem <T>(production, index);
         items[index] = item;
         base.Items.Add(item);
     }
 }
 /// <summary>
 /// 返回指定产生式对应的所有 LR 项。
 /// </summary>
 /// <param name="production">要获取 LR 项的产生式。</param>
 /// <return>指定产生式对应的所有 LR 项。</return>
 private LRItem <T>[] GetItems(Production <T> production)
 {
     LRItem <T>[] items;
     if (!this.itemDict.TryGetValue(production, out items))
     {
         items = new LRItem <T> [production.Body.Count + 1];
         this.itemDict.Add(production, items);
     }
     return(items);
 }
 /// <summary>
 /// 如果指定的 LR 项在当前集合中存在,则返回当前集合中的实际项;
 /// 否则添加到当前集合中。
 /// </summary>
 /// <param name="production">LR 项对应的产生式。</param>
 /// <param name="index">LR 项的定点。</param>
 /// <return>当前集合中的实际项。</return>
 public LRItem <T> AddOrGet(Production <T> production, int index)
 {
     LRItem <T>[] items = GetItems(production);
     if (items[index] == null)
     {
         LRItem <T> item = new LRItem <T>(production, index);
         items[index] = item;
         base.Items.Add(item);
     }
     return(items[index]);
 }
Esempio n. 7
0
 /// <summary>
 /// 指示当前对象是否等于同一类型的另一个对象。
 /// </summary>
 /// <param name="other">与此对象进行比较的对象。</param>
 /// <returns>如果当前对象等于 <paramref name="other"/> 参数,则为 <c>true</c>;
 /// 否则为 <c>false</c>。</returns>
 public bool Equals(LRItem <T> other)
 {
     if (other == null)
     {
         return(false);
     }
     if (object.ReferenceEquals(other, this))
     {
         return(true);
     }
     if (production != other.production)
     {
         return(false);
     }
     return(index == other.index);
 }
Esempio n. 8
0
        /// <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);
            }
        }