/// <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> /// 构造 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); } }
/// <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); } }