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