Ejemplo n.º 1
0
        public static cSet <cLexem> cm_FirstTerminals(List <cLexem> a_listLexem)
        {
            cSet <cLexem> _tempSet = new cSet <cLexem>();

            if (a_listLexem.Count > 0)
            {
                int    _pos       = 0;
                cLexem _currLexem = a_listLexem[_pos];
                do
                {
                    _tempSet.Remove(cLexem.cc_EpsilonLexem);
                    _currLexem = a_listLexem[_pos];
                    _tempSet.UnionWith(_currLexem.cp_FirstCache);
                    _pos++;
                } while (_tempSet.Contains(cLexem.cc_EpsilonLexem) && (_pos < a_listLexem.Count));
            }
            cSet <cLexem> _retSet = new cSet <cLexem>();

            foreach (cLexem _lexem in _tempSet)
            {
                if (_lexem.cp_Type != eLexType.NonTerminal)
                {
                    _retSet.Add(_lexem);
                }
            }
            return(_retSet);
        }
Ejemplo n.º 2
0
        public object Clone()
        {
            cSet <T> _retSet = new cSet <T>();

            _retSet.UnionWith(this);
            return(_retSet);
        }
Ejemplo n.º 3
0
 private cLexem(string a_name, eLexType a_type)
 {
     cf_firstCache   = null;
     cf_EpsilonCount = 0;
     cf_Name         = a_name;
     cf_type         = a_type;
     if (a_name == cc_Epsilon)
     {
         cf_type = eLexType.Epsilon;
     }
 }
Ejemplo n.º 4
0
        private cSet <cLexem> cm_getAllPossibleGotoLexems(cSet <cConfiguration> a_set)
        {
            cSet <cLexem> _retSet = new cSet <cLexem>();

            foreach (cConfiguration _configuration in a_set)
            {
                if (_configuration.cf_Production.cp_RightPart.Count > _configuration.cf_Position)
                {
                    _retSet.Add(_configuration.cf_Production.cp_RightPart[_configuration.cf_Position]);
                }
            }
            _retSet.Remove(cLexem.cc_EpsilonLexem);
            return(_retSet);
        }
Ejemplo n.º 5
0
        public static cSet <cConfiguration> cm_Goto(cSet <cConfiguration> a_listConfiguration, cLexem a_lexem)
        {
            cSet <cConfiguration> _validConfigurations = new cSet <cConfiguration>();

            foreach (cConfiguration _configuration in a_listConfiguration)
            {
                if (_configuration.cf_Production.cp_RightPart.Count > _configuration.cf_Position)
                {
                    if (_configuration.cf_Production.cp_RightPart[_configuration.cf_Position] == a_lexem)
                    {
                        cConfiguration _newConfiguration = cConfiguration.cm_GetConfiguration(_configuration.cf_Production, _configuration.cf_Position + 1, _configuration.cf_Terminal);
                        _validConfigurations.Add(_newConfiguration);
                    }
                }
            }
            return(cm_Closure(_validConfigurations));
        }
Ejemplo n.º 6
0
        private cSet <cLexem> cm_First(List <cLexem> a_listLexem)
        {
            cSet <cLexem> _retSet = new cSet <cLexem>();

            if (a_listLexem.Count > 0)
            {
                int    _pos       = a_listLexem.Count - 1;
                cLexem _currLexem = a_listLexem[_pos];
                do
                {
                    _retSet.Remove(cLexem.cc_EpsilonLexem);
                    _currLexem = a_listLexem[_pos];
                    _retSet.UnionWith(_currLexem.cp_FirstCache);
                    _pos--;
                } while (_retSet.Contains(cLexem.cc_EpsilonLexem) && (_pos >= 0));
            }
            return(_retSet);
        }
