Beispiel #1
0
 /// <summary>
 /// 从一个LR(1)状态跳转到另一个LR(1)状态
 /// </summary>
 /// <param name="from"></param>
 /// <param name="x"></param>
 /// <param name="to"></param>
 public LR1Edge(SmallerLR1State from, TreeNodeType x, SmallerLR1State to)
     : base(GetUniqueString)
 {
     this.From = from;
     this.X    = x;
     this.To   = to;
 }
Beispiel #2
0
 /// <summary>
 /// 从一个LR(0)状态跳转到另一个LR(0)状态
 /// </summary>
 /// <param name="from"></param>
 /// <param name="x"></param>
 /// <param name="to"></param>
 public LR0Edge(LR0State from, TreeNodeType x, LR0State to)
     : base(GetUniqueString)
 {
     this.From = from;
     this.X    = x;
     this.To   = to;
 }
Beispiel #3
0
        /// <summary>
        /// LR(0)的Closure操作。
        /// 补全一个状态。
        /// </summary>
        /// <param name="list"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        static LR0State Closure(this RegulationList list, LR0State state)
        {
            Queue <LR0Item> queue = new Queue <LR0Item>();

            foreach (var item in state)
            {
                queue.Enqueue(item);
            }
            while (queue.Count > 0)
            {
                LR0Item      item = queue.Dequeue();
                TreeNodeType node = item.GetNodeNext2Dot();
                if (node == null)
                {
                    continue;
                }

                foreach (var regulation in list)
                {
                    if (regulation.Left == node)
                    {
                        var newItem = new LR0Item(regulation, 0);
                        if (state.TryInsert(newItem))
                        {
                            queue.Enqueue(newItem);
                        }
                    }
                }
            }

            return(state);
        }
Beispiel #4
0
        public LR1Item this[int index]
        {
            get
            {
                if (index < 0)
                {
                    throw new ArgumentOutOfRangeException();
                }

                int current = 0;
                for (int i = 0; i < this.regulationDotList.Count; i++)
                {
                    if (index <= current + this.regulationDotList.Count)
                    {
                        TreeNodeType node = this.lookAheadCollectionList[i][index - current];
                        LR0Item      item = this.regulationDotList[i];
                        return(new LR1Item(item.Regulation, item.DotPosition, node));
                    }
                    else
                    {
                        current += this.regulationDotList.Count;
                    }
                }

                throw new ArgumentOutOfRangeException();
            }
        }
        private static string GetUniqueString(HashCache cache)
        {
            TreeNodeType obj = cache as TreeNodeType;

            return(obj.Dump());
            //return string.Format("({0})[{1}][{2}]", obj.Type, obj.Content, obj.Nickname);
        }
