public static cProductInfo[] cm_getProductsByRoot(cLexem a_root, ref int a_Counter) { List<cProductInfo> _retLst = new List<cProductInfo>(); int _counterRoots = a_Counter; a_Counter += a_root.cp_ListProducts.Count; if (a_root.cp_ListProducts.ContainsKey(cLexem.cc_EpsilonLexem)) a_Counter--; foreach (KeyValuePair<cLexem, List<cLexem>> _kvp in a_root.cp_ListProducts) { // В список не добавляются пустые продукции if (_kvp.Key.cp_Type == eLexType.Epsilon) continue; cProductInfo _newPro = new cProductInfo(); _newPro.cf_root = new KeyValuePair<cLexem,int>(a_root, _counterRoots++); _newPro.cf_lstLexems = new List<KeyValuePair<cLexem, int>>(); int i = _kvp.Value.Count; foreach (cLexem _lex in _kvp.Value) { _newPro.cf_lstLexems.Add(new KeyValuePair<cLexem, int>(_lex, a_Counter++)); // Для последнего нетерминала if (--i == 0) { bool _flag = false; if (_lex.cp_Type == eLexType.NonTerminal) { foreach (cLexem _leadLex in _lex.cp_LeadLexems) if (_leadLex.cp_Type == eLexType.Epsilon) { _flag = true; break; } } if (_flag) { a_Counter++; } } } if (_kvp.Key.cp_Type == eLexType.NonTerminal) _newPro.cf_arrDirLexems = _newPro.cf_root.Key.cm_GetLeadLexems(_kvp.Key); else _newPro.cf_arrDirLexems = new cLexem[]{ _kvp.Key }; _retLst.Add(_newPro); } return _retLst.ToArray(); }
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; }
void cm_checkProducts(cProductInfo[] a_data) { int _count = a_data.Length; Dictionary<cLexem, cLexem> _dic = new Dictionary<cLexem, cLexem>(); for (int k = 0; k < _count; k++) { cProductInfo _info = a_data[k]; KeyValuePair<cLexem, int>[] _arrLexems = _info.cp_ArrLexems; int _lexCount = _arrLexems.Length; bool _clearDic = true; for (int j = 0; j < _lexCount; j++) { if (_clearDic) _dic.Clear(); _clearDic = true; cLexem _lexem = _arrLexems[j].Key; switch (_lexem.cp_Type) { case eLexType.Terminal: if (_dic.ContainsKey(_lexem)) throw new cNotLL1Exception(cLexem.cc_EpsilonLexem, cLexem.cc_EpsilonLexem, "Невозможно однозначно определить продукцию для символа " + _lexem.ToString() + " правой части " + _info.cp_Root.Key.ToString() + " из-за " + cLexem.cc_Epsilon + "-порождающих нетерминалов."); _dic.Add(_lexem, _lexem); break; case eLexType.NonTerminal: foreach (cLexem _lex in _lexem.cp_LeadLexems) { if (_lex.cp_Type == eLexType.Terminal) { if (_dic.ContainsKey(_lex)) throw new cNotLL1Exception(cLexem.cc_EpsilonLexem, cLexem.cc_EpsilonLexem, "Невозможно однозначно определить продукцию для символа " + _lex.ToString() + " правой части " + _info.cp_Root.Key.ToString() + " из-за " + cLexem.cc_Epsilon + "-порождающих нетерминалов."); _dic.Add(_lex, _lex); } else if (_lex.cp_Type == eLexType.Epsilon) { _clearDic = false; } } break; case eLexType.Epsilon: _clearDic = true; break; } } } }