/// <summary> /// 计算文法的所有单个的结点的FIRST /// </summary> /// <param name="grammar"></param> /// <param name="nullableDict"></param> /// <returns></returns> private static void GetFirstCollection4Node( this RegulationList grammar, out FIRSTCollection firstCollection, Dictionary <TreeNodeType, bool> nullableDict = null) { // 初始化FIRST firstCollection = new FIRSTCollection(); // 初始化非叶结点的FIRST foreach (var item in grammar.GetAllTreeNodeNonLeaveTypes()) { if (nullableDict[item]) { firstCollection.TryInsert(new FIRST(item, TreeNodeType.NullNode)); } else { firstCollection.TryInsert(new FIRST(item)); } } // 初始化叶结点的FIRST(叶结点的FIRST实际上已经完工) foreach (var item in grammar.GetAllTreeNodeLeaveTypes()) { firstCollection.TryInsert(new FIRST(item, item)); } bool changed = false; do { changed = false; foreach (var regulation in grammar) { FIRST first = FindFirst(firstCollection, regulation.Left); int rightPartCount = regulation.RightPart.Count(); for (int checkCount = 0; checkCount < rightPartCount; checkCount++) { // 如果前面checkCount个结点都可为null, // 就说明RightPart[checkCount]的FIRST是此regulation.Left的FIRST的一部分。 if (Nullable(regulation.RightPart, 0, checkCount, nullableDict)) { FIRST refFirst = FindFirst(firstCollection, regulation.RightNode(checkCount)); if (refFirst == null) { throw new Exception("algorithm error!"); } if (refFirst != first) { foreach (var value in refFirst.Values) { if (value != TreeNodeType.NullNode) { changed = first.TryInsert(value) || changed; } } } } } } } while (changed); }
/// <summary> /// 用LR(0)分析法计算分析表 /// </summary> /// <param name="grammar"></param> /// <returns></returns> public static void GetLR0ParsingMap(this RegulationList grammar, out LRParsingMap map, out LR0StateCollection stateCollection, out LR0EdgeCollection edgeCollection, TextWriter writer) { // 给文法添加一个辅助的开始产生式 S' -> S $ // 如何添加一个外来的结点类型?用Enum是无法做到的。 var decoratedS = new TreeNodeType("__S2", "S'", "<S'>"); var decoratedEnd = TreeNodeType.endOfTokenListNode; var decoratedRegulation = new Regulation( decoratedS, grammar[0].Left, decoratedEnd); var decoratedGrammar = new RegulationList(decoratedRegulation); decoratedGrammar.AddRange(grammar); // 初始化T为{ Closure(S' -> S $) } var firstItem = new LR0Item(decoratedGrammar[0], 0); var firstState = new LR0State(firstItem); firstState = decoratedGrammar.Closure(firstState); stateCollection = new LR0StateCollection(firstState); edgeCollection = new LR0EdgeCollection(stateCollection); var queue = new Queue <LR0State>(); queue.Enqueue(firstState); int lastOutputLength = 0; int stateListCount = 1; int queueCount = 1; while (queue.Count > 0) { LR0State fromState = queue.Dequeue(); queueCount--; int itemIndex = 0; int itemCount = fromState.Count(); foreach (var item in fromState) { { TextWriter currentWriter = Console.Out; if (Console.Out != writer) { Console.SetOut(writer); } for (int i = 0; i < lastOutputLength; i++) { Console.Write('\u0008'); } string output = string.Format("Calculating LR(0) State List: {0} <-- {1}, working on {2}/{3} ...", stateListCount, queueCount, 1 + itemIndex++, itemCount); Console.Write(output); lastOutputLength = output.Length; Console.SetOut(currentWriter); } TreeNodeType x = item.GetNodeNext2Dot(); if (x == null || x == decoratedEnd) { continue; } LR0State toState = decoratedGrammar.Goto(fromState, x); if (stateCollection.TryInsert(toState)) { queue.Enqueue(toState); stateListCount++; queueCount++; var edge = new LR0Edge(fromState, x, toState); edgeCollection.TryInsert(edge); } else { int index = stateCollection.IndexOf(toState); toState = stateCollection[index]; var edge = new LR0Edge(fromState, x, toState); edgeCollection.TryInsert(edge); } } } { TextWriter currentWriter = Console.Out; if (Console.Out != writer) { Console.SetOut(writer); } Console.WriteLine(); Console.SetOut(currentWriter); } map = new LRParsingMap(); foreach (var edge in edgeCollection) { int stateId = edge.From.ParsingMapIndex + 1; //stateCollection.IndexOf(edge.From) + 1; int nextStateId = edge.To.ParsingMapIndex + 1; //stateCollection.IndexOf(edge.To) + 1; if (edge.X.IsLeave) { map.SetAction(stateId, edge.X, new LR1ShiftInAction(nextStateId)); } else { map.SetAction(stateId, edge.X, new LR1GotoAction(nextStateId)); } } var endItem = new LR0Item(decoratedRegulation, 1); foreach (var state in stateCollection) { if (state.Contains(endItem)) { int stateId = state.ParsingMapIndex + 1;// stateCollection.IndexOf(state) + 1; map.SetAction(stateId, decoratedEnd, new LR1AceptAction()); } foreach (var item in state) { if (item.GetNodeNext2Dot() == null) { List <TreeNodeType> allTreeNodeTypes = decoratedGrammar.GetAllTreeNodeLeaveTypes(); foreach (var treeNodeType in allTreeNodeTypes) { int stateId = state.ParsingMapIndex + 1;//stateCollection.IndexOf(state) + 1 map.SetAction(stateId, treeNodeType, new LR1ReducitonAction(decoratedGrammar.IndexOf(item.Regulation))); } } } } }