Static Value-Flow Analysis
Loading...
Searching...
No Matches
Public Member Functions | Private Member Functions | List of all members
SVF::CFGNormalizer Class Reference

#include <CFGNormalizer.h>

Public Member Functions

 CFGNormalizer ()
 
CFGrammarnormalize (GrammarBase *generalGrammar)
 Binary Normal Form(BNF) normalization with variable attribute expanded.
 
CFGrammarfillAttribute (CFGrammar *grammar, const Map< CFGrammar::Kind, Set< CFGrammar::Attribute > > &kindToAttrsMap)
 Expand every variable attribute in rawProductions of grammarbase.
 

Private Member Functions

void ebnf_bin (CFGrammar *grammar)
 Add nonterminal to tranfer long rules to binary rules.
 
void ebnfSignReplace (char sign, CFGrammar *grammar)
 
void barReplace (CFGrammar *grammar)
 
void insertToCFLGrammar (CFGrammar *grammar, GrammarBase::Production &prod)
 Based on prod size to add on suitable member field of grammar.
 
int ebnfBracketMatch (GrammarBase::Production &prod, int i, CFGrammar *grammar)
 
GrammarBase::Symbol check_head (GrammarBase::SymbolMap< GrammarBase::Symbol, GrammarBase::Productions > &grammar, GrammarBase::Production &rule)
 
void strTrans (std::string strPro, CFGrammar *grammar, GrammarBase::Production &normalProd)
 
void getFilledProductions (GrammarBase::Production &prod, const NodeSet &nodeSet, CFGrammar *grammar, GrammarBase::Productions &normalProds)
 
void removeFirstSymbol (CFGrammar *grammar)
 

Detailed Description

Generate Normalized Grammar (backus naur form) from a grammarbase (Extended extended Backus–Naur form )

To Do: Error Notice for ill formed production, e.g. not end with ';' and '*' not preceding with '()' and extra space before ';' '|' sign support

Definition at line 48 of file CFGNormalizer.h.

Constructor & Destructor Documentation

◆ CFGNormalizer()

SVF::CFGNormalizer::CFGNormalizer ( )
inline

Definition at line 52 of file CFGNormalizer.h.

53 {
54 }

Member Function Documentation

◆ barReplace()

void CFGNormalizer::barReplace ( CFGrammar grammar)
private

Definition at line 294 of file CFGNormalizer.cpp.

295{
296 for (auto &symbolToProductionsPair : grammar->getRawProductions())
297 {
299 //GrammarBase::Productions Originalproductions = symbolToProductionsPair.second;
301 {
302 size_t i = 1;
303 size_t j = 1;
304 while (i < ebnfProduction.size())
305 {
306 if (grammar->kindToStr(ebnfProduction[i].kind) == "|")
307 {
309 tempPro.insert(tempPro.begin(), symbolToProductionsPair.first );
310 productions.insert(tempPro);
311 j = i+1;
312 }
313 i++;
314 }
316 tempPro.insert(tempPro.begin(), symbolToProductionsPair.first );
317 productions.insert(tempPro);
318 }
319 symbolToProductionsPair.second.clear();
321 }
322}
SymbolSet< Production > Productions
Definition CFGrammar.h:161
std::string kindToStr(Kind kind) const
std::vector< Symbol > Production
Definition CFGrammar.h:160
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76

◆ check_head()

GrammarBase::Symbol CFGNormalizer::check_head ( GrammarBase::SymbolMap< GrammarBase::Symbol, GrammarBase::Productions > &  grammar,
GrammarBase::Production rule 
)
private

Definition at line 466 of file CFGNormalizer.cpp.

467{
468 for(auto symProdPair: grammar)
469 {
470 for(auto prod: symProdPair.second)
471 {
472 if (rule == prod)
473 {
474 return symProdPair.first;
475 }
476 }
477 }
479 return symbol;
480}
unsigned u32_t
Definition GeneralType.h:67

◆ ebnf_bin()

void CFGNormalizer::ebnf_bin ( CFGrammar grammar)
private

Add nonterminal to tranfer long rules to binary rules.

Assign _attribute if target portion of the production contain more than 1 variable then X add no variable attribute if target only contain one variable attribute X share the same variable attribute

Definition at line 90 of file CFGNormalizer.cpp.

