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;
 }
 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;
 }
 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>();
     }
 }
        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;
        }
        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;
        }
 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;
 }
 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);
 }
 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;
 }
        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;
        }
 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;
 }
 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;
 }
 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;
 }