Ejemplo n.º 7
0
        public static cSet <cConfiguration> cm_Closure(cSet <cConfiguration> a_listConfiguration)
        {
            bool _added = false;

            if (a_listConfiguration != null)
            {
                cSet <cConfiguration> _retList    = a_listConfiguration.Clone() as cSet <cConfiguration>;
                cSet <cConfiguration> _addRetList = new cSet <cConfiguration>();
                do
                {
                    _addRetList.Clear();
                    foreach (cConfiguration _configuration in _retList)
                    {
                        if (_configuration.cf_Production.cp_RightPart.Count > _configuration.cf_Position)
                        {
                            cLexem _lexem = _configuration.cf_Production.cp_RightPart[_configuration.cf_Position];
                            if (_lexem.cp_Type == eLexType.NonTerminal)
                            {
                                List <cLexem> _listTerminals = new List <cLexem>();
                                _listTerminals.AddRange(_configuration.cf_Production.cp_RightPart.GetRange(_configuration.cf_Position + 1, _configuration.cf_Production.cp_RightPart.Count - _configuration.cf_Position - 1));
                                _listTerminals.Add(_configuration.cf_Terminal);
                                cSet <cLexem> _firstTerminals = cm_FirstTerminals(_listTerminals);
                                foreach (cProduction _production in _lexem.cp_ListProducts)
                                {
                                    foreach (cLexem _terminal in _firstTerminals)
                                    {
                                        cConfiguration _newConfiguration = cConfiguration.cm_GetConfiguration(_production, 0, _terminal);
                                        _addRetList.Add(_newConfiguration);
                                    }
                                }
                            }
                        }
                    }
                    _added = _retList.AddRange(_addRetList);
                } while (_added == true);
                return(_retList);
            }
            else
            {
                return(new cSet <cConfiguration>());
            }
        }
Ejemplo n.º 8
0
        private bool cm_addItemGroup(List <cSet <cConfiguration> > a_items, cSet <cConfiguration> a_item, cLexem a_lexem, cSet <cConfiguration> a_set, Dictionary <cSet <cConfiguration>, Dictionary <cLexem, cSet <cConfiguration> > > a_goto)
        {
            bool _notSubset = true;

            foreach (cSet <cConfiguration> _set in a_items)
            {
                if (_set.IsSupersetOf(a_set))
                {
                    _notSubset = false;
                    cm_addToGoto(a_goto, a_item, a_lexem, _set);
                    break;
                }
            }
            if (_notSubset)
            {
                a_items.Add(a_set);
                cm_addToGoto(a_goto, a_item, a_lexem, a_set);
            }
            return(_notSubset);
        }
Ejemplo n.º 9
0
        List <cLexem> cm_getLeadLexemsInternal(List <cLexem> a_watchedLexems)
        {
            List <cLexem> _retLst = new List <cLexem>();

            if (a_watchedLexems.Contains(this))
            {
                //if (cf_type == eLexType.Terminal || cf_type == eLexType.NonTerminal)
                throw new cNotLL1Exception(this, null, String.Empty);
            }
            else
            {
                a_watchedLexems.Add(this);
                switch (cf_type)
                {
                case eLexType.NonTerminal:
                    foreach (KeyValuePair <cLexem, List <cLexem> > _kvp in cf_listProducts)
                    {
                        if (_kvp.Key.cp_Type != eLexType.Epsilon)
                        {
                            cm_fillNonTerminalLeadingLexList(a_watchedLexems, _kvp.Value, 0, _retLst);
                        }
                        else
                        {
                            _retLst.Add(_kvp.Key);
                        }
                    }
                    if (cf_leadLexems == null)
                    {
                        cf_leadLexems = new cSet <cLexem>();
                        cf_leadLexems.AddRange(_retLst);
                    }
                    break;

                case eLexType.Terminal:
                case eLexType.Epsilon:
                    _retLst.Add(this);
                    break;
                }
            }
            return(_retLst);
        }
Ejemplo n.º 10
0
        private KeyValuePair <List <cSet <cConfiguration> >, Dictionary <cSet <cConfiguration>, Dictionary <cLexem, cSet <cConfiguration> > > > cm_Items(cLexem a_root)
        {
            List <cSet <cConfiguration> > _retList = new List <cSet <cConfiguration> >();

            cConfiguration        _rootConfiguration = cConfiguration.cm_GetConfiguration(a_root.cp_ListProducts[0], 0, cLexem.cc_StopLexem);
            cSet <cConfiguration> _rootClosure       = cConfiguration.cm_Closure(new cSet <cConfiguration>()
            {
                _rootConfiguration
            });

            Dictionary <cSet <cConfiguration>, Dictionary <cLexem, cSet <cConfiguration> > > _gotoResults = new Dictionary <cSet <cConfiguration>, Dictionary <cLexem, cSet <cConfiguration> > >();

            _retList.Add(_rootClosure);

            bool _added       = false;
            int  _lastChecked = 0;

            do
            {
                _added = false;
                for (; _lastChecked < _retList.Count; _lastChecked++)
                {
                    cSet <cConfiguration> _currentItem    = _retList[_lastChecked];
                    cSet <cLexem>         _currentChecked = cm_getAllPossibleGotoLexems(_currentItem);
                    foreach (cLexem _lexem in _currentChecked)
                    {
                        cSet <cConfiguration> _possibleItem = cConfiguration.cm_Goto(_currentItem, _lexem);
                        if (cm_addItemGroup(_retList, _currentItem, _lexem, _possibleItem, _gotoResults))
                        {
                            _added = true;
                        }
                    }
                }
            } while (_added);

            return(new KeyValuePair <List <cSet <cConfiguration> >, Dictionary <cSet <cConfiguration>, Dictionary <cLexem, cSet <cConfiguration> > > >(_retList, _gotoResults));
        }