91{
93 std::string tempStr = "";
94 removeFirstSymbol(grammar);
95
96 auto rawProductions = grammar->getRawProductions();
97
98 for(auto itr : rawProductions)
99 {
100 auto head = *(grammar->getRawProductions().find(itr.first));
101 for(auto rule: head.second)
102 {
103 if (rule.size() < 3) continue;
104
106 GrammarBase::Production long_run(rule.begin() + 1, rule.end());
107 auto it = grammar->getRawProductions()[head.first].find(rule);
108 grammar->getRawProductions()[head.first].erase(it);
110 if (X == u32_t(-1))
111 {
112 X = check_head(grammar->getRawProductions(), long_run);
113 }
114 if ((X == u32_t(-1)) == false)
115 {
116 rule = {first, X};
117 grammar->getRawProductions()[head.first].insert(rule);
118 }
119 else
120 {
121 tempStr = "X";
122 std::ostringstream ss;
123 ss << grammar->num_generator();
124 tempStr.append(ss.str());
130 for (unsigned i = 0; i < long_run.size(); i++)
131 {
132 GrammarBase::VariableAttribute variableAttribute = long_run[i].variableAttribute;
133 if ( variableAttribute != 0)
134 {
135 variableAttributeSet.insert(variableAttribute);
136 }
137 }
138 if ( variableAttributeSet.size() == 1)
139 {
140 tempStr += "_";
141 tempStr += char(*variableAttributeSet.begin());
142 }
144 rule = {first, tempSym};
145 grammar->getRawProductions()[head.first].insert(rule);
146 X = tempSym;
147 }
148 new_grammar[X] = {};
151 if (long_run.size() ==2)
152 {
153 new_grammar[X].insert(temp_p);
154 long_run.clear();
155 }
156 else
157 {
158 new_grammar[X].insert(long_run);
159 RHX = X;
160 }
161 while (long_run.size() > 2)
162 {
163 first = long_run[0];
165 long_run.erase(long_run.begin());
166
167 X = RHX;
169
171 if (RHX == u32_t(-1))
172 {
174 }
175 if(RHX == u32_t(-1))
176 {
177 tempStr = "X";
178 std::ostringstream ss;
179 ss << grammar->num_generator();
180 tempStr.append(ss.str());
182 for (unsigned i = 0; i < long_run.size(); i++)
183 {
184 GrammarBase::VariableAttribute variableAttribute = long_run[i].variableAttribute;
185 if ( variableAttribute != 0)
186 {
187 variableAttributeSet.insert(variableAttribute);
188 }
189 }
190 if ( variableAttributeSet.size() == 1)
191 {
192 tempStr += "_";
193 tempStr += char(*variableAttributeSet.begin());
194 }
196 auto it = new_grammar[X].find(prev_rule);
197 new_grammar[X].erase(it);
198 new_grammar[X].insert({first, tempSym});
200 RHX = tempSym;
201 }
202 }
203 }
204 }
205 for (auto new_head : new_grammar)
206 {
207 for (auto prod : new_head.second)
208 {
209 auto it = grammar->getRawProductions()[new_head.first].find(prod);
210 if (it == grammar->getRawProductions()[new_head.first].end())
211 {
212 grammar->getRawProductions()[new_head.first].insert(prod);
213 }
214 }
215 }
216}
void removeFirstSymbol(CFGrammar *grammar)
GrammarBase::Symbol check_head(GrammarBase::SymbolMap< GrammarBase::Symbol, GrammarBase::Productions > &grammar, GrammarBase::Production &rule)
const u32_t num_generator()
Definition CFGrammar.h:392
Symbol insertNonTerminalSymbol(std::string strLit)
SymbolMap< Symbol, Productions > & getRawProductions()
Definition CFGrammar.h:194
u32_t VariableAttribute
Definition CFGrammar.h:45
Map< Key, Value, Hash, KeyEqual, Allocator > SymbolMap
Definition CFGrammar.h:154

◆ ebnfBracketMatch()

int CFGNormalizer::ebnfBracketMatch ( GrammarBase::Production prod,
int  i,
CFGrammar grammar 
)
private

Definition at line 280 of file CFGNormalizer.cpp.

