Пример #1
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);
        }
Пример #2
0
        /// <summary>
        /// 构造 LALR 语法分析表。
        /// </summary>
        /// <param name="grammar">语法分析器使用的语法。</param>
        /// <param name="itemsets">LR 项集族。</param>
        private void BuildLRTable(Grammar <T> grammar, List <LRItemset <T> > itemsets)
        {
            int stateCnt = itemsets.Count;

            this.states = new StateData[stateCnt];
            int gotoCnt = grammar.NonTerminals.Count;

            for (int i = 0; i < stateCnt; i++)
            {
                List <Tuple <LRItem <T>, ParseAction> >[] actions = new List <Tuple <LRItem <T>, ParseAction> > [actionCount];
                for (int j = 0; j < actionCount; j++)
                {
                    actions[j] = new List <Tuple <LRItem <T>, ParseAction> >();
                }
                LRItemset <T> itemset = itemsets[i];
                foreach (LRItem <T> item in itemset.Items)
                {
                    if (item.Index < item.Production.Body.Count)
                    {
                        // 移入动作。
                        Symbol <T>   sym  = item.Production.Body[item.Index];
                        Terminal <T> tSym = sym as Terminal <T>;
                        if (tSym != null)
                        {
                            int targetIndex = itemset.Goto[tSym];
                            actions[tSym.Index + Constants.TokenOffset].Add(
                                new Tuple <LRItem <T>, ParseAction>(item, ParseAction.Shift(targetIndex)));
                        }
                    }
                    else if (item.Production.Head != grammar.AugmentedStart)
                    {
                        // 归约动作。
                        int targetIndex = item.Production.Index;
                        foreach (Terminal <T> sym in item.Forwards)
                        {
                            actions[sym.Index + Constants.TokenOffset].Add(
                                new Tuple <LRItem <T>, ParseAction>(item, ParseAction.Reduce(targetIndex)));
                        }
                    }
                    else if (item.Forwards.Contains(EndOfFile) && actions[Constants.EOFIdx].Count == 0)
                    {
                        // 接受动作。
                        actions[Constants.EOFIdx].Add(new Tuple <LRItem <T>, ParseAction>(item, ParseAction.Accept));
                    }
                }
                // 生成 GOTO 转换。
                int[] gotos = new int[gotoCnt];
                foreach (NonTerminal <T> sym in grammar.NonTerminals)
                {
                    int state;
                    if (!itemset.Goto.TryGetValue(sym, out state))
                    {
                        state = Constants.DeadState;
                    }
                    gotos[sym.Index] = state;
                }
                string[] originRules = new string[itemset.Items.Count];
                for (int j = 0; j < originRules.Length; j++)
                {
                    originRules[j] = itemset.Items[j].ToString();
                }
                this.states[i] = new StateData(ResolveActions(grammar, i, actions), gotos, originRules);
            }
        }
Пример #3
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);
            }
        }