public void EliminareRecursivitateStanga()
        {
            // Indice pentru lista regulilor de productie
            int it = 0;
            // Facem o copie la lista regulilor de productie
            List <ReguliDeProductie> cReguliProductie = new List <ReguliDeProductie>();

            bool[] arr = new bool[_reguliProductie.Count];
            Array.Clear(arr, 0, arr.Length);

            // Indicele nu trebuie sa depaseasca numarul regulilor de productie
            while (it < _reguliProductie.Count)
            {
                // Se determina toate regulile de produtie corespunzatoare unui neterminal
                ReguliDeProductie regula = _reguliProductie[it];
                IEnumerable <ReguliDeProductie> results = _reguliProductie.Where(s => s.GetLeft() == regula.GetLeft());

                // Se salveaza rezultatul intr-o lista
                List <ReguliDeProductie> rList = results.ToList();

                // Numarul regulilor de productie corespunzatoare aceluiasi neterminal
                int counter = rList.Count;
                CheckLeftRecv(rList, it, cReguliProductie, arr);
                it = it + counter;
            }
            _reguliProductie.Clear();
            _reguliProductie = new List <ReguliDeProductie>(cReguliProductie);
            pNr = _reguliProductie.Count;
        }
        public void EliminareReguliIdentice()
        {
            // Indice pentru lista regulilor de productie
            int it = 0;

            // Facem o copie la lista regulilor de productie
            List <ReguliDeProductie> cReguliProductie = new List <ReguliDeProductie>();

            bool[] arr = new bool[_reguliProductie.Count];
            Array.Clear(arr, 0, arr.Length);

            // Indicele nu trebuie sa depaseasca numarul regulilor de productie
            while (it < _reguliProductie.Count)
            {
                // Se determina toate regulile de produtie corespunzatoare unui neterminal
                ReguliDeProductie regula = _reguliProductie[it];
                IEnumerable <ReguliDeProductie> results = _reguliProductie.Where(s => s.GetLeft() == regula.GetLeft());

                // Se salveaza rezultatul intr-o lista
                List <ReguliDeProductie> rList = results.ToList();

                // Numarul regulilor de productie corespunzatoare aceluiasi neterminal
                int counter = rList.Count;

                // Functie care elimina regulile de productie care incep la fel
                CheckElements(rList, it, cReguliProductie, arr);

                // Se trece la contorizarea urmatorului set de reguli de productie pentru urmatorul neterminal
                it = it + counter;
            }

            _reguliProductie.Clear();
            _reguliProductie = new List <ReguliDeProductie>(cReguliProductie);
            pNr = _reguliProductie.Count;
        }
        private void InitRegProd(string[] reguliProd)
        {
            ReguliDeProductie x = new ReguliDeProductie();

            x.SetLeft(reguliProd[0]);
            x.InitializeRightPartOfExistingRules(reguliProd);
            _reguliProductie.Add(x);

            Console.WriteLine();
        }
        public void AddMethods(Gramatica gramatica)
        {
            List <CodeMemberMethod> methodList = new List <CodeMemberMethod>();

            for (int i = 0; i < gramatica.Neterminale.Count; i++)
            {
                CodeMemberMethod tmp = new CodeMemberMethod
                {
                    Attributes = MemberAttributes.Private | MemberAttributes.Static,
                    Name       = gramatica.Tab.Rows[i][0].ToString(),
                    ReturnType = new CodeTypeReference(typeof(void)),
                };
                targetClass.Members.Add(tmp);
                CodeSnippetExpression methodValue = new CodeSnippetExpression();
                for (int j = 1; j <= gramatica.Terminale.Count + 1; j++)
                {
                    ReguliDeProductie regula = gramatica.Tab.Rows[i][j] as ReguliDeProductie;
                    if (regula != null)
                    {
                        methodValue.Value += $"if( inputArrayString[stringIndex] == \"{gramatica.Tab.Columns[j].Caption}\" )\n" +
                                             "{\n";

                        if (regula.GetRight().Count() >= 1 && regula.GetRight()[0] != "")
                        {
                            foreach (var symbol in regula.GetRight())
                            {
                                if (gramatica.Neterminale.Contains(symbol))
                                {
                                    methodValue.Value += $"{symbol}();\n";
                                }
                                if (gramatica.Terminale.Contains(symbol))
                                {
                                    methodValue.Value += "stringIndex++;\n";
                                }
                            }
                        }
                        methodValue.Value += "return;\n";

                        methodValue.Value += "}\n";
                    }
                }

                methodValue.Value += $"else\nthrow new Exception($\"Caracter invalid la pozitia {{ stringIndex }}\");\n";
                tmp.Statements.Add(new CodeSnippetStatement(methodValue.Value));
            }
        }
        private void CheckLeftRecv(List <ReguliDeProductie> rList, int index, List <ReguliDeProductie> cReguliProductie, bool[] checkArr)
        {
            for (int i = 0; i < rList.Count; i++)
            {
                int    contor = rList[i].GetRight().Length;
                string first  = rList[i].GetRight().FirstOrDefault();
                if (rList[i].GetLeft() == first)
                {
                    if (rList.Count < 2)
                    {
                        Console.WriteLine("Imposibil de eliminar recursivitatea stanga!");
                        break;
                    }

                    int l_contor = rList[i].GetRight().Length;

                    // Introducem 2 reguli de productie noi
                    ReguliDeProductie newRule1 = new ReguliDeProductie();
                    ReguliDeProductie newRule2 = new ReguliDeProductie();

                    // Ambele reguli de productie vor fi pentru acelasi neterminal
                    newRule1.SetLeft(rList[i].GetLeft().ToString() + 'x');
                    newRule2.SetLeft(rList[i].GetLeft().ToString() + 'x');


                    // Se adauga noul neterminal in lista
                    _neterminale.Add(newRule1.GetLeft());

                    // Initializare prima regula de productie introdusa
                    string[] right_1 = rList[i].GetRight().Reverse().Take(l_contor - 1).Reverse().ToArray();
                    newRule1.SetRight(Helper.Concatenate(right_1, newRule1.GetLeft()));


                    // Initializare a doua regula de productie introdusa
                    string[] right_2 = new string[] { };
                    newRule2.SetRight(right_2);



                    // Introducem noile reguli de productie in lista
                    cReguliProductie.Add(newRule1);
                    cReguliProductie.Add(newRule2);

                    ReguliDeProductie newRule0 = new ReguliDeProductie();
                    newRule0.SetLeft(rList[i].GetLeft());

                    // Aplicam prima parte a regulii de eliminare a recursivitatii
                    if (i == rList.Count - 1)
                    {
                        string[] right = rList[i - 1].GetRight().Take(1).Select(ind => ind.ToString()).ToArray();
                        string[] str   = Helper.Concatenate(right, newRule1.GetLeft());
                        newRule0.SetRight(str);

                        //_reguliProductie.RemoveAt(index + i - 1);
                        if (checkArr[index + i - 1] == false)
                        {
                            checkArr[index + i - 1] = true;
                        }
                    }
                    else
                    if (i < rList.Count - 1)
                    {
                        string[] right = rList[i + 1].GetRight().Take(1).Select(ind => ind.ToString()).ToArray();
                        string[] str   = Helper.Concatenate(right, newRule1.GetLeft());
                        newRule0.SetRight(str);

                        if (checkArr[index + i + 1] == false)
                        {
                            checkArr[index + i + 1] = true;
                        }
                        //_reguliProductie.RemoveAt(index + i + 1);
                    }
                    cReguliProductie.Add(newRule0);
                    checkArr[index + i] = true;
                }
            }

            for (int i = 0; i < rList.Count; i++)
            {
                if (checkArr[index + i] == false)
                {
                    cReguliProductie.Add(rList[i]);
                    checkArr[index + i] = true;
                }
            }
        }
        private void CheckElements(List <ReguliDeProductie> rList, int index, List <ReguliDeProductie> cReguliProductie, bool[] checkArr)
        {
            // Contor utiliat in denumirea noilor neterminale
            int contor = 0;

            // Fiecare regula de productie specifica aceluiasi neterminal
            for (int i = 0; i < rList.Count; i++)
            {
                for (int j = i + 1; j < rList.Count; j++)
                {
                    // Se compara inceputul partii drepte a regulii de productie cu cel al urmatoarelor neterminale
                    int NumberOfCommonElements = Helper.Compare(rList[i].GetRight(), rList[j].GetRight());

                    // Daca se gaseste cel putin un element comun
                    if (NumberOfCommonElements != 0)
                    {
                        contor++;

                        // Doua reguli pentru A1
                        ReguliDeProductie newElement1 = new ReguliDeProductie();
                        ReguliDeProductie newElement2 = new ReguliDeProductie();


                        // Se seteaza partea stanga a celor doua reguli corespunzatoare neterminalului A1
                        newElement1.SetLeft(rList[i].GetLeft() + contor.ToString());
                        newElement2.SetLeft(rList[i].GetLeft() + contor.ToString());

                        // Se adauga A1 in lista de neterminale
                        _neterminale.Add(newElement1.GetLeft());

                        // Se seteaza partea dreapta a primei reguli corespunzatoare lui A1
                        string[] right_1 = rList[i].GetRight().Reverse().Take(rList[i].GetRightPartNumberOfElements() - NumberOfCommonElements).Reverse().ToArray();
                        newElement1.SetRight(right_1);

                        // Se seteaza partea dreapta pentru a doua regula corespunzatoare lui A1
                        string[] right_2 = rList[j].GetRight().Reverse().Take(rList[j].GetRightPartNumberOfElements() - NumberOfCommonElements).Reverse().ToArray();
                        newElement2.SetRight(right_2);

                        //// Adauugam cele doua reugli de productie la lista
                        cReguliProductie.Add(newElement1);
                        cReguliProductie.Add(newElement2);

                        // Se ia partea comuna a celor coua reguli (a)
                        string[] right = rList[i].GetRight().Take(NumberOfCommonElements).ToArray();

                        // Se concateneaza cu neterminalul introdus (A1)
                        ReguliDeProductie newElement0 = new ReguliDeProductie();
                        newElement0.SetLeft(rList[i].GetLeft());
                        newElement0.SetRight(Helper.Concatenate(right, newElement1.GetLeft()));

                        // Se adauga noua regula de productie in lista
                        cReguliProductie.Add(newElement0);

                        // se bifeaza regula de productie folosita din sirul original
                        checkArr[index + i] = true;

                        // Se elimina A -> ac
                        if (checkArr[index + j] == false)
                        {
                            //_reguliProductie.RemoveAt(index + j);
                            checkArr[index + j] = true;
                        }
                    }
                }
                if (checkArr[index + i] == false)
                {
                    cReguliProductie.Add(rList[i]);
                    checkArr[index + i] = true;
                }
            }
        }