Static Value-Flow Analysis
CFGrammar.cpp
Go to the documentation of this file.
1 //===----- CFGrammar.cpp -- Context-free grammar --------------------------//
2 //
3 // SVF: Static Value-Flow Analysis
4 //
5 // Copyright (C) <2013-> <Yulei Sui>
6 //
7 
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
12 
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
17 
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 //
21 //===----------------------------------------------------------------------===//
22 
23 /*
24  * CFGrammar.cpp
25  *
26  * Created on: March 5, 2022
27  * Author: Yulei Sui
28  */
29 
30 #include "CFL/CFGrammar.h"
31 #include "Util/SVFUtil.h"
32 #include <string>
33 #include <iostream>
34 #include <fstream>
35 #include <sstream>
36 
37 using namespace SVF;
38 
39 
41 {
42  this->rawProductions = rawProductions;
43 }
44 
46 {
48 }
49 
50 void GrammarBase::setAttributeKinds(const Set<Kind>& attributeKinds)
51 {
52  this->attributeKinds = attributeKinds;
53 }
54 
56 {
57 
58  auto tit = terminals.find(str);
59  if(tit!=terminals.end())
60  return tit->second;
61 
62  auto nit = nonterminals.find(str);
63  if(nit!=nonterminals.end())
64  return nit->second;
65 
66  auto sit = EBNFSigns.find(str);
67  if(sit!=EBNFSigns.end())
68  return sit->second;
69 
70  assert(false && "kind not found!");
71  abort();
72 }
73 
75 {
76  Symbol symbol;
79  symbol.kind = strToKind(kindStr);
80 
81  if ( attributeStr == "") return symbol;
82 
83  if ( (attributeStr.size() == 1) && (std::isalpha(attributeStr[attributeStr.size()-1])) )
84  {
85  symbol.variableAttribute = (u32_t)attributeStr[attributeStr.size()-1];
86  }
87  else
88  {
89  for( char &c : attributeStr)
90  {
91  if ( std::isdigit(c) == false )
92  {
93  SVFUtil::errs() << SVFUtil::errMsg("\t Symbol Attribute Parse Failure :") << str
94  << " Attribute:" << attributeStr << " (only number or single alphabet.)";
95  assert(false && "grammar loading failed!");
96  }
97  }
98  symbol.attribute = std::stoi(attributeStr);
99  }
100  return symbol;
101 }
102 
104 {
105 
106  std::string key = "";
107  for (auto &i : terminals)
108  {
109  if (i.second == kind)
110  {
111  key = i.first;
112  return key;
113  }
114  }
115 
116  std::string nkey = "";
117  for (auto &ni : nonterminals)
118  {
119  if (ni.second == kind)
120  {
121  nkey = ni.first;
122  return nkey;
123  }
124  }
125 
126  std::string signs = "";
127  for (auto &i : EBNFSigns)
128  {
129  if (i.second == kind)
130  {
131  signs = i.first;
132  return signs;
133  }
134  }
135 
136  return "";
137 }
138 
140 {
141  Kind kind = sym.kind;
142  Attribute attribute = sym.attribute;
143 
144  std::string key = "";
145  for (auto &i : terminals)
146  {
147  if (i.second == kind)
148  {
149  key = i.first;
150  if(attribute != 0)
151  {
152  key.append("_");
153  key.append(std::to_string(attribute));
154  }
155  return key;
156  }
157  }
158 
159  std::string nkey = "";
160  for (auto &ni : nonterminals)
161  {
162  if (ni.second == kind)
163  {
164  nkey = ni.first;
165  if(attribute != 0)
166  {
167  nkey.append("_");
168  nkey.append(std::to_string(attribute));
169  }
170  return nkey;
171  }
172  }
173 
174  return "";
175 }
176 
178 {
179  Kind kind;
180  if (terminals.find(kindStr) == terminals.end())
181  {
182  kind = totalKind++;
183  terminals.insert({kindStr, kind});
184  }
185  else
186  {
187  kind = strToKind(kindStr);
188  }
189  return kind;
190 }
191 
193 {
194  Kind kind;
195  if (nonterminals.find(kindStr) == nonterminals.end())
196  {
197  kind = totalKind++;
198  nonterminals.insert({kindStr, kind});
199  }
200  else
201  {
202  kind = strToKind(kindStr);
203  }
204  return kind;
205 }
206 
208 {
209  std::string kindStr;
210  // symbolStr end with '_', the whole symbolStr treat as kind, not with attribute.
211  auto underscorePosition = symbolStr.find_last_of("_", symbolStr.size()-1);
212  if (underscorePosition == std::string::npos)
213  {
214  return symbolStr;
215  }
216  return symbolStr.substr(0, underscorePosition);
217 }
218 
220 {
221  std::string attributeStr;
222  // symbolStr end with '_', the whole symbolStr treat as kind, not with attribute.
223  auto underscorePosition = symbolStr.find_last_of("_", symbolStr.size()-1);
224  if (underscorePosition == std::string::npos)
225  {
226  return "";
227  }
228  return symbolStr.substr(underscorePosition+1);
229 }
230 
232 {
233  Symbol symbol;
234  if ((symbolStr.size() == 1) && (!isalpha(symbolStr[0])))
235  {
236  symbol = insertEBNFSigns(symbolStr);
237  }
238  else if (isupper(symbolStr[0]))
239  {
240  symbol = insertNonTerminalSymbol(symbolStr);
241  }
242  else
243  {
244  symbol = insertTerminalSymbol(symbolStr);
245  }
246  return symbol;
247 }
248 
250 {
251  Symbol symbol;
252  std::string kindStr = extractKindStrFromSymbolStr(symbolStr);
253  std::string attributeStr = extractAttributeStrFromSymbolStr(symbolStr);
254  symbol.kind = insertNonterminalKind(kindStr);
255 
256  if ( attributeStr == "") return symbol;
257 
258  if ( (attributeStr.size() == 1) && (std::isalpha(attributeStr[attributeStr.size()-1])) )
259  {
260  attributeKinds.insert(symbol.kind);
261  symbol.variableAttribute = (u32_t)attributeStr[attributeStr.size()-1];
262  }
263  else
264  {
265  for( char &c : attributeStr)
266  {
267  if ( std::isdigit(c) == false )
268  {
269  SVFUtil::errs() << SVFUtil::errMsg("\t Symbol Attribute Parse Failure :") << symbolStr
270  << " Attribute:" << attributeStr << " (only number or single alphabet.)";
271  assert(false && "grammar loading failed!");
272  }
273  }
274  attributeKinds.insert(symbol.kind);
275  symbol.attribute = std::stoi(attributeStr);
276  }
277  return symbol;
278 }
279 
281 {
282  Symbol symbol;
283  std::string kindStr = extractKindStrFromSymbolStr(symbolStr);
284  std::string attributeStr = extractAttributeStrFromSymbolStr(symbolStr);
285  symbol.kind = insertTerminalKind(kindStr);
286 
287  if ( attributeStr == "") return symbol;
288 
289  if ( (attributeStr.size() == 1) && (std::isalpha(attributeStr[attributeStr.size()-1])) )
290  {
291  attributeKinds.insert(symbol.kind);
292  symbol.variableAttribute = (u32_t)attributeStr[attributeStr.size()-1];
293  }
294  else
295  {
296  for( char &c : attributeStr)
297  {
298  if ( std::isdigit(c) == false )
299  {
300  SVFUtil::errs() << SVFUtil::errMsg("\t Symbol Attribute Parse Failure :") << symbolStr
301  << " Attribute:" << attributeStr << " (only number or single alphabet.)";
302  assert(false && "grammar loading failed!");
303  }
304  }
305  attributeKinds.insert(symbol.kind);
306  symbol.attribute = std::stoi(attributeStr);
307  }
308  return symbol;
309 }
310 
312 {
313  Symbol sign;
314  if (EBNFSigns.find(symbolStr) == EBNFSigns.end())
315  {
316  sign = totalKind++;
317  EBNFSigns.insert({symbolStr, sign});
318  }
319  else
320  {
321  sign = strToKind(symbolStr);
322  }
323  return sign;
324 
325 }
326 
328 {
329  attributeKinds.insert(kind);
330  if (kindToAttrsMap.find(kind)!= kindToAttrsMap.end())
331  {
332  kindToAttrsMap[kind].insert(attribute);
333  }
334  else
335  {
336  Set<CFGrammar::Attribute> attrs {attribute};
337  kindToAttrsMap.insert(make_pair(kind, attrs));
338  }
339 }
340 
342 {
344 }
345 
346 void CFGrammar::dump() const
347 {
348  dump("Normailized_Grammar.txt");
349 }
350 
351 void CFGrammar::dump(std::string fileName) const
352 {
353  std::ofstream gramFile(fileName);
354  gramFile << "Start Kind:\n";
355  gramFile << '\t' << kindToStr(startKind) << '(' << startKind << ')' << ' ' << "\n\n";
356 
357  gramFile << "Epsilon Production:\n";
358  std::vector<std::string> strV;
359  for (auto pro: this->epsilonProds)
360  {
361  std::stringstream ss;
362  for (auto sym : pro)
363  {
364  if (sym == pro[1])
365  {
366  ss << "-> ";
367  }
368  ss << symToStrDump(sym) << '(' << sym.kind << ')' << ' ';
369  }
370  strV.insert(strV.begin(), ss.str());
371  }
372  std::sort(strV.begin(), strV.end());
373  for (auto pro: strV)
374  {
375  gramFile << '\t';
376  gramFile << pro;
377  gramFile << '\n';
378  }
379  gramFile << '\n';
380 
381  gramFile << "Single Production:\n";
382  strV = {};
383  for (auto symProPair: singleRHSToProds)
384  {
385  for (auto pro: symProPair.second)
386  {
387  std::stringstream ss;
388  int i = 0;
389  for (auto sym : pro)
390  {
391  i++;
392  if (i == 2)
393  {
394  ss << "-> ";
395  }
396  ss << symToStrDump(sym) << '(' << sym.kind << ')' << ' ';
397  }
398  strV.insert(strV.begin(), ss.str());
399  }
400  }
401  std::sort(strV.begin(), strV.end());
402  for (auto pro: strV)
403  {
404  gramFile << '\t';
405  gramFile << pro;
406  gramFile << '\n';
407  }
408  gramFile << '\n';
409 
410  gramFile << "Binary Production:\n";
411  strV = {};
412  for (auto symProPair: firstRHSToProds)
413  {
414  for (auto pro: symProPair.second)
415  {
416  std::stringstream ss;
417  int i = 0;
418  for (auto sym : pro)
419  {
420  i++;
421 
422  if (i == 2)
423  {
424  ss << "-> ";
425  }
426  ss << symToStrDump(sym) << '(' << sym.kind << ')' << ' ';
427  }
428  strV.insert(strV.begin(), ss.str());
429  }
430  }
431  std::sort(strV.begin(), strV.end());
432  for (auto pro: strV)
433  {
434  gramFile << '\t';
435  gramFile << pro;
436  gramFile << '\n';
437  }
438  gramFile << '\n';
439 
440  gramFile.close();
441 }
#define false
Definition: cJSON.cpp:70
const char *const string
Definition: cJSON.h:172
SymbolMap< Symbol, Productions > firstRHSToProds
Definition: CFGrammar.h:396
void dump() const
Definition: CFGrammar.cpp:346
SymbolSet< Production > epsilonProds
Definition: CFGrammar.h:394
SymbolMap< Symbol, Productions > singleRHSToProds
Definition: CFGrammar.h:395
u32_t newTerminalSubscript
Definition: CFGrammar.h:398
Map< std::string, Kind > terminals
Definition: CFGrammar.h:282
void setKindToAttrsMap(const Map< Kind, Set< Attribute >> &kindToAttrsMap)
Definition: CFGrammar.cpp:45
std::string extractAttributeStrFromSymbolStr(const std::string &symbolStr) const
Definition: CFGrammar.cpp:219
void setAttributeKinds(const Set< Kind > &attributeKind)
Definition: CFGrammar.cpp:50
Symbol insertEBNFSigns(std::string strLit)
Definition: CFGrammar.cpp:311
void setRawProductions(SymbolMap< Symbol, Productions > &rawProductions)
Definition: CFGrammar.cpp:40
std::string extractKindStrFromSymbolStr(const std::string &symbolStr) const
Definition: CFGrammar.cpp:207
Kind strToKind(std::string str) const
Definition: CFGrammar.cpp:55
Symbol insertSymbol(std::string strLit)
Definition: CFGrammar.cpp:231
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > SymbolMap
Definition: CFGrammar.h:150
Symbol strToSymbol(const std::string str) const
Definition: CFGrammar.cpp:74
std::string symToStrDump(Symbol sym) const
Definition: CFGrammar.cpp:139
SymbolMap< Symbol, Productions > rawProductions
Definition: CFGrammar.h:286
Symbol insertNonTerminalSymbol(std::string strLit)
Definition: CFGrammar.cpp:249
Symbol insertTerminalSymbol(std::string strLit)
Definition: CFGrammar.cpp:280
Map< Kind, Set< Attribute > > kindToAttrsMap
Definition: CFGrammar.h:285
Map< std::string, Kind > EBNFSigns
Definition: CFGrammar.h:283
void insertAttribute(Kind kind, Attribute a)
Definition: CFGrammar.cpp:327
Map< std::string, Kind > nonterminals
Definition: CFGrammar.h:281
Kind insertNonterminalKind(std::string const kindStr)
Insert kind to nonterminal and return kind.
Definition: CFGrammar.cpp:192
Set< Kind > attributeKinds
Map contains Signs' String and associated Symbols.
Definition: CFGrammar.h:284
std::string kindToStr(Kind kind) const
Definition: CFGrammar.cpp:103
Kind insertTerminalKind(std::string strLit)
Definition: CFGrammar.cpp:177
int isdigit(int c)
Definition: extapi.c:851
int isupper(int c)
Definition: extapi.c:881
int isalpha(int character)
Definition: extapi.c:836
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
Definition: SVFUtil.cpp:76
std::ostream & errs()
Overwrite llvm::errs()
Definition: SVFUtil.h:56
for isBitcode
Definition: BasicTypes.h:68
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition: GeneralType.h:101
unsigned u32_t
Definition: GeneralType.h:46
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96
VariableAttribute variableAttribute
Definition: CFGrammar.h:46