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