-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
396 lines (341 loc) · 12.4 KB
/
main.c
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // strlen fonskiyonu kullanıldı.
#include <time.h> // Rastgele sayı üretmek için kullanıldı
#include <math.h> // sadece pow fonskiyonu kullanıldı
#define Split 256
#define Match 257
typedef struct State state;
typedef struct Fragmentation frag;
typedef struct PointerList ptr_list;
typedef struct StateList list;
struct State {
int c;
state *out;
state *out1;
int lastlist; //Diyagramı dolaşırken işimize yarayacak.
};
struct Fragmentation {
state *start;
ptr_list *outs;
};
struct PointerList {
state **out;
ptr_list *next;
};
struct StateList {
state **states;
int count;
};
//Global variables...
state matchState = {Match, NULL, NULL};
list l1 = {NULL, 0};
list l2 = {NULL, 0};
int listid = 0;
// Building NFA
state* createState(int c, state *out, state *out1);
frag createFrag(state* start, ptr_list *outs);
ptr_list* createList(state** out);
ptr_list* append(ptr_list* l1, ptr_list* l2);
void patch(ptr_list* l1, state* s);
state* nfaBuilder(char* postfix);
// Word Controls
int checkWord(state* start, char* word);
int isMatch(list *l);
void addState(list *l, state *s, int* listid);
list* startList(state *s, list* l, int* listid);
void Step(list* clist, int c, list* nlist);
//Convert infix to postfix
char* convertToPostfix(char* infix);
// Word production
void wordProduction(char* alphabet, int numberOfWords, state* start);
char* separateAlphabet(char* alphabet);
int main() {
srand(time(NULL));
char p[1000], alphabet[40];
int control = 1, numberOfWords = 0;
l1.states = malloc(sizeof(state*));
l2.states = malloc(sizeof(state*));
printf("Lütfen üzerinde çalışılacak alfabeyi giriniz: Not: alfabeyi a,b,c,d şeklinde girin.\n");
scanf("%s", alphabet);
printf("Lütfen işlenecek infix ifadeyi giriniz: \n");
scanf("%s", p);
char* postfix = convertToPostfix(p);
printf("İşlenecek olan postfix ifade: %s\n", postfix);
state *start = nfaBuilder(postfix);
printf("Ne işlemi yapmak istiyorsunuz?\n 1-Verdiğim kurala göre belli sayıda kelime üretmek istiyorum\n 2-Verdiğim kelimenin bu dile ait olup olmadığını öğrenmek istiyorum.\n");
printf("Lütfen 1 yada 2 numaralı tuşa basınız...\n");
scanf("%d", &control);
switch (control) {
case 1:
printf("Dile ait kaç kelime görmek istiyorsunuz?");
scanf("%d", &numberOfWords);
wordProduction(alphabet, numberOfWords, start);
break;
case 2:
while (control) {
printf("Lütfen kontrol etmek istediğiniz kelimeyi giriniz:\n");
scanf("%s",p);
int result = checkWord(start, p);
if (result == 1) printf("Evet bu kelime ilgili dile ait bir kelimedir: %s\n",p);
else printf("Bu kelime ilgili dile ait değildir! %s\n",p);
printf("Çıkmak için 0'e basiniz:\n");
scanf("%d", &control);
}
break;
default:
printf("Yanlış bir tuşlama yaptınız. Doğru tuşlama yapmayı öğrenene kadar lütfen programı kullanmayın!");
break;
}
free(start);
return 0;
}
ptr_list* createList(state** out) {
ptr_list* list = malloc(sizeof(ptr_list));
list->out = out;
list->next = NULL;
return list;
}
/// İkinci parametre'de gelen listeyi ilk listenin sonuna ekler / Adds the list from the second parameter to the end of the first list
/// @param l1
/// @param l2
/// @return A new merged list
ptr_list* append(ptr_list* l1, ptr_list* l2) {
if(l1 == NULL) return l2;
ptr_list *ptr = l1;
while (ptr->next != NULL) ptr = ptr->next;
ptr->next = l2;
return l1;
}
/// Parametre olarak aldığı pointer listesini ki bu boşta kalan okları temsil eder, bunları belirtilen state'e bağlar.
/// @param l1 Bağlanacak okları tutan liste
/// @param s Bağlanılacak state
void patch(ptr_list* l1, state* s) {
if(l1 == NULL) return; //Liste boş olması durumda bağlanacak ok yoktur.
while (l1 != NULL) {
*(l1->out) = s; //Artık ilgili ok bir adresi gösteriyor. Önceden null bir değeri gösteriyordu.
l1 = l1->next;
}
free(l1); //Liste artık kullanılmayacak.
}
/// Yeni bir state oluşturur.
/// @param c state'den çıkan yolun değerini belirler.
/// @param out ilgili state'den çıkan birinci oku tutar.
/// @param out1 ilgili state'den çıkan ikinci oku tutar.
/// @return
state* createState(int c, state* out, state* out1) {
state* s = malloc(sizeof(state));
s->c = c;
s->out = out;
s->out1 = out1;
return s;
}
/// İlgili nfa grafının/diyagramının başlangıç düğümünü ve boşta sallanan oklarını tutan bir fragment oluşturur.
/// @param start
/// @param outs
/// @return Bir fragment döner. Fragmentlar küçük nfa diyagramlarıdır/graflarıdır..
frag createFrag(state* start, ptr_list* outs) {
frag fragment = {start, outs};
return fragment;
}
/// Epsilon yollarıda içeren bir nfa diyagramı oluşturur.
/// @param postfix bir postfi ifadeye göre işlem yapar.
/// @return Nfa diyagramının başlangıç state'ini döner.
state* nfaBuilder(char* postfix) {
char *p; // Pointer for the postfix exp.
// Kullanılacak veri yapıları
frag stack[1000], *stackp, e1, e2;
state* s;
//Stack func.
#define Push(s) *stackp++ = s;
#define Pop() *--stackp;
stackp = stack;
for (p = postfix; *p; p++) {
switch (*p) {
case '+':
// e1 ve e2 birer fragmenttır. + işareti veya anlamı katar.
// Yani fragmentlerdan herhangi birisine geçiş yapabiliriz. Bunu ifade etmek için de split durumunda bir state oluşturalım.
e2 = Pop(); //İlk çıkanın e2 ye atanması postfix ifadenin okunması durumda oluşan sıradan kaynaklanmaktadır.
e1 = Pop();
s = createState(Split, e1.start, e2.start); //Split durumda state oluşturuldu.
Push(createFrag(s, append(e1.outs, e2.outs))); // Fragment oluşturulur ve state içine itilir.
//append fonksiyonu iki fragment çıkış oklarını tek bir liste olarak geri döner.
break;
case '*':
e1 = Pop();
s = createState(Split, e1.start, NULL);
patch(e1.outs, s);
Push(createFrag(s, createList(&s->out1)));
break;
case '.':
// Yeni bir state ihtiyaç yoktur. İlgili fragmentları sıraya göre birbirine bağlar. Bağlama işlemi boşta olan oklar ile yapılır.
e2 = Pop();
e1 = Pop();
patch(e1.outs, e2.start);
Push(createFrag(e1.start, e2.outs));
break;
default:
s = createState(*p, NULL, NULL);
Push(createFrag(s, createList(&s->out)));
break;
}
}
// Stack içinde kalan son fragment parçası tüm kurallı yolları oluşturulmuş bir nfa diyagramı içerir. Buda sallanan oklarının herhangi bir state
// bağlanma zorunluluğu olmadığını gösterir. Bunun anlamı ise bu oklar final state bağlanması gerekir.
e1 = Pop();
patch(e1.outs, &matchState); //Okları önceden tanımlanmış matchState'e bağlar.
return e1.start;
}
int checkWord(state* start, char* word) {
if (word == NULL) return 0;
list *clist, *nlist, *t;
clist = startList(start, &l1, &listid);
nlist = &l2;
for(; *word; word++) {
Step(clist, *word, nlist);
t = clist;
clist = nlist;
nlist = t;
if (clist->count == 0) return 0; // refactoring for performance...
}
return isMatch(clist);
}
int isMatch(list *l) {
for (int i = 0; l->count > i; i++) {
if(l->states[i] == &matchState) return 1;
}
return 0;
}
void addState(list *l, state *s, int* listid) {
if(s == NULL || s->lastlist == *listid) return;
s->lastlist = *listid;
if(s->c == Split) {
addState(l, s->out,listid);
addState(l, s->out1, listid);
return;
}
l->states[l->count++] = s;
}
list* startList(state *s, list* l, int* listid) {
(*listid)++;
l->count = 0;
addState(l,s, listid);
return l;
}
// Kısaca ilgili yürütme işlemi yapar. Yani ilgli durumdan geçilebilecek durumları hesaplar ve bunları nlist içine atar.
void Step(list* clist, int c, list* nlist) {
state *s;
listid++;
nlist->count = 0;
for(int i = 0; i < clist->count; i++) {
s = clist->states[i];
if(s->c == c)
addState(nlist, s->out, &listid);
}
}
char* convertToPostfix(char* infix) {
char stack[1000];
int stack_counter = -1;
int letter_counter = 0;
char *postfix = (char*)malloc(1000 * sizeof(char));
char *ptr = postfix;
for (;*infix; infix++) {
char temp = *infix;
switch (temp) {
case '+':
while (stack_counter != -1 && stack[stack_counter] == '.' || stack[stack_counter] == '*' || stack_counter == '+') {
*ptr++ = stack[stack_counter--];
}
stack[++stack_counter] = temp;
letter_counter = 0;
break;
case '*':
while (stack_counter != -1 && stack[stack_counter] == '*'){
*ptr++ = stack[stack_counter--];
}
stack[++stack_counter] = temp;
break;
case ')':
while (stack[stack_counter] != '(') *ptr++ = stack[stack_counter--];
stack_counter--;
letter_counter++;
break;
case '(':
if (letter_counter >= 1) {
while (stack_counter != -1 && (stack[stack_counter] == '.' || stack[stack_counter] == '*'))
*ptr++ = stack[stack_counter--];
stack[++stack_counter] = '.';
letter_counter = 0;
}
stack[++stack_counter] = '(';
break;
default:
letter_counter++;
if(letter_counter >= 2) {
while (stack_counter != -1 && (stack[stack_counter] == '.' || stack[stack_counter] == '*'))
*ptr++ = stack[stack_counter--];
stack[++stack_counter] = '.';
letter_counter--;
}
*ptr++ = temp;
break;
}
}
if (stack_counter != -1) {
for (; stack_counter > -1; stack_counter--) {
*ptr++ = stack[stack_counter];
}
}
*ptr = '\0';
return postfix;
}
char* separateAlphabet(char* alphabet) {
char* setOfAlphabet = malloc(40 * sizeof(char));
for (int i = 0; strlen(alphabet) > i; i++) {
if (alphabet[i] == ',') continue;
char temp[2];
temp[0] = alphabet[i];
temp[1] = '\0';
strcat(setOfAlphabet, temp);
}
return setOfAlphabet;
}
int isWordInArray(char** words, int count, const char* word) {
for (int i = 0; i < count; i++) {
if (strcmp(words[i], word) == 0) {
return 1; // Kelime bulundu
}
}
return 0; // Kelime bulunamadı
}
void wordProduction(char* alphabet, int numberOfWords, state* start) {
char* setOfAlphabet = separateAlphabet(alphabet);
char word[100] = "";
char** words = (char**)malloc((numberOfWords + 1) * sizeof(char*));
char** wordsp = words;
int generatedCount = 0;
for (int i = 1; numberOfWords > 0; i++) {
int calculated = (int)pow((int)strlen(setOfAlphabet), i) * i;
for (int j = 0; calculated > j; j++) {
if (numberOfWords <= 0) break;
char temp[2];
temp[0] = setOfAlphabet[rand() % (int)strlen(setOfAlphabet)];
temp[1] = '\0';
strcat(word, temp);
if (i == strlen(word)) {
if (checkWord(start, word) && !isWordInArray(words, generatedCount, word)) {
for (int k = 0; k < strlen(words);k++) {
}
printf("%s\n", word);
numberOfWords--;
*wordsp = (char*)malloc((strlen(word) + 1) * sizeof(char));
strcpy(*wordsp, word);
wordsp++;
generatedCount++;
}
word[0] = '\0';
}
}
}
free(words);
}