예제 #1
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;
                        }
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// 确定指定的 <see cref="System.Object"/> 是否等于当前的 <see cref="LRItemCollection&lt;T&gt;"/>。
        /// </summary>
        /// <param name="obj">与当前的 <see cref="LRItemCollection&lt;T&gt;"/> 进行比较的 object。</param>
        /// <returns>如果指定的 <see cref="System.Object"/> 等于当前的 <see cref="LRItemCollection&lt;T&gt;"/>,
        /// 则为 <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));
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
        /// <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);
        }
예제 #5
0
 /// <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);
 }
예제 #6
0
 /// <summary>
 /// 使用指定的项集合初始化 <see cref="LRItemset&lt;T&gt;"/> 类的新实例。
 /// </summary>
 /// <param name="items">当前项集中包含的项。</param>
 internal LRItemset(LRItemCollection <T> items)
 {
     this.Items = items;
     this.Goto  = new Dictionary <Symbol <T>, int>();
 }
예제 #7
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);
            }
        }