Static Value-Flow Analysis
Loading...
Searching...
No Matches
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
37using namespace SVF;
38
39
41{
42 this->rawProductions = rawProductions;
43}
44
46{
48}
49
50void 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{
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
103std::string GrammarBase::kindToStr(Kind kind) const
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
207std::string GrammarBase::extractKindStrFromSymbolStr(const std::string& symbolStr) const
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
219std::string GrammarBase::extractAttributeStrFromSymbolStr(const std::string& symbolStr) const
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{
234 if ((symbolStr.size() == 1) && (!isalpha(symbolStr[0])))
235 {
237 }
238 else if (isupper(symbolStr[0]))
239 {
241 }
242 else
243 {
245 }
246 return symbol;
247}
248
250{
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{
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 {
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 {
337 kindToAttrsMap.insert(make_pair(kind, attrs));
338 }
339}
340
345
346void CFGrammar::dump() const
347{
348 dump("Normailized_Grammar.txt");
349}
350
351void 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
SymbolMap< Symbol, Productions > firstRHSToProds
Definition CFGrammar.h:396
void dump() const
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
std::string extractAttributeStrFromSymbolStr(const std::string &symbolStr) const
void setAttributeKinds(const Set< Kind > &attributeKind)
Definition CFGrammar.cpp:50
Symbol insertEBNFSigns(std::string strLit)
void setRawProductions(SymbolMap< Symbol, Productions > &rawProductions)
Definition CFGrammar.cpp:40
std::string extractKindStrFromSymbolStr(const std::string &symbolStr) const
Kind strToKind(std::string str) const
Definition CFGrammar.cpp:55
Symbol insertSymbol(std::string strLit)
Symbol strToSymbol(const std::string str) const
Definition CFGrammar.cpp:74
std::string symToStrDump(Symbol sym) const
SymbolMap< Symbol, Productions > rawProductions
Definition CFGrammar.h:286
Symbol insertNonTerminalSymbol(std::string strLit)
Symbol insertTerminalSymbol(std::string strLit)
Map< Kind, Set< Attribute > > kindToAttrsMap
Definition CFGrammar.h:285
Map< std::string, Kind > EBNFSigns
Definition CFGrammar.h:283
void insertAttribute(Kind kind, Attribute a)
Map< std::string, Kind > nonterminals
Definition CFGrammar.h:281
Kind insertNonterminalKind(std::string const kindStr)
Insert kind to nonterminal and return kind.
Set< Kind > attributeKinds
Map contains Signs' String and associated Symbols.
Definition CFGrammar.h:284
void setKindToAttrsMap(const Map< Kind, Set< Attribute > > &kindToAttrsMap)
Definition CFGrammar.cpp:45
std::string kindToStr(Kind kind) const
Kind insertTerminalKind(std::string strLit)
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:77
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
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
unsigned u32_t
Definition GeneralType.h:46