281{
282 int index = i;
283 while (index >= 0)
284 {
285 if (grammar->kindToStr(prod[index].kind) == "(")
286 {
287 return index;
288 }
289 index--;
290 }
291 return 0;
292}
int index
Definition cJSON.h:170

◆ ebnfSignReplace()

void CFGNormalizer::ebnfSignReplace ( char  sign,
CFGrammar grammar 
)
private

Replace Sign Group With tempNonterminal 'X' And load the replace in newProductions

If sign associate without group e.i with single symbol

sign associate with group of symbol by brace pair

For Both * and ? need to insert epsilon rule

insert second rule for '*' X -> X E for '+' X -> E

Insert Back the Group

Definition at line 324 of file CFGNormalizer.cpp.

325{
329 std::string tempNonterminal = "X";
330
331 for (auto &symbolToProductionsPair : grammar->getRawProductions())
332 {
335 {
336 size_t i = 1;
337 while (i < ebnfProduction.size())
338 {
340 if (grammar->kindToStr(ebnfProduction[i].kind) == std::string(1, sign))
341 {
343 assert(i != 1 && "sign in grammar associate with no symbol");
344 if (grammar->kindToStr(ebnfProduction[i - 1].kind) != std::string(1, ')'))
345 {
346 signGroupStart = i - 1;
347 }
349 else
350 {
352 }
353 std::string groupString = "";
354 for (size_t j = signGroupStart; j < i; j++)
355 {
356 groupString.append(grammar->kindToStr(ebnfProduction[j].kind));
357 groupString.append(" ");
358 }
359 groupString.append(grammar->kindToStr(ebnfProduction[i].kind));
360 if (newProductions.find(groupString) != newProductions.end())
361 {
363 ebnfProduction.erase(ebnfProduction.begin() + signGroupStart, ebnfProduction.begin() + i + 1);
366 }
367 else if ( (signGroupStart == 1) && (i == ebnfProduction.size() -1))
368 {
371 ebnfProduction.erase(ebnfProduction.begin() + signGroupStart, ebnfProduction.begin() + i + 1);
372
373 }
374 else
375 {
376 tempNonterminal = "X";
377 std::ostringstream ss;
378 ss << grammar->num_generator();
379 tempNonterminal.append(ss.str());
382 ebnfProduction.erase(ebnfProduction.begin() + signGroupStart, ebnfProduction.begin() + i + 1);
386 }
387
389 }
390 i++;
391 }
392 }
394 }
395 for(auto rep: newProductions)
396 {
398 std::string new_nonterminal = rep.second;
400 grammar->getRawProductions()[grammar->strToSymbol(new_nonterminal)].insert(temp_list);
403 if (sign == '*' || sign == '?')
404 {
407 strTrans(rep.first, grammar, normalProd);
409 if (sign == '*')
410 {
411 for (auto &word : normalProd)
412 {
413 if (word != grammar->strToSymbol("*") && word != grammar->strToSymbol("(") && word != grammar->strToSymbol(")"))
414 {
415 withoutSign.push_back(word);
416 }
417 }
418 withoutSign.push_back(grammar->strToSymbol(rep.second));
419 }
420 if (sign == '?')
421 {
422 for (auto &word : normalProd)
423 {
424 if (word != grammar->strToSymbol("?") && word != grammar->strToSymbol("(") && word != grammar->strToSymbol(")"))
425 {
426 withoutSign.push_back(word);
427 }
428 }
429 }
430 temp_list.insert(temp_list.end(), withoutSign.begin(), withoutSign.end());
431 }
432 grammar->getRawProductions()[grammar->strToSymbol(new_nonterminal)].insert(temp_list);
433 }
434}
int ebnfBracketMatch(GrammarBase::Production &prod, int i, CFGrammar *grammar)
void strTrans(std::string strPro, CFGrammar *grammar, GrammarBase::Production &normalProd)
Symbol strToSymbol(const std::string str) const
Definition CFGrammar.cpp:76
signed s32_t
Definition GeneralType.h:68

◆ fillAttribute()

CFGrammar * CFGNormalizer::fillAttribute ( CFGrammar grammar,
const Map< CFGrammar::Kind, Set< CFGrammar::Attribute > > &  kindToAttrsMap 
)

Expand every variable attribute in rawProductions of grammarbase.

rawProductions production does not include lhs so append to the begin of the production