Beispiel #6
0
        public override void Dump(System.IO.TextWriter stream)
        {
            this.Regulation.Left.Dump(stream);
            stream.Write(" ::= ");

            int count = this.Regulation.RightPart.Count();

            for (int i = 0; i < count; i++)
            {
                if (i == this.DotPosition)
                {
                    stream.Write('.'); stream.Write(' ');
                }

                TreeNodeType item = this.Regulation.RightNode(i);
                item.Dump(stream);

                stream.Write(' ');
            }

            if (this.DotPosition == count)
            {
                stream.Write('.'); stream.Write(' ');
            }

            stream.Write(';');
            stream.Write(", ");
            this.LookAheadNodeType.Dump(stream);
        }
        public SyntaxTree Parse(TokenList tokenList)
        {
            LRParsingMap   parsingMap = GetParsingMap();
            RegulationList grammar    = GetGrammar();

            //TODO:这个convertor以后是可以配置的。
            var tokenTypeConvertor = new TokenType2TreeNodeType();
            var context            = new ParsingContext(tokenList, grammar, parsingMap, tokenTypeConvertor);

            while (context.CurrentTokenIndex < context.TokenList.Count + 1)
            {
                PrintParsingProgress(context);
                TreeNodeType    nodeType          = context.CurrentNodeType();
                int             stateId           = context.StateIdStack.Peek();
                LRParsingAction action            = parsingMap.GetAction(stateId, nodeType);
                int             currentTokenIndex = action.Execute(context);
                context.CurrentTokenIndex = currentTokenIndex;
            }

            PrintLastState(context);

            if (context.TreeStack.Count > 0)
            {
                return(context.TreeStack.Peek());
            }
            else
            {
                return(new SyntaxTree());
            }
        }
        private void PrintParsingProgress(ParsingContext context)
        {
#if DEBUG
            if (!print)
            {
                return;
            }                       // 调试时快速取消print

            Debug.WriteLine("=======================");
            {
                Debug.WriteLine("Current Stack:");
                Debug.Write("    ");
                var stateIdArray = context.StateIdStack.ToArray();
                var treeArray    = context.TreeStack.ToArray();
                for (int i = stateIdArray.Length - 1; i > 0; i--)
                {
                    Debug.Write(stateIdArray[i]);
                    Debug.Write('['); Debug.Write(treeArray[i - 1].NodeType.Nickname); Debug.Write(']');
                }
                Debug.Write(stateIdArray[0]); Debug.Write(' ');
                Debug.WriteLine("");
            }
            {
                Debug.WriteLine("Current token list:");
                Debug.Write("    ");
                for (int i = context.CurrentTokenIndex; i < context.TokenList.Count; i++)
                {
                    Debug.Write(context.TokenList[i].TokenType.Content); Debug.Write(' ');
                }
                Debug.WriteLine("");
            }
            {
                Debug.WriteLine("Next action:");
                TreeNodeType    nodeType = context.CurrentNodeType();
                int             stateId  = context.StateIdStack.Peek();
                LRParsingAction action   = context.ParsingMap.GetAction(stateId, nodeType);
                Debug.Write("    "); Debug.WriteLine(action);
            }
            {
                Debug.WriteLine("Current syntax tree:");
                SyntaxTree virtualParent = new SyntaxTree();
                virtualParent.NodeType = new TreeNodeType("VirtualParent", "", "Virtual Parent");
                var treeArray = context.TreeStack.ToArray();
                for (int i = treeArray.Length - 1; i >= 0; i--)
                {
                    virtualParent.Children.Add(treeArray[i]);
                    treeArray[i].Parent = virtualParent;
                }
                Debug.WriteLine(virtualParent);
                foreach (var item in context.TreeStack)
                {
                    item.Parent = null;
                }
            }
            Debug.WriteLine("=======================");
#endif
        }
        public virtual TreeNodeType GetNodeType(TokenType tokenType)
        {
            //TODO:“Leave__”后缀,这是个自定义规则
            string       strTreeNodeType = tokenType.Type + "Leave__";
            string       content         = tokenType.Content;
            TreeNodeType result          = new TreeNodeType(strTreeNodeType, content, tokenType.Nickname);

            return(result);
        }
        public virtual TokenType GetTokenType(TreeNodeType treeNodeType)
        {
            //TODO:“Leave__”后缀,这是个自定义规则
            string    strTokenType = treeNodeType.Type.Substring(0, treeNodeType.Type.Length - "Leave__".Length);
            string    content      = treeNodeType.Content;
            TokenType result       = new TokenType(strTokenType, treeNodeType.Content, treeNodeType.Nickname);

            return(result);
        }
Beispiel #11
0
        public Regulation(TreeNodeType left, params TreeNodeType[] rights)
            : base(getUniqueString)
        {
            if (left == null)
            {
                throw new ArgumentNullException();
            }

            this.Left = left;
            this.rightPart.AddRange(rights);
        }