Ejemplo n.º 11
0
        //private static cSet<cLexem> cm_FirstInList(List<cLexem> a_listLexem)
        //{
        //    cSet<cLexem> _retSet = new cSet<cLexem>();
        //    if (a_listLexem.Count > 0)
        //    {
        //        int _pos = 0;
        //        cLexem _currLexem = a_listLexem[_pos];
        //        do
        //        {
        //            _retSet.Remove(cLexem.cc_EpsilonLexem);
        //            _currLexem = a_listLexem[_pos++];
        //            _currLexem.cm_First(_retSet);
        //        } while (_retSet.Contains(cLexem.cc_EpsilonLexem) && (_pos < a_listLexem.Count));
        //    }
        //    return _retSet;
        //}

        //public cSet<cLexem> cm_First(cSet<cLexem> a_set)
        //{
        //    if (cf_firstCache == null)
        //    {
        //        cSet<cLexem> _retSet = a_set ?? new cSet<cLexem>();
        //        switch (cf_type)
        //        {
        //            case (eLexType.Epsilon):
        //            case (eLexType.Stop):
        //            case (eLexType.Terminal):
        //                _retSet.Add(this);
        //                break;
        //            case (eLexType.NonTerminal):
        //                if (cf_EpsilonCount > 0)
        //                {
        //                    _retSet.Add(cc_EpsilonLexem);
        //                }
        //                bool _added = false;
        //                do
        //                {
        //                    _added = false;
        //                    foreach (cProduction _production in cf_listProducts)
        //                    {
        //                        if (_production.cp_RightPart.Count > 0)
        //                        {
        //                            int _pos = 0;
        //                            cLexem _currLexem = _production.cp_RightPart[_pos];
        //                            do
        //                            {
        //                                _retSet.Remove(cLexem.cc_EpsilonLexem);
        //                                _currLexem = _production.cp_RightPart[_pos++];
        //                                if (_currLexem != this)
        //                                {
        //                                    _currLexem.cm_First(_retSet);
        //                                }
        //                                else
        //                                {
        //                                    break;
        //                                    //if (_retSet.Contains(cLexem.cc_EpsilonLexem))
        //                                    //{
        //                                    //    //    int _countBefore=_retSet.Count;
        //                                    //    //    for
        //                                    //}
        //                                    //else
        //                                    //{
        //                                    //    break;
        //                                    //}
        //                                }
        //                            } while (_retSet.Contains(cLexem.cc_EpsilonLexem) && (_pos < _production.cp_RightPart.Count));
        //                        }
        //                    }
        //                } while (_added);
        //                break;
        //            default:
        //                throw new Exception("Передан некорректный тип в cm_First: " + cf_type.ToString());
        //        }
        //        cf_firstCache = _retSet.Clone() as cSet<cLexem>;
        //        return _retSet;
        //    }
        //    else
        //    {
        //        if (a_set == null)
        //        {
        //            return cf_firstCache.Clone() as cSet<cLexem>;
        //        }
        //        else
        //        {
        //            a_set.AddRange(cf_firstCache);
        //            return a_set;
        //        }
        //    }
        //}

        public static void cm_CacheFirst()
        {
            Dictionary <cLexem, cSet <cLexem> > _firstPerLexem = new Dictionary <cLexem, cSet <cLexem> >();

            foreach (cLexem _lexem in cf_LexemDic.Values)
            {
                _firstPerLexem.Add(_lexem, new cSet <cLexem>());
            }
            _firstPerLexem.Add(cLexem.cc_EpsilonLexem, new cSet <cLexem>());
            _firstPerLexem.Add(cLexem.cc_StopLexem, new cSet <cLexem>());

            bool _added = false;

            do
            {
                _added = false;
                foreach (cLexem _lexem in _firstPerLexem.Keys)
                {
                    switch (_lexem.cf_type)
                    {
                    case eLexType.Epsilon:
                    case eLexType.Stop:
                    case eLexType.Terminal:
                        _added |= _firstPerLexem[_lexem].Add(_lexem);
                        break;

                    case eLexType.NonTerminal:
                        foreach (cProduction _production in _lexem.cf_listProducts)
                        {
                            if (_production.cp_RightPart.Count > 0)
                            {
                                int    _pos        = 0;
                                cLexem _currLexem  = _production.cp_RightPart[_pos];
                                bool   _hasEpsilon = false;
                                do
                                {
                                    _currLexem  = _production.cp_RightPart[_pos];
                                    _hasEpsilon = false;
                                    cSet <cLexem> _currentSet = _firstPerLexem[_currLexem];
                                    _hasEpsilon |= _currentSet.Contains(cLexem.cc_EpsilonLexem);
                                    if (_hasEpsilon)
                                    {
                                        _currentSet = _currentSet.Clone() as cSet <cLexem>;
                                        _currentSet.Remove(cLexem.cc_EpsilonLexem);
                                    }
                                    _added |= _firstPerLexem[_lexem].AddRange(_currentSet);
                                    _pos++;
                                } while (_hasEpsilon && (_pos < _production.cp_RightPart.Count));
                                if (_hasEpsilon)
                                {
                                    _added |= _firstPerLexem[_lexem].Add(cLexem.cc_EpsilonLexem);
                                }
                            }
                        }
                        break;

                    case eLexType.Action:
                        break;

                    default:
                        throw new Exception("Некорректный тип в cm_CacheFirst: " + _lexem.cf_type.ToString());
                    }
                }
            } while (_added);

            foreach (cLexem _lexem in _firstPerLexem.Keys)
            {
                _lexem.cf_firstCache = _firstPerLexem[_lexem];
            }
        }