Definition at line 60 of file CFGNormalizer.cpp.

61{
62 NodeSet nodeSet = {};
63 for (auto pair: kindToAttrsMap)
64 {
65 for (auto attri: pair.second)
66 {
67 nodeSet.insert(attri);
68 }
69 }
70 for(auto symProdsPair: grammar->getRawProductions())
71 {
72 for(auto prod: symProdsPair.second)
73 {
77 tempP.insert(tempP.begin(), symProdsPair.first);
79 getFilledProductions(tempP, nodeSet, grammar, normalProds);
80 for (auto filledProd : normalProds)
81 {
83 }
84 }
85 }
86
87 return grammar;
88}
void insertToCFLGrammar(CFGrammar *grammar, GrammarBase::Production &prod)
Based on prod size to add on suitable member field of grammar.
void getFilledProductions(GrammarBase::Production &prod, const NodeSet &nodeSet, CFGrammar *grammar, GrammarBase::Productions &normalProds)
Set< NodeID > NodeSet
Definition GeneralType.h:87

◆ getFilledProductions()

void CFGNormalizer::getFilledProductions ( GrammarBase::Production prod,
const NodeSet nodeSet,
CFGrammar grammar,
GrammarBase::Productions normalProds 
)
private

Loop through provided production based on existence of attribute of attribute variable and expand to productions set e.g Xi -> Y Zi with Xi i = 0, 1, Yi i = 0,2 Will get {X0 -> Y Z0, X1 -> Y Z1, X2 -> Y Z2}

Get the first encounter variable attribute to expand

Check whether all symbol expanded

Definition at line 222 of file CFGNormalizer.cpp.

223{
224 normalProds.clear();
226 worklist.push(prod);
227 while( worklist.empty() == false )
228 {
232 // GrammarBase::Kind baseKind;
234 {
235 if ( currentVariableAttribute == 0 )
236 {
237 currentVariableAttribute = symbol.variableAttribute;
238 // baseKind = symbol.kind;
239 }
240 }
241 if ( currentVariableAttribute == 0)
242 {
244 continue;
245 }
246 //*(kindToAttriMap.find(baseKind));
247 //for (auto attribute : nodeSet.second)
248 for (auto attribute : nodeSet)
249 {
252 {
253 if ( symbol.variableAttribute == currentVariableAttribute)
254 {
255 symbol.attribute = attribute;
256 symbol.variableAttribute = 0;
257 }
258 }
260 bool continueToFill = false;
262 {
263 if ( symbol.variableAttribute != 0 )
264 {
265 continueToFill = true;
266 }
267 }
268 if ( continueToFill == false)
269 {
271 }
272 else
273 {
274 worklist.push(fillingProduction);
275 }
276 }
277 }
278}
bool empty() const
Definition CFGrammar.h:420
bool push(Data data)
Definition CFGrammar.h:433

◆ insertToCFLGrammar()

void CFGNormalizer::insertToCFLGrammar ( CFGrammar grammar,
GrammarBase::Production prod 
)
private

Based on prod size to add on suitable member field of grammar.

Definition at line 483 of file CFGNormalizer.cpp.

484{
485 if (prod.size() == 2)
486 {
487 if ((std::find(prod.begin(), prod.end(), grammar->strToKind("epsilon")) != prod.end()))
488 {
489 if (std::find(grammar->getEpsilonProds().begin(), grammar->getEpsilonProds().end(), prod) == grammar->getEpsilonProds().end())
490 {
491 grammar->getEpsilonProds().insert(prod);
492 }
493 }
494 else
495 {
496 grammar->getSingleRHSToProds()[prod[1]].insert(prod);
497 }
498 }
499 if (prod.size() == 3)
500 {
501 grammar->getFirstRHSToProds()[prod[1]].insert(prod);
502 grammar->getSecondRHSToProds()[prod[2]].insert(prod);
503 }
504}
SymbolMap< Symbol, Productions > & getFirstRHSToProds()
Definition CFGrammar.h:322
SymbolMap< Symbol, Productions > & getSingleRHSToProds()
Definition CFGrammar.h:317
SymbolMap< Symbol, Productions > & getSecondRHSToProds()
Definition CFGrammar.h:327
Productions & getEpsilonProds()
Definition CFGrammar.h:312
Kind strToKind(std::string str) const
Definition CFGrammar.cpp:57