Beispiel #12
0
 /// <summary>
 /// 一个FOLLOW集
 /// </summary>
 /// <param name="target"></param>
 /// <param name="values"></param>
 public FOLLOW(TreeNodeType target, params TreeNodeType[] values)
     : base(GetUniqueString)
 {
     this.Target = target;
     if (values != null)
     {
         foreach (var item in values)
         {
             this.values.TryInsert(item);
         }
     }
 }
Beispiel #13
0
        private static FOLLOW FindFollow(FOLLOWCollection followCollection, TreeNodeType target)
        {
            foreach (var item in followCollection)
            {
                if (item.Target == target)
                {
                    return(item);
                }
            }

            return(null);
        }
Beispiel #14
0
 /// <summary>
 /// 一个FIRST集
 /// </summary>
 /// <param name="target"></param>
 /// <param name="values"></param>
 public FIRST(TreeNodeType target, params TreeNodeType[] values)
     : base(GetUniqueString)
 {
     this.target.Add(target);
     if (values != null)
     {
         foreach (var item in values)
         {
             this.values.TryInsert(item);
         }
     }
 }
Beispiel #15
0
 public bool TryInsert(TreeNodeType value)
 {
     if (this.values.TryInsert(value))
     {
         this.SetDirty();
         return(true);
     }
     else
     {
         return(false);
     }
 }
Beispiel #16
0
        private static FIRST FindFirst(FIRSTCollection firstCollection, TreeNodeType target)
        {
            foreach (var item in firstCollection)
            {
                if (item.Target.Count() == 1 &&
                    item.Target.First() == target)
                {
                    return(item);
                }
            }

            return(null);
        }
        private void PrintLastState(ParsingContext context)
        {
#if DEBUG
            if (!print)
            {
                return;
            }                       // 调试时快速取消print

            Debug.WriteLine("=======================");
            Debug.WriteLine("***********************");
            {
                Debug.WriteLine("Last Stack:");
                Debug.Write("    ");
                var stateIdArray = context.StateIdStack.ToArray();
                var treeArray    = context.TreeStack.ToArray();
                for (int i = stateIdArray.Length - 1; i > 0; i--)
                {
                    Debug.Write(stateIdArray[i]);
                    Debug.Write('['); Debug.Write(treeArray[i - 1].NodeType.Nickname); Debug.Write(']');
                }
                Debug.Write(stateIdArray[0]); Debug.Write(' ');
                Debug.WriteLine("");
            }
            {
                Debug.WriteLine("Last token list:");
                Debug.Write("    ");
                for (int i = context.CurrentTokenIndex; i < context.TokenList.Count; i++)
                {
                    Debug.Write(context.TokenList[i].TokenType.Content); Debug.Write(' ');
                }
                Debug.WriteLine("");
            }
            {
                Debug.WriteLine("Last action:");
                TreeNodeType    nodeType = context.CurrentNodeType();
                int             stateId  = context.StateIdStack.Peek();
                LRParsingAction action   = context.ParsingMap.GetAction(stateId, nodeType);
                Debug.Write("    "); Debug.WriteLine(action);
            }
            {
                Debug.WriteLine("Last syntax tree:");
                Debug.WriteLine(context.TreeStack.Peek());
                foreach (var item in context.TreeStack)
                {
                    item.Parent = null;
                }
            }
            Debug.WriteLine("***********************");
            Debug.WriteLine("=======================");
#endif
        }
        // rename "next"
        /// <summary>
        /// 获取处理函数
        /// </summary>
        /// <param name="leftNode">当前结非终点类型</param>
        /// <param name="nodeType">要处理的结点类型</param>
        /// <returns></returns>
        public LRParsingAction GetAction(int stateId, TreeNodeType nodeType)
        {
            string key = stateId.ToString() + "+" + nodeType.Type.ToString();
            List <LRParsingAction> value = null;

            if (parserMap.TryGetValue(key, out value))
            {
                return(value[0]);
            }
            else
            {
                return(null);// new LR1ParsingAction(); // TODO:将来这里可以放对语法错误进行分析的函数
            }
        }
        /// <summary>
        /// 获取以指定结点为左部的规则。
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public List <Regulation> GetRegulations(TreeNodeType node)
        {
            List <Regulation> list = new List <Regulation>();

            foreach (var item in this)
            {
                if (item.Left == node)
                {
                    list.Add(item);
                }
            }

            return(list);
        }
        /// <summary>
        /// 获取所有非叶结点。
        /// </summary>
        /// <returns></returns>
        public List <TreeNodeType> GetAllTreeNodeNonLeaveTypes()
        {
            var result = new List <TreeNodeType>();

            foreach (var item in this)
            {
                TreeNodeType node = item.Left;
                if (!result.Contains(node))
                {
                    result.Add(node);
                }
            }

            return(result);
        }
        //TODO: rename "next"
        /// <summary>
        /// 设置给定语法类型、单词类型所对应的分析函数
        /// </summary>
        /// <param name="leftNode"></param>
        /// <param name="next"></param>
        /// <param name="function"></param>
        public void SetAction(int stateId, TreeNodeType next, LRParsingAction function)
        {
            string key = stateId.ToString() + "+" + next.Type.ToString();
            List <LRParsingAction> value = null;

            if (parserMap.TryGetValue(key, out value))
            {
                value.Add(function);
            }
            else
            {
                List <LRParsingAction> list = new List <LRParsingAction>();
                list.Add(function);
                parserMap.Add(key, list);
            }
        }