Ejemplo n.º 12
0
        public void cm_Init(cParser a_parser)
        {
            cf_valid = false;
            cf_root  = a_parser.cp_Root;

            // Заполнение множества FOLLOW
            cf_follow = new Dictionary <cLexem, cSet <cLexem> >();
            foreach (cLexem _nonTerminal in cp_Lexems)
            {
                if (_nonTerminal.cp_Type == eLexType.NonTerminal)
                {
                    cf_follow[_nonTerminal] = new cSet <cLexem>();
                }
            }

            // 2
            cSet <cLexem> _first = new cSet <cLexem>();

            foreach (cLexem _nonTerminal in cp_Lexems)
            {
                if (_nonTerminal.cp_Type == eLexType.NonTerminal)
                {
                    foreach (List <cLexem> _lstLex in _nonTerminal.cp_ListProducts.Values)
                    {
                        int _count = _lstLex.Count;
                        _first.Clear();
                        for (int i = _lstLex.Count - 1; i >= 0; i--)
                        {
                            cLexem _lex = _lstLex[i];
                            switch (_lex.cp_Type)
                            {
                            case eLexType.NonTerminal:
                                cf_follow[_lex].AddRange(_first);
                                if (!_lex.cm_IsLeadingLexem(cLexem.cc_EpsilonLexem))
                                {
                                    _first.Clear();
                                }
                                _first.AddRange(_lex.cp_LeadLexems);
                                break;

                            case eLexType.Terminal:
                                _first.Clear();
                                _first.Add(_lex);
                                break;

                            case eLexType.Epsilon:
                                _first.Clear();
                                break;
                            }
                        }
                    }
                }
            }

            // 3
            bool _added = true;

            while (_added)
            {
                _added = false;
                foreach (cLexem _nonTerminal in cp_Lexems)
                {
                    if (_nonTerminal.cp_Type == eLexType.NonTerminal)
                    {
                        foreach (List <cLexem> _lstLex in _nonTerminal.cp_ListProducts.Values)
                        {
                            int _count = _lstLex.Count;
                            _first.Clear();
                            bool _break = false;
                            for (int i = _lstLex.Count - 1; i >= 0; i--)
                            {
                                cLexem _lex = _lstLex[i];
                                switch (_lex.cp_Type)
                                {
                                case eLexType.NonTerminal:
                                    cf_follow[_lex].AddRange(_first);
                                    if (!_lex.cm_IsLeadingLexem(cLexem.cc_EpsilonLexem))
                                    {
                                        _break = true;
                                    }
                                    //else
                                    _added = cf_follow[_lex].AddRange(cf_follow[_nonTerminal]) | _added;
                                    break;

                                case eLexType.Action:
                                    break;

                                default:
                                    _break = true;
                                    break;
                                }
                                if (_break)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            cf_valid = true;
        }
Ejemplo n.º 13
0
        DataTable cm_fillDataTable(cProductInfo[] a_data)
        {
            cm_checkProducts(a_data);
            Dictionary <cLexem, int> _dicJump = new Dictionary <cLexem, int>();

            for (int k = 0; k < a_data.Length; k++)
            {
                if (!_dicJump.ContainsKey(a_data[k].cp_Root.Key))
                {
                    _dicJump.Add(a_data[k].cp_Root.Key, a_data[k].cp_Root.Value);
                }
            }

            DataTable _retDT = new DataTable("table");

            _retDT.Columns.Add("i", typeof(int));
            _retDT.Columns.Add("terminals", typeof(string[]) /*typeof(object)*/);
            _retDT.Columns.Add("jump", typeof(int));
            _retDT.Columns.Add("accept", typeof(bool));
            _retDT.Columns.Add("stack", typeof(bool));
            _retDT.Columns.Add("return", typeof(bool));
            _retDT.Columns.Add("error", typeof(bool));
            _retDT.Columns.Add("action", typeof(string));

            int  _count   = a_data.Length;
            bool _warning = false;

            for (int k = 0; k < _count; k++)
            {
                cProductInfo _info = a_data[k];

                // Проверка LL(1)
                if (k == 0 || a_data[k - 1].cp_Root.Key != _info.cp_Root.Key)
                {
                    _warning = _info.cp_Root.Key.cm_HasEpsilonProduct();
                }
                foreach (cLexem _lex in _info.cp_ArrDirLexems)
                {
                    if (cf_follow[_info.cp_Root.Key].ContainsKey(_lex))
                    {
                        if (_warning)
                        {
                            throw new Exception("Невозможно однозначно определить переход из-за " + cLexem.cc_Epsilon + "-порождающей продукции в " + _info.cp_Root.Key + ".");
                        }
                        if (_lex.cp_Type != eLexType.Epsilon)
                        {
                            _warning = true;
                        }
                    }
                    else if (_lex.cp_Type == eLexType.Epsilon)
                    {
                        if (_warning)
                        {
                            throw new Exception("Невозможно однозначно определить переход из-за " + cLexem.cc_Epsilon + "-порождающей продукции в " + _info.cp_Root.Key + ".");
                        }
                        _warning = true;
                    }
                }

                int           _i         = _info.cp_Root.Value;
                cSet <string> _terminals = new cSet <string>();
                foreach (cLexem _lex in _info.cp_ArrDirLexems)
                {
                    if (_lex.cp_Type == eLexType.Terminal)
                    {
                        _terminals.Add(_lex.cf_Name);
                    }
                }
                int  _jump   = _info.cp_ArrLexems[0].Value;
                bool _accept = false;
                bool _stack  = false;
                bool _return = false;
                bool _error  = false;
                if (k == _count - 1 || a_data[k + 1].cp_Root.Key != _info.cp_Root.Key)
                {
                    _error = true;
                }
                string _action = "";
                //_terminals.Sort();
                _retDT.Rows.Add(_i, _terminals.ToArray(), _jump, _accept, _stack, _return, _error, _action);

                KeyValuePair <cLexem, int>[] _arrLexems = _info.cp_ArrLexems;
                int _lexCount = _arrLexems.Length;
                for (int j = 0; j < _lexCount; j++)
                {
                    cLexem _lexem = _arrLexems[j].Key;
                    _i = _arrLexems[j].Value;

                    // ERROR
                    _error = true;

                    // TERMINALS
                    switch (_lexem.cp_Type)
                    {
                    case eLexType.Epsilon:
                        _terminals = new cSet <string>();
                        //foreach (cLexem _lex in _info.cp_ArrDirLexems)
                        //    _terminals.Add(_lex.cf_Name);
                        break;

                    case eLexType.Terminal:
                        _terminals = new cSet <string>();
                        _terminals.Add(_lexem.cf_Name);
                        break;

                    case eLexType.NonTerminal:
                        _terminals = new cSet <string>();
                        foreach (cLexem _lex in _lexem.cp_LeadLexems)
                        {
                            if (_lex.cp_Type == eLexType.Epsilon)
                            {
                                if (j == _lexCount - 1)
                                {
                                    _retDT.Rows.Add(_i + 1, new string[0], 0, false, false, true, true, "");
                                }
                                _error = false;
                            }
                            else
                            {
                                _terminals.Add(_lex.cf_Name);
                            }
                        }
                        break;

                    case eLexType.Action:
                        _terminals = new cSet <string>();
                        break;
                    }

                    // JUMP
                    if (_lexem.cp_Type == eLexType.NonTerminal)
                    {
                        _jump = _dicJump[_lexem];
                    }
                    else
                    {
                        // Не последний терминал или действие
                        //if (j < _lexCount - 1)
                        _jump = _i + 1;
                        // Последний терминал или действие
                        //else
                        //    _jump = 0;
                    }

                    // ACCEPT
                    _accept = _lexem.cp_Type == eLexType.Terminal;

                    // STACK
                    // Не последний нетерминал правой части
                    _stack = (_lexem.cp_Type == eLexType.NonTerminal && j < _lexCount - 1);

                    // RETURN
                    // Крайний правый терминал или действие
                    _return = ((_lexem.cp_Type != eLexType.NonTerminal) && j == _lexCount - 1);

                    // ACTION
                    _action = "";
                    if (_lexem.cp_Type == eLexType.Action)
                    {
                        _action = _lexem.cf_Name;
                    }

                    //_terminals.Sort();
                    _retDT.Rows.Add(_i, _terminals.ToArray(), _jump, _accept, _stack, _return, _error, _action);
                }
            }

            // Сортировка строк
            DataTable _oldDT = _retDT;

            _retDT = _oldDT.Clone();

            foreach (DataRow _dr in _oldDT.Select(null, "i"))
            {
                _retDT.Rows.Add(_dr.ItemArray);
            }

            return(_retDT);
        }
Ejemplo n.º 14
0
        private bool cm_addToGoto(Dictionary <cSet <cConfiguration>, Dictionary <cLexem, cSet <cConfiguration> > > a_goto, cSet <cConfiguration> a_item, cLexem a_lexem, cSet <cConfiguration> a_gotoItem)
        {
            bool _retVal;

            if (!a_goto.ContainsKey(a_item))
            {
                a_goto.Add(a_item, new Dictionary <cLexem, cSet <cConfiguration> >());
            }
            if (!a_goto[a_item].ContainsKey(a_lexem))
            {
                a_goto[a_item].Add(a_lexem, a_gotoItem);
                _retVal = true;
            }
            else
            {
                _retVal = false;
                throw new Exception("Попытка заменить значение в дереве Goto при построении списка пунктов");
            }
            return(_retVal);
        }
Ejemplo n.º 15
0
        private Dictionary <cLexem, cSet <cLexem> > cm_Follow()
        {
            Dictionary <cLexem, cSet <cLexem> > _retDic = new Dictionary <cLexem, cSet <cLexem> >();

            foreach (cLexem _nonTerminal in cp_Lexems)
            {
                if (_nonTerminal.cp_Type == eLexType.NonTerminal)
                {
                    _retDic[_nonTerminal] = new cSet <cLexem>();
                }
            }

            _retDic[cf_root].Add(cLexem.cc_StopLexem);

            // 2
            foreach (cLexem _nonTerminal in _retDic.Keys)
            {
                foreach (cProduction _production in _nonTerminal.cp_ListProducts)
                {
                    int           _count          = _production.cp_RightPart.Count - 1;
                    List <cLexem> _revListProduct = new List <cLexem>();
                    for (int i = _count; i >= 0; i--)
                    {
                        cLexem _lex = _production.cp_RightPart[i];
                        switch (_lex.cp_Type)
                        {
                        case eLexType.NonTerminal:
                            cSet <cLexem> _first = cm_First(_revListProduct);
                            _first.Remove(cLexem.cc_EpsilonLexem);
                            _retDic[_lex].AddRange(_first);
                            break;

                        default:
                            break;
                        }
                        _revListProduct.Add(_lex);
                    }
                }
            }

            // 3
            bool _added = true;

            while (_added)
            {
                _added = false;
                foreach (cLexem _nonTerminal in _retDic.Keys)
                {
                    foreach (cProduction _production in _nonTerminal.cp_ListProducts)
                    {
                        int           _count          = _production.cp_RightPart.Count - 1;
                        List <cLexem> _revListProduct = new List <cLexem>();
                        bool          _break          = false;      //?
                        for (int i = _count; i >= 0; i--)
                        {
                            cLexem _lex = _production.cp_RightPart[i];
                            switch (_lex.cp_Type)
                            {
                            case eLexType.NonTerminal:
                                cSet <cLexem> _first = cm_First(_revListProduct);
                                if (_first.Contains(cLexem.cc_EpsilonLexem) | (i == _count))
                                {
                                    //_production.cp_Root.cm_First(_first);
                                    //_first.UnionWith(_production.cp_Root.cp_FirstCache);
                                    _first.Remove(cLexem.cc_EpsilonLexem);
                                    _first.UnionWith(_retDic[_nonTerminal]);
                                }
                                _added |= _retDic[_lex].AddRange(_first);
                                break;

                            case eLexType.Action:
                                break;

                            default:
                                _break = true;
                                break;
                            }
                            _revListProduct.Add(_lex);
                            if (_break)
                            {
                                break;
                            }
                        }
                    }
                }
            }

            return(_retDic);
        }