◆ normalize()

CFGrammar * CFGNormalizer::normalize ( GrammarBase generalGrammar)

Binary Normal Form(BNF) normalization with variable attribute expanded.

Definition at line 40 of file CFGNormalizer.cpp.

41{
42 CFGrammar *grammar = new CFGrammar();
43 grammar->setStartKind(generalGrammar->getStartKind());
44 grammar->setTerminals(generalGrammar->getTerminals());
45 grammar->setNonterminals(generalGrammar->getNonterminals());
46 grammar->setEBNFSigns(generalGrammar->getEBNFSigns());
47 grammar->setTotalKind(generalGrammar->getTotalKind());
48 grammar->setAttributeKinds(generalGrammar->getAttrSyms());
49 grammar->setKindToAttrsMap(generalGrammar->getKindToAttrsMap());
50 grammar->setRawProductions(generalGrammar->getRawProductions());
51 barReplace(grammar);
52 ebnfSignReplace('*', grammar);
53 ebnfSignReplace('?', grammar);
54 ebnf_bin(grammar);
55 fillAttribute(grammar, grammar->getKindToAttrsMap());
56 return grammar;
57}
void barReplace(CFGrammar *grammar)
void ebnf_bin(CFGrammar *grammar)
Add nonterminal to tranfer long rules to binary rules.
void ebnfSignReplace(char sign, CFGrammar *grammar)
CFGrammar * fillAttribute(CFGrammar *grammar, const Map< CFGrammar::Kind, Set< CFGrammar::Attribute > > &kindToAttrsMap)
Expand every variable attribute in rawProductions of grammarbase.
void setStartKind(Kind startKind)
Definition CFGrammar.h:214
void setAttributeKinds(const Set< Kind > &attributeKind)
Definition CFGrammar.cpp:52
const Map< Kind, Set< Attribute > > & getKindToAttrsMap() const
Definition CFGrammar.h:199
void setRawProductions(SymbolMap< Symbol, Productions > &rawProductions)
Definition CFGrammar.cpp:42
void setTotalKind(Kind totalKind)
Definition CFGrammar.h:219
void setKindToAttrsMap(const Map< Kind, Set< Attribute > > &kindToAttrsMap)
Definition CFGrammar.cpp:47
void setEBNFSigns(Map< std::string, Kind > &EBNFSigns)
Definition CFGrammar.h:189
void setTerminals(Map< std::string, Kind > &terminals)
Definition CFGrammar.h:179
void setNonterminals(Map< std::string, Kind > &nonterminals)
Definition CFGrammar.h:169

◆ removeFirstSymbol()

void CFGNormalizer::removeFirstSymbol ( CFGrammar grammar)
private

Definition at line 506 of file CFGNormalizer.cpp.

507{
508 // Remove First Terminal
509 for(auto head : grammar->getRawProductions())
510 {
511 for(auto rule: head.second)
512 {
513
515 long_run.erase(long_run.begin());
516 auto it = grammar->getRawProductions().at(head.first).find(rule);
517 grammar->getRawProductions().at(head.first).erase(it);
518 grammar->getRawProductions()[head.first].insert(long_run);
519 }
520 }
521}

◆ strTrans()

void CFGNormalizer::strTrans ( std::string  strPro,
CFGrammar grammar,
GrammarBase::Production normalProd 
)
private

Definition at line 436 of file CFGNormalizer.cpp.

437{
438 // Find the position of the first non-whitespace character
439 size_t start = LHS.find_first_not_of(" \t\n\r");
440 // If the string contains non-whitespace characters, remove leading spaces
441 if (start != std::string::npos)
442 {
443 LHS = LHS.substr(start);
444 }
445 else
446 {
447 // If the string contains only spaces, clear it
448 LHS.clear();
449 }
450
451 std::string delimiter;
452 size_t pos;
453 std::string word;
454
455 delimiter = " ";
456 while ((pos = LHS.find(delimiter)) != std::string::npos)
457 {
458 word = LHS.substr(0, pos);
459 LHS.erase(0, pos + delimiter.length());
460 normalProd.push_back(grammar->strToSymbol(word));
461 }
462 normalProd.push_back(grammar->strToSymbol(LHS));
463}

The documentation for this class was generated from the following files: