-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbinary_tree.cpp
307 lines (281 loc) · 9.45 KB
/
binary_tree.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
/*
* SET07109 Coursework 2: Implementing a binary search tree (Part B)
* -----------------------------------------------------------------
* implementation functions for reading and writing to files
* - using binary trees
* author: Vinh Phat Tu (40507973)
* last date of modification: April 2021
*/
#include "Identifier.hpp"
#include "binary_tree.hpp"
#include "formatting.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
/*
* Function: read_CFile
* --------------------
* reads .c files line by line:
* - using stringstream split into tokens:
* - look for variables and functions
* - add them to tree or increase references
*
* parameter: CFile_name - name of the .c file to be read
*
* returns: unique_ptr<Node> - smart pointer to top node of tree
* - a binary tree containing all identifiers
*/
unique_ptr<Node> read_CFile(const string &CFile_name)
{
//Top node of the binary tree
unique_ptr<Node> tree;
//General string vectors for keeping track of identifiers
vector<string> identifier_names;
vector<string> all_identifier_names;
vector<string> function_strings;
//Arrays for checking C related keywords
const string primitives[] = {"char*", "short*", "int*", "long*", "float*", "double*",
"char", "short", "int", "long", "float", "double", "void"};
const string conditions[3] = {"if","for","while"};
int condition_quantities[3] = {0};
//Line counter
int line_number = 0;
//Variable to store the current function name
string function_name;
//Temporary variables for reading in strings and looping through tokens
string line;
string token;
//Reading in .c file
ifstream input_CFile(CFile_name);
while(getline(input_CFile, line))
{
line_number++;
stringstream stream(line);
while(stream >> token)
{
/*
* Look for references
* -------------------
* Loop through all local identifiers
* - If name is equal to token -> create a temporary node with name
*/
for (auto identifier : identifier_names)
{
vector<string> temp;
if (identifier.find("(") != string::npos)
{
temp = string_split(identifier, ' ');
}
else
{
temp.push_back(identifier);
}
if (token == temp[0])
{
auto temp = make_shared<Identifier>("", identifier, 0);
insert(tree,temp);
}
}
/*
* Look for declarations
* ---------------------
* Token pattern of declarations:
* - type, name... -> Variable
* or
* - type, name, (... -> Function
*
* ex.
* "int a = 1;" -> type = int, name = a
*/
for (auto primitive : primitives)
{
if (token == primitive)
{
string type = primitive;
stream >> token;
/*
* If the next token is the same as the previous one
* ex. "long long"
* - assign it to type
* - go to next token
*/
if (token == type)
{
type += " " + type;
stream >> token;
}
string name = token;
stream >> token;
/*
* If the token is "(" -> Function
* - Add function name to function_string
* - Add new node in tree
* - Assign name of function to function_name
* - Copy all variable names in identifier_names to all_identifier_names
* - Clear identifier_names
* - Add all function names to identifier_names
* ----------------------------------------------------------------------
* Else -> Variable
* - Look for [] (array declaration)
* - If true, add [] to type
* - Add variable name to identifier_names
* - Add new node in tree
*/
if (token == "(") //Function
{
auto func = make_shared<Identifier>(type, name, line_number);
insert(tree, func);
function_name = name;
function_strings.push_back(name);
for (auto identifier_name : identifier_names)
{
if (identifier_name.find("(") != string::npos)
{
all_identifier_names.push_back(identifier_name);
}
}
identifier_names.clear();
for (auto function_string : function_strings)
{
identifier_names.push_back(function_string);
}
break;
}
else //Variable
{
if (token == "[]")
{
type += " []";
}
string var_name = name + " (" + function_name + ")";
auto var = make_shared<Identifier>(type, var_name, line_number);
insert(tree, var);
identifier_names.push_back(var_name);
break;
}
}
}
/*
* Look for if,for and while
* -------------------------
* Loop through array of keywords,
* - If keyword is found,
* - Increment at current index in quantities array
*/
for (int i = 0; i < 3; i++)
{
if (conditions[i] == token)
{
condition_quantities[i]++;
}
}
}
}
return tree;
}
/*
* Function: insert
* ----------------
* inserts Identifier into binary tree
* or adds reference if it already exists
*
* parameters:
* - node: smart pointer to tree node
* - identifier: identifier to be added/updated
*
* returns: void
* - new node is created
* - or a reference is added
*
*/
void insert(unique_ptr<Node> &node, const shared_ptr<Identifier> &identifier)
{
if (node == nullptr)
{
node = make_unique<Node>(identifier);
}
else
{
if (identifier->get_name() < node->identifier->get_name())
{
insert(node->left_node, identifier);
}
else if (identifier->get_name() > node->identifier->get_name())
{
insert(node->right_node, identifier);
}
else
{
node->identifier->add_reference();
}
}
}
/*
* Function: print_inorder
* -----------------------
* prints all the nodes in alphabetical order
* using recursion
*
* parameter: tree - top node of binary tree
*
* returns: void
* - prints all the nodes to console
*/
void print_inorder(const unique_ptr<Node> &tree)
{
if (tree != nullptr)
{
//Prints all in alphabetical order
print_inorder(tree->left_node);
cout << tree->identifier->get_name() << ", line ";
cout << tree->identifier->get_line_number() << ", ";
if (tree->identifier->get_name().find("(") != string::npos)
{
cout << "variable, ";
}
else
{
cout << "function, ";
}
cout << tree->identifier->get_type() << ", referenced ";
cout << tree->identifier->get_references() << endl;
print_inorder(tree->right_node);
}
}
/*
* Function: write_inorder
* -----------------------
* writes all the nodes in alphabetical order
* to .txt file
* using recursion
*
* parameters:
* - tree - top node of binary tree
* - file - .txt file
*
* returns: void
* - writes all the nodes to .txt file
*/
void write_inorder(const unique_ptr<Node> &tree, ofstream &file)
{
if (tree != nullptr)
{
//Print the most left nodes
write_inorder(tree->left_node, file);
file << tree->identifier->get_name() << ", line ";
file << tree->identifier->get_line_number() << ", ";
if (tree->identifier->get_name().find("(") != string::npos)
{
file << "variable, ";
}
else
{
file << "function, ";
}
file << tree->identifier->get_type() << ", referenced ";
file << tree->identifier->get_references() << endl;
//Print the most right nodes
write_inorder(tree->right_node, file);
}
}