-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLCFG LFA.cpp
179 lines (156 loc) · 5.23 KB
/
LCFG LFA.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include "prelucrareInputCFG.h";
#include "validareInputCFG.h";
#include <iostream>
#include <random>
#include <string>
using namespace std;
int gasireCratimaN(vector <string> vector, int n) // functie care gaseste al n lea "-" dintr-un vector
{
int cont = 0;
for(int i = 0; i < vector.size(); i++)
{
if (vector[i] == "-")
cont++;
if(cont == n)
return i;
}
return -1;
}
bool existaFisier(const string& numeFisier) // functie care verifica daca fisierul exista in folder
{
ifstream file(numeFisier);
return file.good();
}
int main()
{
int aplicatReguli = 0; // pt loop infinit
bool afisatMesajProcesare = false; // pt loop infinit
string numeFisier;
while (true) // citirea numelui fisierului de intrare
{
try
{
cout << "\nIntroduceti numele fisierului de intrare (numele fisierului deja creat in acest proiect este cfgInput.txt): ";
getline(cin, numeFisier);
if (!existaFisier(numeFisier))
throw invalid_argument("\nFisierul nu exista in folder.\n");
break;
}
catch (exception& e)
{
cout << e.what();
}
catch (...)
{
cout << "\nEroare necunoscuta.\n";
}
}
bool fisierValid = false;
fisierValid = validareFisier(numeFisier); // validare fisier
if (fisierValid) // daca fisierul este valid, se incarca continutul si se prelucreaza
{
vector <string> content = loadFile(numeFisier);
vector <string> sectionList = getSectionList(content);
string headerVariabile, headerReguli, headerAlfabet;
for (int i = 0; i < sectionList.size(); i++) // extragere header variabile, reguli si alfabet prin intermediul ultimului caracter
{
if (sectionList[i][sectionList[i].size() - 1] == 'V')
{
headerVariabile = sectionList[i];
break;
}
}
for (int i = 0; i < sectionList.size(); i++)
{
if (sectionList[i][sectionList[i].size() - 1] == 'R')
{
headerReguli = sectionList[i];
break;
}
}
for (int i = 0; i < sectionList.size(); i++)
{
if (sectionList[i][sectionList[i].size() - 1] == 'A')
{
headerAlfabet = sectionList[i];
break;
}
}
vector <string> variabile = getSectionContent(content, headerVariabile); // extragere continut variabile, reguli si alfabet
vector <string> reguli = getSectionContent(content, headerReguli);
vector <string> alfabet = getSectionContent(content, headerAlfabet);
string start;
for (int i = 1; i < variabile.size(); i++) // gasirea variabilei de start
{
if (variabile[i] == "*")
start = variabile[i - 1];
}
random_device rd; // generare random a unui int care apartine [1, nrReguli], nrReguli este inserat in vectorul reguli pe ultima pozitie
mt19937 gen(rd());
int nrReguli = stoi(reguli[reguli.size() - 1]);
uniform_int_distribution<> dis(1, nrReguli);
reguli.pop_back(); // scoatem nrReguli din vectorul de reguli eoarece nu mai avem nevoie de el
vector <string> rez;
rez.push_back(start); // adaugam variabila de start in vectorul rezultat
bool rezEsteVar, gasitRegula;
int random, index;
for (int i = 0; i < rez.size(); i++)
{
rezEsteVar = false;
for (int j = 0; j < variabile.size(); j++) // verficam daca rez[i] este variabila
{
if (rez[i] == variabile[j])
{
rezEsteVar = true;
break;
}
}
if (rezEsteVar) // daca rez[i] este variabila, cautam o regula random care sa aiba variabila respectiva pe partea stanga, daca regula selectata random nu are variabila pe partea stanga, cautam alta regula tot random
{
gasitRegula = false;
while (gasitRegula == false) // o regula are pe al doilea element cratima
{
random = dis(gen);
index = gasireCratimaN(reguli, random); //functie care gaseste al n lea "-" dintr-un vector, unde n este repr de var random
if (reguli[index - 1] == rez[i])
gasitRegula = true;
}
index++; // indexul este mutat cu 1 pentru a nu lua in considerare cratima
vector <string> aux; // vector auxiliar in care se stocheaza elementele regulei selectate random care vor inlocui variabila din vectorul rezultat
while (reguli[index] != "-") // adaugam elementele regulei selectate random in vectorul auxiliar
{
aux.push_back(reguli[index]);
if (index == reguli.size() - 3)
aux.push_back(reguli[index + 1]);
index++;
if (reguli[index + 1] == "-")
break;
}
rez.erase(rez.begin() + i); // stergem variabila din vectorul rezultat
for (int a = aux.size() - 1; a >= 0; a--) // adaugam elementele regulei selectate random in vectorul rezultat
rez.insert(rez.begin() + i, aux[a]);
aplicatReguli++;
if (aplicatReguli > 3000 && !afisatMesajProcesare) // afisare mesaj de procesare in cazul in care aplicam reguli de 3000 de ori
{
cout << "\nProcesare CFG...\n";
afisatMesajProcesare = true;
}
if (aplicatReguli > 10000) // oprire program in cazul in care aplicam reguli de 10.000 de ori, cel mai probabil semnifica un loop infinit
{
cout << "\nProgramul a fost oprit deoarece s-au aplicat mai mult de 10.000 reguli.\n";
cout << "Cel mai probabil exista o variabila care nu are cel putin o regula care contine doar litere din alfabet.\n";
return 0;
}
}
else
{
continue;
}
}
cout << "\nRezultatul este: ";
for (int i = 0; i < rez.size(); i++) // afisare rezultat
cout << rez[i];
}
cout << endl;
return 0;
}