Beispiel #22
0
        /// <summary>
        /// LR(1)项(A->α.β,x)指出,序列α在栈顶,且输入中开头的是可以从βx导出的符号。
        /// </summary>
        /// <param name="regulation">A->αβ/param>
        /// <param name="dotPosition">圆点的位置</param>
        /// <param name="lookAheadNodeType">x代表的类型</param>
        public LR1Item(Regulation regulation, int dotPosition, TreeNodeType lookAheadNodeType)
            : base(GetUniqueString)
        {
            if (regulation == null || lookAheadNodeType == null)
            {
                throw new ArgumentNullException();
            }
            if (dotPosition < 0 || regulation.RightPart.Count() < dotPosition)
            {
                throw new ArgumentOutOfRangeException();
            }

            this.Regulation        = regulation;
            this.DotPosition       = dotPosition;
            this.LookAheadNodeType = lookAheadNodeType;
        }
Beispiel #23
0
        /// <summary>
        /// LR(0)的Goto操作。
        /// 将圆点移到所有LR(0)项中的符号<paramref name="x"/>之后。
        /// </summary>
        /// <param name="list"></param>
        /// <param name="state"></param>
        /// <param name="x">一个文法符号,终结点或非终结点。</param>
        /// <returns></returns>
        static LR0State Goto(this RegulationList list, LR0State state, TreeNodeType x)
        {
            LR0State toState = new LR0State();

            foreach (var item in state)
            {
                TreeNodeType nextNode = item.GetNodeNext2Dot();
                if (nextNode == x)
                {
                    var newItem = new LR0Item(item.Regulation, item.DotPosition + 1);
                    toState.TryInsert(newItem);
                }
            }

            return(Closure(list, toState));
        }
