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
33#include <algorithm>
34#include <string>
35#include <iostream>
36#include <fstream>
37#include <sstream>
38
39using namespace SVF;
40
41
43{
44 this->rawProductions = rawProductions;
45}
46
48{
50}
51
52void GrammarBase::setAttributeKinds(const Set<Kind>& attributeKinds)
53{
54 this->attributeKinds = attributeKinds;
55}
56
58{
59
60 auto tit = terminals.find(str);
61 if(tit!=terminals.end())
62 return tit->second;
63
64 auto nit = nonterminals.find(str);
65 if(nit!=nonterminals.end())
66 return nit->second;
67
68 auto sit = EBNFSigns.find(str);
69 if(sit!=EBNFSigns.end())
70 return sit->second;
71
72 assert(false && "kind not found!");
73 abort();
74}
75
77{
81 symbol.kind = strToKind(kindStr);
82
83 if ( attributeStr == "") return symbol;
84
85 if ( (attributeStr.size() == 1) && (std::isalpha(attributeStr[attributeStr.size()-1])) )
86 {
87 symbol.variableAttribute = (u32_t)attributeStr[attributeStr.size()-1];
88 }
89 else
90 {
91 for( char &c : attributeStr)
92 {
93 if ( std::isdigit(c) == false )
94 {
95 SVFUtil::errs() << SVFUtil::errMsg("\t Symbol Attribute Parse Failure :") << str
96 << " Attribute:" << attributeStr << " (only number or single alphabet.)";
97 assert(false && "grammar loading failed!");
98 }
99 }
100 symbol.attribute = std::stoi(attributeStr);
101 }
102 return symbol;
103}
104
105std::string GrammarBase::kindToStr(Kind kind) const
106{
107
108 std::string key = "";
109 for (auto &i : terminals)
110 {
111 if (i.second == kind)
112 {
113 key = i.first;
114 return key;
115 }
116 }
117
118 std::string nkey = "";
119 for (auto &ni : nonterminals)
120 {
121 if (ni.second == kind)
122 {
123 nkey = ni.first;
124 return nkey;
125 }
126 }
127
128 std::string signs = "";
129 for (auto &i : EBNFSigns)
130 {
131 if (i.second == kind)
132 {
133 signs = i.first;
134 return signs;
135 }
136 }
137
138 return "";
139}
140
142{
143 Kind kind = sym.kind;
144 Attribute attribute = sym.attribute;
145
146 std::string key = "";
147 for (auto &i : terminals)
148 {
149 if (i.second == kind)
150 {
151 key = i.first;
152 if(attribute != 0)
153 {
154 key.append("_");
155 key.append(std::to_string(attribute));
156 }
157 return key;
158 }
159 }
160
161 std::string nkey = "";
162 for (auto &ni : nonterminals)
163 {
164 if (ni.second == kind)
165 {
166 nkey = ni.first;
167 if(attribute != 0)
168 {
169 nkey.append("_");
170 nkey.append(std::to_string(attribute));
171 }
172 return nkey;
173 }
174 }
175
176 return "";
177}
178
180{
181 Kind kind;
182 if (terminals.find(kindStr) == terminals.end())
183 {
184 kind = totalKind++;
185 terminals.insert({kindStr, kind});
186 }
187 else
188 {
189 kind = strToKind(kindStr);
190 }
191 return kind;
192}
193
195{
196 Kind kind;
197 if (nonterminals.find(kindStr) == nonterminals.end())
198 {
199 kind = totalKind++;
200 nonterminals.insert({kindStr, kind});
201 }
202 else
203 {
204 kind = strToKind(kindStr);
205 }
206 return kind;
207}
208
209std::string GrammarBase::extractKindStrFromSymbolStr(const std::string& symbolStr) const
210{
211 std::string kindStr;
212 // symbolStr end with '_', the whole symbolStr treat as kind, not with attribute.
213 auto underscorePosition = symbolStr.find_last_of("_", symbolStr.size()-1);
214 if (underscorePosition == std::string::npos)
215 {
216 return symbolStr;
217 }
218 return symbolStr.substr(0, underscorePosition);
219}
220
221std::string GrammarBase::extractAttributeStrFromSymbolStr(const std::string& symbolStr) const
222{
223 std::string attributeStr;
224 // symbolStr end with '_', the whole symbolStr treat as kind, not with attribute.
225 auto underscorePosition = symbolStr.find_last_of("_", symbolStr.size()-1);
226 if (underscorePosition == std::string::npos)
227 {
228 return "";
229 }
230 return symbolStr.substr(underscorePosition+1);
231}
232
234{
236 if ((symbolStr.size() == 1) && (!isalpha(symbolStr[0])))
237 {
239 }
240 else if (isupper(symbolStr[0]))
241 {
243 }
244 else
245 {
247 }
248 return symbol;
249}
250
252{
257
258 if ( attributeStr == "") return symbol;
259
260 if ( (attributeStr.size() == 1) && (std::isalpha(attributeStr[attributeStr.size()-1])) )
261 {
262 attributeKinds.insert(symbol.kind);
263 symbol.variableAttribute = (u32_t)attributeStr[attributeStr.size()-1];
264 }
265 else
266 {
267 for( char &c : attributeStr)
268 {
269 if ( std::isdigit(c) == false )
270 {
271 SVFUtil::errs() << SVFUtil::errMsg("\t Symbol Attribute Parse Failure :") << symbolStr
272 << " Attribute:" << attributeStr << " (only number or single alphabet.)";
273 assert(false && "grammar loading failed!");
274 }
275 }
276 attributeKinds.insert(symbol.kind);
277 symbol.attribute = std::stoi(attributeStr);
278 }
279 return symbol;
280}
281
283{
288
289 if ( attributeStr == "") return symbol;
290
291 if ( (attributeStr.size() == 1) && (std::isalpha(attributeStr[attributeStr.size()-1])) )
292 {
293 attributeKinds.insert(symbol.kind);
294 symbol.variableAttribute = (u32_t)attributeStr[attributeStr.size()-1];
295 }
296 else
297 {
298 for( char &c : attributeStr)
299 {
300 if ( std::isdigit(c) == false )
301 {
302 SVFUtil::errs() << SVFUtil::errMsg("\t Symbol Attribute Parse Failure :") << symbolStr
303 << " Attribute:" << attributeStr << " (only number or single alphabet.)";
304 assert(false && "grammar loading failed!");
305 }
306 }
307 attributeKinds.insert(symbol.kind);
308 symbol.attribute = std::stoi(attributeStr);
309 }
310 return symbol;
311}
312
314{
315 Symbol sign;
316 if (EBNFSigns.find(symbolStr) == EBNFSigns.end())
317 {
318 sign = totalKind++;
319 EBNFSigns.insert({symbolStr, sign});
320 }
321 else
322 {
324 }
325 return sign;
326
327}
328
330{
331 attributeKinds.insert(kind);
332 if (kindToAttrsMap.find(kind)!= kindToAttrsMap.end())
333 {
334 kindToAttrsMap[kind].insert(attribute);
335 }
336 else
337 {
339 kindToAttrsMap.insert(make_pair(kind, attrs));
340 }
341}
342
347
348void CFGrammar::dump() const
349{
350 dump("Normailized_Grammar.txt");
351}
352
353void CFGrammar::dump(std::string fileName) const
354{
355 std::ofstream gramFile(fileName);
356 gramFile << "Start Kind:\n";
357 gramFile << '\t' << kindToStr(startKind) << '(' << startKind << ')' << ' ' << "\n\n";
358
359 gramFile << "Epsilon Production:\n";
360 std::vector<std::string> strV;
361 for (auto pro: this->epsilonProds)
362 {
363 std::stringstream ss;
364 for (auto sym : pro)
365 {
366 if (sym == pro[1])
367 {
368 ss << "-> ";
369 }
370 ss << symToStrDump(sym) << '(' << sym.kind << ')' << ' ';
371 }
372 strV.insert(strV.begin(), ss.str());
373 }
374 std::sort(strV.begin(), strV.end());
375 for (auto pro: strV)
376 {
377 gramFile << '\t';
378 gramFile << pro;
379 gramFile << '\n';
380 }
381 gramFile << '\n';
382
383 gramFile << "Single Production:\n";
384 strV = {};
385 for (auto symProPair: singleRHSToProds)
386 {
387 for (auto pro: symProPair.second)
388 {
389 std::stringstream ss;
390 int i = 0;
391 for (auto sym : pro)
392 {
393 i++;
394 if (i == 2)
395 {
396 ss << "-> ";
397 }
398 ss << symToStrDump(sym) << '(' << sym.kind << ')' << ' ';
399 }
400 strV.insert(strV.begin(), ss.str());
401 }
402 }
403 std::sort(strV.begin(), strV.end());
404 for (auto pro: strV)
405 {
406 gramFile << '\t';
407 gramFile << pro;
408 gramFile << '\n';
409 }
410 gramFile << '\n';
411
412 gramFile << "Binary Production:\n";
413 strV = {};
414 for (auto symProPair: firstRHSToProds)
415 {
416 for (auto pro: symProPair.second)
417 {
418 std::stringstream ss;
419 int i = 0;
420 for (auto sym : pro)
421 {
422 i++;
423
424 if (i == 2)
425 {
426 ss << "-> ";
427 }
428 ss << symToStrDump(sym) << '(' << sym.kind << ')' << ' ';
429 }
430 strV.insert(strV.begin(), ss.str());
431 }
432 }
433 std::sort(strV.begin(), strV.end());
434 for (auto pro: strV)
435 {
436 gramFile << '\t';
437 gramFile << pro;
438 gramFile << '\n';
439 }
440 gramFile << '\n';
441
442 gramFile.close();
443}
#define false
Definition cJSON.cpp:70
SymbolMap< Symbol, Productions > firstRHSToProds
Definition CFGrammar.h:400
void dump() const
SymbolSet< Production > epsilonProds
Definition CFGrammar.h:398
SymbolMap< Symbol, Productions > singleRHSToProds
Definition CFGrammar.h:399
u32_t newTerminalSubscript
Definition CFGrammar.h:402
Map< std::string, Kind > terminals
Definition CFGrammar.h:286
std::string extractAttributeStrFromSymbolStr(const std::string &symbolStr) const
void setAttributeKinds(const Set< Kind > &attributeKind)
Definition CFGrammar.cpp:52
Symbol insertEBNFSigns(std::string strLit)
void setRawProductions(SymbolMap< Symbol, Productions > &rawProductions)
Definition CFGrammar.cpp:42
std::string extractKindStrFromSymbolStr(const std::string &symbolStr) const
Kind strToKind(std::string str) const
Definition CFGrammar.cpp:57
Symbol insertSymbol(std::string strLit)
Symbol strToSymbol(const std::string str) const
Definition CFGrammar.cpp:76
std::string symToStrDump(Symbol sym) const
SymbolMap< Symbol, Productions > rawProductions
Definition CFGrammar.h:290
Symbol insertNonTerminalSymbol(std::string strLit)
Symbol insertTerminalSymbol(std::string strLit)
Map< Kind, Set< Attribute > > kindToAttrsMap
Definition CFGrammar.h:289
Map< std::string, Kind > EBNFSigns
Definition CFGrammar.h:287
void insertAttribute(Kind kind, Attribute a)
Map< std::string, Kind > nonterminals
Definition CFGrammar.h:285
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:288
void setKindToAttrsMap(const Map< Kind, Set< Attribute > > &kindToAttrsMap)
Definition CFGrammar.cpp:47
std::string kindToStr(Kind kind) const
Kind insertTerminalKind(std::string strLit)
int isupper(int c)
Definition extapi.c:1004
int isalpha(int character)
Definition extapi.c:959
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
Definition SVFUtil.cpp:82
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:58
for isBitcode
Definition BasicTypes.h:70
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition GeneralType.h:56
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
unsigned u32_t
Definition GeneralType.h:67