Static Value-Flow Analysis
Loading...
Searching...
No Matches
SVF::CFGNormalizer Class Reference

#include <CFGNormalizer.h>

Public Member Functions

 CFGNormalizer ()
CFGrammar * normalize (GrammarBase *generalGrammar)
 Binary Normal Form(BNF) normalization with variable attribute expanded.
CFGrammar * fillAttribute (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 {
298 GrammarBase::Productions productions;
299 //GrammarBase::Productions Originalproductions = symbolToProductionsPair.second;
300 for (auto ebnfProduction : 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 {
308 GrammarBase::Production tempPro(ebnfProduction.begin()+j, ebnfProduction.begin()+i);
309 tempPro.insert(tempPro.begin(), symbolToProductionsPair.first );
310 productions.insert(tempPro);
311 j = i+1;
312 }
313 i++;
314 }
315 GrammarBase::Production tempPro(ebnfProduction.begin()+j, ebnfProduction.begin()+i);
316 tempPro.insert(tempPro.begin(), symbolToProductionsPair.first );
317 productions.insert(tempPro);
318 }
319 symbolToProductionsPair.second.clear();
320 symbolToProductionsPair.second = productions;
321 }
322}
SymbolMap< Symbol, Productions > & getRawProductions()
Definition CFGrammar.h:194
SymbolSet< Production > Productions
Definition CFGrammar.h:161
std::string kindToStr(Kind kind) const
std::vector< Symbol > Production
Definition CFGrammar.h:160

◆ check_head()

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 }
478 GrammarBase::Symbol symbol = u32_t(-1);
479 return symbol;
480}
struct SVF::GrammarBase::Symbol Symbol
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
105 GrammarBase::Symbol first = rule[0];
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);
109 GrammarBase::Symbol X = check_head(new_grammar, long_run);
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());
129 Set<GrammarBase::VariableAttribute> variableAttributeSet = {};
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 }
143 GrammarBase::Symbol tempSym = grammar->insertNonTerminalSymbol(tempStr);
144 rule = {first, tempSym};
145 grammar->getRawProductions()[head.first].insert(rule);
146 X = tempSym;
147 }
148 new_grammar[X] = {};
149 GrammarBase::Production temp_p = long_run;
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];
164 GrammarBase::Production prev_rule = long_run;
165 long_run.erase(long_run.begin());
166
167 X = RHX;
168 temp_p = long_run;
169
170 RHX = check_head(new_grammar, long_run);
171 if (RHX == u32_t(-1))
172 {
173 RHX = check_head(grammar->getRawProductions(), long_run);
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());
181 Set<GrammarBase::VariableAttribute> variableAttributeSet = {};
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 }
195 GrammarBase::Symbol tempSym = grammar->insertNonTerminalSymbol(tempStr);
196 auto it = new_grammar[X].find(prev_rule);
197 new_grammar[X].erase(it);
198 new_grammar[X].insert({first, tempSym});
199 new_grammar[tempSym].insert(long_run);
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)
u32_t VariableAttribute
Definition CFGrammar.h:45
Map< Key, Value, Hash, KeyEqual, Allocator > SymbolMap
Definition CFGrammar.h:154
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition GeneralType.h:51