Beispiel #24
0
        /// <summary>
        /// list中指定的某一段结点是否都能产生null?
        /// </summary>
        /// <param name="list"></param>
        /// <param name="startIndex"></param>
        /// <param name="count"></param>
        /// <param name="nullableDict"></param>
        /// <returns></returns>
        static bool Nullable(IReadOnlyList <TreeNodeType> list, int startIndex, int count, Dictionary <TreeNodeType, bool> nullableDict)
        {
            bool result = true;

            for (int i = 0; i < count; i++)
            {
                TreeNodeType node = list[i + startIndex];
                if (!nullableDict[node])
                {
                    result = false;
                    break;
                }
            }

            return(result);
        }
        /// <summary>
        /// LR(1)的Goto操作。
        /// 将圆点移到所有LR(1)项中的符号<paramref name="x"/>之后。
        /// </summary>
        /// <param name="list"></param>
        /// <param name="state"></param>
        /// <param name="x">一个文法符号,终结点或非终结点。</param>
        /// <param name="firstList"></param>
        /// <returns></returns>
        static SmallerLR1State Goto(this RegulationList list, SmallerLR1State state, TreeNodeType x, Dictionary <TreeNodeType, bool> nullableDict, FIRSTCollection firstList = null)
        {
            var toState = new SmallerLR1State();

            foreach (var group in state.GetGroups())
            {
                TreeNodeType nextNode = group.Item1.GetNodeNext2Dot();
                if (nextNode == x)
                {
                    toState.TryInsert(
                        new LR0Item(group.Item1.Regulation, group.Item1.DotPosition + 1),
                        group.Item2);
                }
            }

            return(Closure(list, toState, nullableDict, firstList));
        }
        /// <summary>
        /// LR(1)的Closure操作。
        /// 补全一个状态。
        /// </summary>
        /// <param name="grammar"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        static SmallerLR1State Closure(this RegulationList grammar, SmallerLR1State state,
                                       Dictionary <TreeNodeType, bool> nullableDict = null, FIRSTCollection firstCollection = null)
        {
            if (nullableDict == null)
            {
                grammar.GetNullableDict(out nullableDict);
            }
            if (firstCollection == null)
            {
                grammar.GetFirstCollection(out firstCollection, nullableDict);
            }

            Queue <LR1Item> queue = new Queue <LR1Item>();

            foreach (var item in state)
            {
                queue.Enqueue(item);
            }
            while (queue.Count > 0)
            {
                LR1Item      item = queue.Dequeue();
                TreeNodeType node = item.GetNodeNext2Dot();
                if (node == null || node.IsLeave)
                {
                    continue;
                }

                List <TreeNodeType> betaZ     = item.GetBetaZ();
                FIRST             first       = grammar.GetFirst(firstCollection, nullableDict, betaZ);
                List <Regulation> regulations = grammar.GetRegulations(node);
                foreach (var regulation in regulations)
                {
                    foreach (var value in first.Values)
                    {
                        LR1Item newItem = new LR1Item(regulation, 0, value);
                        if (state.TryInsert(newItem))
                        {
                            queue.Enqueue(newItem);
                        }
                    }
                }
            }

            return(state);
        }
        public List <TreeNodeType> GetAllTreeNodeTypes()
        {
            var result = new List <TreeNodeType>();

            foreach (var item in this)
            {
                {
                    TreeNodeType node = item.Left;
                    if (!result.Contains(node))
                    {
                        result.Add(node);
                    }
                }
                foreach (var node in item.RightPart)
                {
                    if (!result.Contains(node))
                    {
                        result.Add(node);
                    }
                }
            }

            return(result);
        }
        /// <summary>
        /// 用LR(1)分析法计算分析表
        /// </summary>
        /// <param name="grammar"></param>
        /// <returns></returns>
        public static void GetLR1ParsingMap(this RegulationList grammar,
                                            out LRParsingMap map,
                                            out LR1StateCollection stateCollection,
                                            out LR1EdgeCollection edgeCollection, TextWriter originalOut)
        {
            // 给文法添加一个辅助的开始产生式 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 LR1Item(decoratedGrammar[0], 0, decoratedEnd);
            var firstState = new SmallerLR1State(firstItem);
            Dictionary <TreeNodeType, bool> nullableDict;

            decoratedGrammar.GetNullableDict(out nullableDict);
            FIRSTCollection firstCollection;

            decoratedGrammar.GetFirstCollection(out firstCollection, nullableDict);
            firstState      = decoratedGrammar.Closure(firstState, nullableDict, firstCollection);
            stateCollection = new LR1StateCollection(firstState);
            edgeCollection  = new LR1EdgeCollection(stateCollection);
            var queue = new Queue <SmallerLR1State>();

            queue.Enqueue(firstState);
            int lastOutputLength = 0;
            int stateListCount   = 1;
            int queueCount       = 1;

            while (queue.Count > 0)
            {
                SmallerLR1State fromState  = queue.Dequeue(); queueCount--;
                int             itemIndex  = 0;
                int             groupCount = fromState.GroupCount;
                foreach (var group in fromState.GetGroups())
                {
                    {
                        TextWriter currentWriter = Console.Out;
                        if (Console.Out != originalOut)
                        {
                            Console.SetOut(originalOut);
                        }
                        for (int i = 0; i < lastOutputLength; i++)
                        {
                            Console.Write('\u0008');
                        }
                        string output = string.Format("Calculating LR(1) State List: {0} <-- {1}, working on group {2}/{3} ...",
                                                      stateListCount, queueCount, 1 + itemIndex++, groupCount);
                        Console.Write(output);
                        lastOutputLength = output.Length;
                        Console.SetOut(currentWriter);
                    }
                    TreeNodeType x = group.Item1.GetNodeNext2Dot();
                    if (x == null || x == decoratedEnd)
                    {
                        continue;
                    }
                    SmallerLR1State toState = decoratedGrammar.Goto(fromState, x, nullableDict, firstCollection);
                    if (stateCollection.TryInsert(toState))//融入组织之中吧
                    {
                        int index = stateCollection.IndexOf(toState);
                        toState = stateCollection[index];
                        queue.Enqueue(toState);
                        stateListCount++;
                        queueCount++;
                        var edge = new LR1Edge(fromState, x, toState);
                        edgeCollection.TryInsert(edge);
                    }
                    else
                    {
                        int index = stateCollection.IndexOf(toState);
                        toState = stateCollection[index];
                        var edge = new LR1Edge(fromState, x, toState);
                        edgeCollection.TryInsert(edge);
                    }
                }
            }
            {
                TextWriter currentWriter = Console.Out;
                if (Console.Out != originalOut)
                {
                    Console.SetOut(originalOut);
                }
                Console.WriteLine();
                Console.SetOut(currentWriter);
            }

            map = new LRParsingMap();
            foreach (var edge in edgeCollection)
            {
                if (edge.X.IsLeave)
                {
                    int stateId = edge.From.ParsingMapIndex + 1; // stateCollection.IndexOf(edge.From) + 1;
                    int gotoId  = edge.To.ParsingMapIndex + 1;   //stateCollection.IndexOf(edge.To) + 1
                    map.SetAction(stateId, edge.X, new LR1ShiftInAction(gotoId));
                }
                else
                {
                    int stateId = edge.From.ParsingMapIndex + 1; // stateCollection.IndexOf(edge.From) + 1;
                    int gotoId  = edge.To.ParsingMapIndex + 1;   //stateCollection.IndexOf(edge.To) + 1
                    map.SetAction(stateId, edge.X, new LR1GotoAction(gotoId));
                }
            }
            // TODO: not implemented
            var endItem = new LR1Item(decoratedRegulation, 1, decoratedEnd);

            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 LR1Item in state)
                {
                    if (LR1Item.GetNodeNext2Dot() == null)
                    {
                        int stateId = state.ParsingMapIndex + 1;// stateCollection.IndexOf(state) + 1;
                        map.SetAction(stateId, LR1Item.LookAheadNodeType,
                                      new LR1ReducitonAction(decoratedGrammar.IndexOf(LR1Item.Regulation)));
                    }
                }
            }
        }
Beispiel #29
0
        /// <summary>
        /// 计算文法的FOLLOW集
        /// </summary>
        /// <param name="grammar"></param>
        /// <param name="nullableDict"></param>
        /// <param name="firstList4Node"></param>
        /// <returns></returns>
        private static void DoGetFollowList(
            this RegulationList grammar,
            out FOLLOWCollection followCollection,
            Dictionary <TreeNodeType, bool> nullableDict, FIRSTCollection firstList4Node)
        {
            // 初始化Follow list
            followCollection = new FOLLOWCollection();
            foreach (var item in grammar.GetAllTreeNodeNonLeaveTypes())
            {
                followCollection.TryInsert(new FOLLOW(item));
            }

            // 迭代到不动点
            bool changed = false;

            do
            {
                changed = false;
                foreach (var regulation in grammar)
                {
                    int count = regulation.RightPart.Count();
                    for (int index = 0; index < count; index++)
                    {
                        // 准备为target添加follow元素
                        TreeNodeType target = regulation.RightNode(index);
                        if (target.IsLeave)
                        {
                            continue;
                        }                                                     // 叶结点没有follow
                        FOLLOW follow = FindFollow(followCollection, target); // 找到follow对象
                        for (int checkCount = 0; checkCount < count - (index + 1); checkCount++)
                        {
                            if (Nullable(regulation.RightPart, index + 1, checkCount, nullableDict))
                            {
                                // nullable之后的FIRST是target的follow的一部分
                                FIRST first = FindFirst(
                                    firstList4Node, regulation.RightNode(index + 1 + checkCount));
                                foreach (var value in first.Values)
                                {
                                    if (value != TreeNodeType.NullNode)
                                    {
                                        changed = follow.TryInsert(value) || changed;
                                    }
                                }
                            }
                        }
                        {
                            // 如果target之后的全部结点都是nullable,说明此regulation.Left的folow也是target的一部分。
                            if (Nullable(regulation.RightPart, index + 1, count - (index + 1), nullableDict))
                            {
                                // 找到此regulation.Left的folow
                                FOLLOW refFollow = FindFollow(followCollection, regulation.Left);
                                if (refFollow != follow)
                                {
                                    foreach (var item in refFollow.Values)
                                    {
                                        changed = follow.TryInsert(item) || changed;
                                    }
                                }
                            }
                        }
                    }
                }
            } while (changed);
        }
        /// <summary>
        /// 用SLR分析法计算分析表
        /// </summary>
        /// <param name="grammar"></param>
        /// <returns></returns>
        public static void GetSLRParsingMap(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 SLR 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)
            {
                if (edge.X.IsLeave)
                {
                    int stateId     = edge.From.ParsingMapIndex + 1; //stateCollection.IndexOf(edge.From) + 1
                    int gotoStateId = edge.To.ParsingMapIndex + 1;   //stateCollection.IndexOf(edge.To) + 1
                    map.SetAction(stateId, edge.X, new LR1ShiftInAction(gotoStateId));
                }
                else
                {
                    int stateId     = edge.From.ParsingMapIndex + 1; //stateCollection.IndexOf(edge.From) + 1
                    int gotoStateId = edge.To.ParsingMapIndex + 1;   //stateCollection.IndexOf(edge.To) + 1
                    map.SetAction(stateId, edge.X, new LR1GotoAction(gotoStateId));
                }
            }
            var endItem = new LR0Item(decoratedRegulation, 1);
            FOLLOWCollection followCollection;

            decoratedGrammar.GetFollowCollection(out followCollection);
            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 lr0Item in state)
                {
                    if (lr0Item.GetNodeNext2Dot() == null)
                    {
                        FOLLOW follow = FindFollow(followCollection, lr0Item.Regulation.Left);
                        foreach (var value in follow.Values)
                        {
                            int stateId     = state.ParsingMapIndex + 1;// stateCollection.IndexOf(state) + 1;
                            int reductionId = decoratedGrammar.IndexOf(lr0Item.Regulation);
                            var action      = new LR1ReducitonAction(reductionId);
                            map.SetAction(stateId, value, action);
                        }
                    }
                }
            }
        }