Beispiel #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;
                        }
                    }
                }
            }
        }
Beispiel #2
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);
            }
        }