◆ 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 {
333 GrammarBase::Productions productions = symbolToProductionsPair.second;
334 for (auto ebnfProduction : symbolToProductionsPair.second)
335 {
336 size_t i = 1;
337 while (i < ebnfProduction.size())
338 {
339 s32_t signGroupStart = -1;
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 {
351 signGroupStart = ebnfBracketMatch(ebnfProduction, i, grammar);
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 {
362 productions.erase(ebnfProduction);
363 ebnfProduction.erase(ebnfProduction.begin() + signGroupStart, ebnfProduction.begin() + i + 1);
364 ebnfProduction.insert(ebnfProduction.begin() + signGroupStart, grammar->strToSymbol(newProductions[groupString]));
365 productions.insert(ebnfProduction);
366 }
367 else if ( (signGroupStart == 1) && (i == ebnfProduction.size() -1))
368 {
369 newProductions[groupString] = grammar->kindToStr(ebnfProduction[0].kind);
370 productions.erase(ebnfProduction);
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());
380 GrammarBase::Symbol tempSym = grammar->insertNonTerminalSymbol(tempNonterminal);
381 productions.erase(ebnfProduction);
382 ebnfProduction.erase(ebnfProduction.begin() + signGroupStart, ebnfProduction.begin() + i + 1);
383 ebnfProduction.insert(ebnfProduction.begin() + signGroupStart, tempSym);
384 newProductions[groupString] = tempNonterminal;
385 productions.insert(ebnfProduction);
386 }
387
388 i = signGroupStart;
389 }
390 i++;
391 }
392 }
393 symbolToProductionsPair.second = productions;
394 }
395 for(auto rep: newProductions)
396 {
398 std::string new_nonterminal = rep.second;
399 GrammarBase::Production temp_list = {grammar->strToSymbol(new_nonterminal), grammar->strToSymbol("epsilon")};
400 grammar->getRawProductions()[grammar->strToSymbol(new_nonterminal)].insert(temp_list);
402 temp_list = {grammar->strToSymbol(new_nonterminal)};
403 if (sign == '*' || sign == '?')
404 {
406 GrammarBase::Production normalProd;
407 strTrans(rep.first, grammar, normalProd);
408 GrammarBase::Production withoutSign = {};
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
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition GeneralType.h:56
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 {
76 GrammarBase::Production tempP = prod;
77 tempP.insert(tempP.begin(), symProdsPair.first);
78 GrammarBase::Productions normalProds;
79 getFilledProductions(tempP, nodeSet, grammar, normalProds);
80 for (auto filledProd : normalProds)
81 {
82 insertToCFLGrammar(grammar, filledProd);
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();
225 CFLFIFOWorkList<GrammarBase::Production> worklist;
226 worklist.push(prod);
227 while( worklist.empty() == false )
228 {
229 GrammarBase::Production currentProduction = worklist.pop();
231 GrammarBase::VariableAttribute currentVariableAttribute = 0;
232 // GrammarBase::Kind baseKind;
233 for ( GrammarBase::Symbol &symbol : currentProduction )
234 {
235 if ( currentVariableAttribute == 0 )
236 {
237 currentVariableAttribute = symbol.variableAttribute;
238 // baseKind = symbol.kind;
239 }
240 }
241 if ( currentVariableAttribute == 0)
242 {
243 normalProds.insert(currentProduction);
244 continue;
245 }
246 //*(kindToAttriMap.find(baseKind));
247 //for (auto attribute : nodeSet.second)
248 for (auto attribute : nodeSet)
249 {
250 GrammarBase::Production fillingProduction = currentProduction;
251 for ( GrammarBase::Symbol &symbol : fillingProduction )
252 {
253 if ( symbol.variableAttribute == currentVariableAttribute)
254 {
255 symbol.attribute = attribute;
256 symbol.variableAttribute = 0;
257 }
258 }
260 bool continueToFill = false;
261 for ( GrammarBase::Symbol &symbol : fillingProduction )
262 {
263 if ( symbol.variableAttribute != 0 )
264 {
265 continueToFill = true;
266 }
267 }
268 if ( continueToFill == false)
269 {
270 normalProds.insert(fillingProduction);
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
Map< std::string, Kind > & getEBNFSigns()
Definition CFGrammar.h:184
Map< std::string, Kind > & getNonterminals()
Definition CFGrammar.h:164
Map< std::string, Kind > & getTerminals()
Definition CFGrammar.h:174
Kind getTotalKind()
Definition CFGrammar.h:204
const Set< Kind > & getAttrSyms() const
Definition CFGrammar.h:247
Kind getStartKind()
Definition CFGrammar.h:209
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
514 GrammarBase::Production long_run = rule;
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: