source: icGREP/icgrep-devel/icgrep/combine/regexgen.cpp @ 5516

Last change on this file since 5516 was 5516, checked in by faldebey, 21 months ago

added combinatorial testing tool

File size: 15.0 KB
Line 
1#include "regexgen.h"
2#include "stringGen.h"
3
4#include <string>
5#include <vector>
6#include <fstream>
7#include <boost/algorithm/string/split.hpp>
8#include <iostream>
9#include <algorithm>
10
11#include <stdlib.h>
12#include <time.h> 
13#include <stdio.h>
14#include <re/re_diff.h>
15#include <re/re_any.h> 
16#include <re/re_parser.h>
17
18
19using namespace std;
20
21
22
23class CC {
24        std::vector<string> ccList;
25        std::vector<string> usedCC;
26public:
27        CC(std::vector<string> header, std::vector<string> row, re::RE_Syntax syntax){
28                RegexGen reGen(syntax);
29                ccList = reGen.parseCC(header, row);
30
31        }
32
33        std::string getCC(){
34
35                int random;
36                std::string cc;
37                if (!ccList.empty()){
38                        random = rand() % ccList.size();
39                        cc = ccList[random];
40                        ccList.erase(ccList.begin()+random);
41                        usedCC.push_back(cc);
42                        return cc;
43                }
44                else {
45                        random = rand() % usedCC.size();
46                        cc = usedCC[random];
47                        return cc;
48                }
49        }
50        std::string changeCC(std::string cc){
51                std::string newCC;
52                int random;
53                if (!ccList.empty()){
54                        random = rand() % ccList.size();
55                        newCC = ccList[random];
56                        ccList.erase(ccList.begin()+random);
57                        usedCC.push_back(newCC);
58                }
59                else {
60                        random = rand() % usedCC.size();
61                        newCC = usedCC[random];
62                }
63                ccList.push_back(cc);
64                return newCC;
65        }
66        std::vector<string> getRemainingCC(){
67                return ccList;
68        }
69        bool isEmpty(){
70                return ccList.empty();
71        }
72};
73
74RegexGen::RegexGen(std::vector<string> header, std::vector<string> row){
75        syntax = setSyntax(header, row);
76        RE = parseRE(header, row);
77        flags = parseFlags(header, row);
78}
79
80string RegexGen::stringifyLine(vector<string> elements, string separator){
81        string line = "";
82        bool sep = false;
83        for (auto e : elements){
84                line += sep? separator + e : e;
85                sep = true;
86        }
87        return line;
88}
89
90string RegexGen::getBoundary(){
91        return "\\b";
92}
93string RegexGen::getNotBoundary(){
94        return "\\B";
95}
96string RegexGen::getWord(){
97        if (syntax == re::RE_Syntax::BRE){
98                return "w";
99        }
100        else return "\\w";
101}
102string RegexGen::getNotWord(){
103        if (syntax == re::RE_Syntax::BRE){
104                return "notWord";
105        }
106        else return "\\W";
107}
108string RegexGen::getWhitespace(){
109        return "\\s";
110}
111string RegexGen::getNotWhitespace(){
112        return "\\S";
113}
114string RegexGen::getTab(){
115        if (syntax == re::RE_Syntax::BRE){
116                return "t";
117        }
118        else return "\\t";
119}
120string RegexGen::getDigit(){
121        if (syntax == re::RE_Syntax::BRE){
122                return "d";
123        }
124        else return "\\d";
125}
126string RegexGen::getNotDigit(){
127        if (syntax == re::RE_Syntax::BRE){
128                return "D";
129        }
130        else return "\\D";
131}
132string RegexGen::getAny(){
133        return ".";
134}
135string RegexGen::getPosix(string value){
136        return "[[:" + value + ":]]";
137}
138std::string RegexGen::getUnicode(){
139        if (syntax == re::RE_Syntax::ERE) {
140                std::vector<string> ucd;
141                ifstream file;
142                file.open("../icgrep/combine/Unicode.txt");
143                string line;
144                while(getline(file, line)){
145                        ucd.push_back(line);
146                }
147                file.close();
148                int random = rand() % ucd.size();
149                return "\\u" + ucd[random];
150        }
151        else {
152                return "u";
153        }
154}
155std::string RegexGen::getList(){
156        if (syntax == re::RE_Syntax::BRE) {
157                return "l";
158        }
159        else {
160                const char *l[] = {"[abc]","[XYZ]","[123]","[àŠ¹à§àŠ¯àŠŸàŠ²à§‹]"};
161                std::vector<string> lists (l, l + sizeof(l) / sizeof(l[0]));
162                int random = rand() % lists.size();
163                return lists[random];
164        }
165       
166}
167std::string RegexGen::getNList(){
168        if (syntax == re::RE_Syntax::BRE) {
169                return "L";
170        }
171        else {
172                std::vector<string> lists = {"[^abc]","[^XYZ]","[^123]","[^àŠ¹à§àŠ¯àŠŸàŠ²à§‹]"};
173                int random = rand() % lists.size();
174                return lists[random];
175        }
176}
177std::string RegexGen::getRange(){
178        if (syntax == re::RE_Syntax::BRE) {
179                return "r";
180        }
181        else {
182                std::vector<string> lists = {"[a-zA-Z0-9]","[A-Za-z]","[0-9]","[ا-ي]"};
183                int random = rand() % lists.size();
184                return lists[random];
185        }
186}
187std::string RegexGen::getPropertyValue(){
188        std::vector<string> property = {"Common", "Latin", "Greek", "Cyrillic",
189                                                        "Armenian", "Hebrew", "Arabic", "Syriac", 
190                                                        "Thaana", "Devanagari", "Bengali", "Gurmukhi", 
191                                                        "Gujarati", "Oriya", "Tamil", "Telugu", "Kannada"};
192        int random = rand() % property.size();
193        return property[random];
194}
195std::string RegexGen::getProperty(){
196        if (syntax == re::RE_Syntax::BRE) {
197                return "p";
198        }
199        else {
200                return "\\p{" + getPropertyValue() + "}" ;
201        }
202}
203std::string RegexGen::getNotProperty(){
204        if (syntax == re::RE_Syntax::BRE) {
205                return "P";
206        }
207        else {
208                return "\\P{" + getPropertyValue() + "}" ;
209        }
210}
211std::string RegexGen::getName(){
212        if (syntax == re::RE_Syntax::ERE) {
213                return "\\N{" + getPropertyValue() + "}" ;
214        }
215        else {
216                return "N";
217        }
218}
219string RegexGen::getZeroOrOne(string cc){
220        if (syntax == re::RE_Syntax::BRE) {
221                return cc+ "\\?";
222        }
223        else {
224                return cc + "?" ;
225        }
226}
227string RegexGen::getZeroOrMore(string cc){
228                return cc + "*" ;
229}
230string RegexGen::getOneOrMore(string cc){
231        if (syntax == re::RE_Syntax::BRE) {
232                return cc+ "\\+";
233        }
234        else {
235                return cc + "+" ;
236        }
237}
238string RegexGen::getRep(string cc, int rep){
239        if (syntax == re::RE_Syntax::BRE) {
240                return cc + "\\{" + to_string(rep) + "\\}";
241        }
242        else {
243                return cc + "{" + to_string(rep) + "}";
244        }
245}
246string RegexGen::getRep(string cc, int lb, int ub){
247        if (syntax == re::RE_Syntax::BRE) {
248                return cc + "\\{" + to_string(lb) + ',' + to_string(ub) + "\\}";
249        }
250        else {
251                return cc + "{" + to_string(lb) + ',' + to_string(ub) + "}";
252        }
253}
254string RegexGen::getRepMore(string cc, int rep){
255        if (syntax == re::RE_Syntax::BRE) {
256                return cc + "\\{" + to_string(rep) + ",\\}";
257        }
258        else {
259                return cc + "{" + to_string(rep) + ",}";
260        }
261}
262string RegexGen::getJoin(string LS, string RS){
263        if (syntax == re::RE_Syntax::BRE) {
264                return "\\(" + LS + "\\|" + RS + "\\)";
265        }
266        else {
267                return "(" + LS + "|" + RS + ")";
268        }
269}
270string RegexGen::getBackRef(string cc){
271        if (syntax == re::RE_Syntax::BRE) {
272                return "\\(" + cc + "\\)";
273        }
274        else {
275                return "(" + cc + ")";
276        }
277       
278}
279string RegexGen::getAssertionCoating(string cc){
280        if (cc.find("\\p{") == 0
281                || cc.find("\\P{") == 0
282                || cc.find("\\N{") == 0){
283                re::RE * re_ast = re::RE_Parser::parse(cc, 0);
284                StringGenerator strGen;
285                std::vector<string> set = strGen.generate(re_ast);
286                int random = rand() % set.size();
287                return set[random];
288        }
289        else {
290                return cc;
291        }
292}
293
294string RegexGen::getNegativeAssertionCoating(string cc){
295        re::RE * re_ast = re::RE_Parser::parse(cc, 0);
296        StringGenerator strGen;
297        std::vector<string> set = strGen.generate(re::makeDiff(re::makeAny(),re_ast));
298        int random = rand() % set.size();
299        return set[random];
300}
301string RegexGen::getLookAhead(string cc){
302        if (syntax == re::RE_Syntax::PCRE) {
303                std::string tail = getAssertionCoating(cc);
304                return "(?=" + cc + ")" + tail;
305        }
306        return "";
307}
308string RegexGen::getNegativeLookAhead(string cc){
309        if (syntax == re::RE_Syntax::PCRE) {
310                std::string tail = getNegativeAssertionCoating(cc);
311                return "(?!" + cc + ")" + tail;
312        }
313        return "";
314}
315string RegexGen::getLookBehind(string cc){
316        if (syntax == re::RE_Syntax::PCRE) {
317                std::string front = getAssertionCoating(cc);
318                return front + "(?<=" + cc + ")";
319        }
320        return "";
321}
322string RegexGen::getNegativeLookBehind(string cc){
323        if (syntax == re::RE_Syntax::PCRE) {
324                std::string front = getNegativeAssertionCoating(cc);
325                return front + "(?<!" + cc + ")";
326        }
327        return "";
328}
329
330
331bool RegexGen::usesCC(std::string op){
332        std::vector<string> set = {"zeroOrOne","zeroOrMore","oneOrMore","repeat_n","repeat_nm","repeat_n_more","repeat_m_less", 
333                                                        "backref", "join", "look_ahead", "mlook_ahead", "look_behind", "nlook_behind" "look_ahead", 
334                                                        "mlook_ahead", "look_behind", "nlook_behind"};
335
336        if(std::find(set.begin(), set.end(), op) != set.end()){
337                return true;
338        }
339        else return false;
340}
341
342re::RE_Syntax RegexGen::setSyntax(std::vector<string> header, std::vector<string> row){
343        int colnum = 0;
344        for(auto col : row){
345                if (header[colnum] == "syntax") {
346                        if (col == "-G"){
347                                return re::RE_Syntax::BRE;
348                        }
349                        else if (col == "-E"){
350                                return re::RE_Syntax::ERE;
351                        }
352                }
353                colnum++;
354        }
355        return re::RE_Syntax::PCRE;
356}
357
358
359
360std::vector<string> RegexGen::parseCC(std::vector<string> header, std::vector<string> row){
361        std::vector<string> ccList;
362
363        int colnum = 0;
364        for(auto col : row){
365                if (col != "false"){
366                        string cc;
367
368                        if (header[colnum] == "wordC") {
369                                cc = getWord();
370                                ccList.push_back(getWord());
371                        }
372                        else if (header[colnum] == "notWordC") {
373                                cc = getNotWord();
374                                ccList.push_back(getNotWord());
375                        }
376                        else if (header[colnum] == "whitespace") {
377                                cc = getWhitespace();
378                                ccList.push_back(getWhitespace());
379                        }
380                        else if (header[colnum] == "notWhitespace") {
381                                cc = getNotWhitespace();
382                                ccList.push_back(getNotWhitespace());
383                        }
384                        else if (header[colnum] == "tab") {
385                                cc = getTab();
386                                ccList.push_back(getTab());
387                        }
388                        else if (header[colnum] == "digit") {
389                                cc = getDigit();
390                                ccList.push_back(getDigit());
391                        }
392                        else if (header[colnum] == "notDigit") {
393                                cc = getNotDigit();
394                                ccList.push_back(getNotDigit());
395                        }
396                        else if (header[colnum] == "any") {
397                                cc = getWord();
398                                ccList.push_back(getAny());
399                        }
400                        else if (header[colnum] == "unicodeC"){
401                                cc = getUnicode();
402                                ccList.push_back(getUnicode());
403                        }
404                        else if (header[colnum] == "list"){
405                                cc = getList();
406                                ccList.push_back(getList());
407                        }
408                        else if (header[colnum] == "nList"){
409                                cc = getNList();
410                                ccList.push_back(getNList());
411                        }
412                        else if (header[colnum] == "range"){
413                                cc = getRange();
414                                ccList.push_back(getRange());
415                        }
416                        else if (header[colnum] == "posix"){
417                                // if (col != "off"){
418                                //      c = getPosix(col);
419                                //      if (!c.empty())
420                                //      ccList.push_back(getPosix(col));
421                                // }
422                        }
423                        else if (header[colnum] == "property") {
424                                cc = getProperty();
425                                ccList.push_back(getProperty());
426                        }
427                        else if (header[colnum] == "notProperty") {
428                                cc = getProperty();
429                                ccList.push_back(getNotProperty());
430                        }
431                        else if (header[colnum] == "nameProperty") {
432                                cc = getName();
433                                ccList.push_back(getName());
434                        }
435                }
436                ++colnum;
437        }
438        return ccList;
439}
440
441std::string RegexGen::parseRE(std::vector<string> header, std::vector<string> row){
442        srand (time(NULL));
443        std::vector<string> fullRE;
444        std::vector<string> assertions;
445        CC ccHandler(header,row, syntax);
446        int random;
447        bool bref = false;
448        string first = "";
449        string last = "";
450        int colnum = 0;
451        std::string re;
452        for (auto col : row){
453                if (col != "false" && !ccHandler.isEmpty()){
454                       
455                        string cc;
456                        if (usesCC(header[colnum])){
457
458                                cc = ccHandler.getCC();
459                                if (header[colnum] == "zeroOrOne"  ){
460                                        re = getZeroOrOne(cc);
461                                        if (!re.empty())
462                                        fullRE.push_back(re);
463                                }
464                                else if (header[colnum] == "zeroOrMore"){
465                                        re = getZeroOrMore(cc);
466                                        if (!re.empty())
467                                        fullRE.push_back(re);
468                                } 
469                                else if (header[colnum] == "oneOrMore"){
470                                        re = getOneOrMore(cc);
471                                        // std::string nestDepth = row[colnum+1];
472                                        // int depth = std::stoi(nestDepth);
473                                        // while(depth>0){
474                                        //      std::string cc2;
475                                        //      cc2 = ccHandler.getCC();
476                                        //      re = '(' + re + cc2 + ')' + header[colnum];
477                                        //      --depth;
478                                        // }
479                                        if (!re.empty())
480                                        fullRE.push_back(re);
481                                }
482                                else if (header[colnum] == "repeat_n"){
483                                        random = rand() % 200 + 1;
484                                        re = getRep(cc, random);
485                                        // std::string nestDepth = row[colnum+1];
486                                        // int depth = std::stoi(nestDepth);
487                                        // while(depth>0){
488                                        //      std::string cc2;
489                                        //      cc2 = ccHandler.getCC();
490                                        //      random = rand() % 200;
491                                        //      re = '(?:' + re + cc2 + ')' + '{' + to_string(random) + '}';
492                                        //      --depth;
493                                        // }
494                                        if (!re.empty())
495                                        fullRE.push_back(re);
496                                }
497                                else if (header[colnum] == "repeat_nm" ){
498                                        std::vector<int> randoms;
499                                        int r1 = rand() % 200;
500                                        int r2 = rand() % 200;
501                                        while (r1 == 0 && r2 == 0){
502                                                r2 = rand() % 200;
503                                        }
504                                        randoms.push_back(r1);
505                                        randoms.push_back(r2);
506                                        sort(randoms.begin(), randoms.end());
507                                        re = getRep(cc, randoms[0], randoms[1]);
508                                        // std::string nestDepth = row[colnum+1];
509                                        // int depth = std::stoi(nestDepth);
510                                        // while(depth>0){
511                                        //      std::string cc2 = ccHandler.getCC();
512                                        //      std::vector<int> randoms;
513                                        //      randoms.push_back(rand() % 200);
514                                        //      randoms.push_back(rand() % 200);
515                                        //      sort(randoms.begin(), randoms.end());
516                                        //      re = '(?:' + re + cc2 + ')' + '{' + to_string(randoms[0]) + ',' + to_string(randoms[1]) + '}';
517                                        //      --depth;
518                                        // }
519                                        if (!re.empty())
520                                        fullRE.push_back(re);
521                                }
522                                else if (header[colnum] == "repeat_n_more" ){
523                                        random = rand() % 200;
524                                        re = getRepMore(cc, random);
525                                        if (!re.empty())
526                                        fullRE.push_back(re);
527                                }
528                                else if (header[colnum] == "repeat_m_less" ){
529                                        random = rand() % 200;
530                                        re = getRep(cc, 0, random);
531                                        if (!re.empty())
532                                        fullRE.push_back(re);
533                                }
534                                else if (header[colnum] == "backref"){
535                                        bref = true;
536                                }
537                                else if (header[colnum] == "join" ){
538                                        std::string cc2 = ccHandler.getCC();
539                                        re = getJoin(cc, cc2);
540                                        if (!re.empty())
541                                        fullRE.push_back(re);
542                                }
543                                else if (header[colnum] == "look_ahead"){
544                                        re = getLookAhead(cc);
545                                        if (!re.empty())
546                                        assertions.push_back(re);
547                                }
548                                else if (header[colnum] == "nlook_ahead"){
549                                        if (cc == ".") {
550                                                continue;
551                                        }
552                                        else {
553                                                re = getNegativeLookAhead(cc);
554                                                if (!re.empty())
555                                                assertions.push_back(re);
556                                        }
557                                }
558                                else if (header[colnum] == "look_behind"){
559                                        re = getLookBehind(cc);
560                                        if (!re.empty())
561                                        assertions.push_back(re);
562                                }
563                                else if (header[colnum] == "nlook_behind"){
564                                        if (cc == ".") {
565                                                continue;
566                                        }
567                                        else {
568                                                re = getNegativeLookBehind(cc);
569                                                if (!re.empty())
570                                                assertions.push_back(re);
571                                        }
572                                }
573                        }
574                        else {
575
576                                // if (header[colnum] == "boundary") {
577                                //      re = getBoundary();
578                                //      if (!re.empty())
579                                //      assertions.push_back(re +"\\s");
580                                // }
581                                // else if (header[colnum] == "notBoundary") {
582                                //      std::string front = getAssertionCoating("[^\\s\\t\\n]");
583                                //      re = getNotBoundary();
584                                //      if (!re.empty())
585                                //      assertions.push_back(re + front);
586                                // }
587                                if (header[colnum] == "start"){
588                                                first = "^";
589                                }
590                                else if (header[colnum] == "end"){
591                                                last = "$";
592                                }
593                        }
594
595                }
596                colnum++;
597        }
598
599        vector<string> ccList = ccHandler.getRemainingCC();
600        while(!ccList.empty()){
601                fullRE.push_back(ccList.back());
602                ccList.pop_back();
603        }
604        if(!fullRE.empty()){
605
606                if (bref){
607                        random = rand() % fullRE.size();
608                        fullRE[random] = getBackRef(fullRE[random]);
609                        std::copy (assertions.begin(), assertions.end(), std::back_inserter(fullRE));
610                        std::random_shuffle(fullRE.begin(), fullRE.end());
611                        fullRE.push_back("\\1");
612                }
613                else {
614                        std::copy (assertions.begin(), assertions.end(), std::back_inserter(fullRE)); //to avoid nesting assertions.
615                        std::random_shuffle(fullRE.begin(), fullRE.end());
616                }
617                string sre= first + stringifyLine(fullRE) + last;
618                return sre;
619        }
620        else {
621                return "";
622        }
623}
624
625std::vector<string> RegexGen::parseFlags(std::vector<string> header, std::vector<string> row){
626        std::vector<string> flags;
627        int colnum = 0;
628        for (auto col : row){
629                if (col != "false"){
630                        if (header[colnum] == "-c"
631                                || header[colnum] == "-i"
632                                // || header[colnum] == "-w"
633                                // || header[colnum] == "-x"
634                                || header[colnum] == "-e"
635                                || header[colnum] == "-f"){
636                                flags.push_back(header[colnum]);
637                        }
638                        else if (header[colnum] == "syntax"){
639                                flags.push_back(col);
640                        }
641                }
642                colnum++;
643        }
644        return flags;
645}
646
Note: See TracBrowser for help on using the repository browser.