lambda-graphs 0.1.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. lambda_graphs/__init__.py +18 -0
  2. lambda_graphs/__main__.py +7 -0
  3. lambda_graphs/cli.py +183 -0
  4. lambda_graphs/codeviews/AST/AST.py +120 -0
  5. lambda_graphs/codeviews/AST/AST_driver.py +37 -0
  6. lambda_graphs/codeviews/AST/__init__.py +0 -0
  7. lambda_graphs/codeviews/CFG/CFG.py +42 -0
  8. lambda_graphs/codeviews/CFG/CFG_c.py +1182 -0
  9. lambda_graphs/codeviews/CFG/CFG_cpp.py +5604 -0
  10. lambda_graphs/codeviews/CFG/CFG_driver.py +45 -0
  11. lambda_graphs/codeviews/CFG/CFG_java.py +1722 -0
  12. lambda_graphs/codeviews/CFG/__init__.py +0 -0
  13. lambda_graphs/codeviews/CST/CST_driver.py +70 -0
  14. lambda_graphs/codeviews/CST/__init__.py +0 -0
  15. lambda_graphs/codeviews/DFG/DFG_driver.py +42 -0
  16. lambda_graphs/codeviews/DFG/__init__.py +0 -0
  17. lambda_graphs/codeviews/SDFG/SDFG.py +135 -0
  18. lambda_graphs/codeviews/SDFG/SDFG_c.py +2041 -0
  19. lambda_graphs/codeviews/SDFG/SDFG_cpp.py +4030 -0
  20. lambda_graphs/codeviews/SDFG/SDFG_java.py +1618 -0
  21. lambda_graphs/codeviews/SDFG/__init__.py +0 -0
  22. lambda_graphs/codeviews/__init__.py +0 -0
  23. lambda_graphs/codeviews/combined_graph/__init__.py +0 -0
  24. lambda_graphs/codeviews/combined_graph/combined_driver.py +163 -0
  25. lambda_graphs/tree_parser/__init__.py +0 -0
  26. lambda_graphs/tree_parser/c_parser.py +565 -0
  27. lambda_graphs/tree_parser/cpp_parser.py +424 -0
  28. lambda_graphs/tree_parser/custom_parser.py +66 -0
  29. lambda_graphs/tree_parser/java_parser.py +254 -0
  30. lambda_graphs/tree_parser/parser_driver.py +54 -0
  31. lambda_graphs/utils/DFG_utils.py +44 -0
  32. lambda_graphs/utils/__init__.py +0 -0
  33. lambda_graphs/utils/c_nodes.py +431 -0
  34. lambda_graphs/utils/cpp_nodes.py +1331 -0
  35. lambda_graphs/utils/java_nodes.py +756 -0
  36. lambda_graphs/utils/multi_file_merger.py +444 -0
  37. lambda_graphs/utils/postprocessor.py +83 -0
  38. lambda_graphs/utils/preprocessor.py +68 -0
  39. lambda_graphs/utils/src_parser.py +23 -0
  40. lambda_graphs-0.1.4.dist-info/METADATA +380 -0
  41. lambda_graphs-0.1.4.dist-info/RECORD +45 -0
  42. lambda_graphs-0.1.4.dist-info/WHEEL +5 -0
  43. lambda_graphs-0.1.4.dist-info/entry_points.txt +2 -0
  44. lambda_graphs-0.1.4.dist-info/licenses/LICENSE +21 -0
  45. lambda_graphs-0.1.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,254 @@
1
+ from .custom_parser import CustomParser
2
+
3
+
4
+ class JavaParser(CustomParser):
5
+ def __init__(self, src_language, src_code):
6
+ super().__init__(src_language, src_code)
7
+
8
+ def check_declaration(self, current_node):
9
+
10
+ # node_list_type = ['local_variable_declaration','declaration', 'expression_statement', 'labeled_statement', 'if_statement', 'while_statement', 'for_statement', 'enhanced_for_statement', 'assert_statement', 'do_statement', 'break_statement', 'continue_statement', 'return_statement', 'yield_statement', 'switch_expression', 'synchronized_statement', 'local_variable_declaration', 'throw_statement', 'try_statement', 'try_with_resources_statement', 'method_declaration','constructor_declaration', 'switch_block_statement_group', 'switch_rule', 'throw_statement', 'explicit_constructor_invocation']
11
+ parent_types = [
12
+ "variable_declarator",
13
+ "catch_formal_parameter",
14
+ "formal_parameter",
15
+ ]
16
+ current_types = ["identifier"]
17
+ if (
18
+ current_node.parent is not None
19
+ and current_node.parent.type in parent_types
20
+ and current_node.type in current_types
21
+ ):
22
+ if current_node.parent.type == "variable_declarator":
23
+ # TODO: If it is a class attribute need to maintain class_name.class_variable so that the correct datatype can be mapped
24
+ if (
25
+ len(
26
+ list(
27
+ filter(
28
+ lambda x: x.type == "=", current_node.parent.children
29
+ )
30
+ )
31
+ )
32
+ > 0
33
+ ):
34
+ if (
35
+ current_node.next_sibling is not None
36
+ and current_node.next_sibling.type == "="
37
+ ):
38
+ return True
39
+ else:
40
+ return False
41
+ else:
42
+ return True
43
+ return True
44
+ return False
45
+
46
+ def get_type(self, node):
47
+ """Given a variable declarator node, return the variable type of the identifier"""
48
+ datatypes = [
49
+ "type_identifier",
50
+ "integral_type",
51
+ "floating_point_type",
52
+ "void_type",
53
+ "boolean_type",
54
+ "scoped_type_identifier",
55
+ "generic_type",
56
+ ]
57
+ if node.type == "formal_parameter":
58
+ return node.children[0].text.decode("utf-8")
59
+
60
+ for child in node.parent.children:
61
+ if child.type in datatypes:
62
+ return child.text.decode("utf-8")
63
+ return None
64
+
65
+ def scope_check(self, parent_scope, child_scope):
66
+ for p in parent_scope:
67
+ if p not in child_scope:
68
+ return False
69
+ return True
70
+
71
+ def longest_scope_match(self, name_matches, symbol_table):
72
+ """Given a list of name matches, return the longest scope match"""
73
+ # [(ind, var), (ind,var)]
74
+ scope_array = list(map(lambda x: symbol_table["scope_map"][x[0]], name_matches))
75
+ # scope_array.sort(key=lambda x: len(x), reverse=True)
76
+ # index = max(range(len(scope_array)), key=lambda x: len(x))
77
+ max_val = max(scope_array, key=lambda x: len(x))
78
+ for i in range(len(scope_array)):
79
+ if scope_array[i] == max_val:
80
+ return name_matches[i][0]
81
+
82
+ def create_all_tokens(
83
+ self,
84
+ src_code,
85
+ root_node,
86
+ all_tokens,
87
+ label,
88
+ method_map,
89
+ method_calls,
90
+ start_line,
91
+ declaration,
92
+ declaration_map,
93
+ symbol_table,
94
+ ):
95
+ # Needs to be modifed for every language
96
+ remove_list = ["class_declaration", "method_declaration", "method_invocation"]
97
+ # node_list_type = ['local_variable_declaration', 'declaration', 'expression_statement', 'labeled_statement',
98
+ # 'if_statement', 'while_statement', 'for_statement', 'enhanced_for_statement',
99
+ # 'assert_statement', 'do_statement', 'break_statement', 'continue_statement',
100
+ # 'return_statement', 'yield_statement', 'synchronized_statement',
101
+ # 'local_variable_declaration', 'throw_statement', 'try_statement',
102
+ # 'try_with_resources_statement', 'method_declaration', 'constructor_declaration',
103
+ # 'switch_expression', 'switch_block_statement_group', 'switch_rule', 'throw_statement',
104
+ # 'explicit_constructor_invocation']
105
+ block_types = [
106
+ "block",
107
+ "if_statement",
108
+ "while_statement",
109
+ "for_statement",
110
+ "enhanced_for_statement",
111
+ "do_statement",
112
+ "switch_expression",
113
+ "switch_block_statement_group",
114
+ "switch_rule",
115
+ "throw_statement",
116
+ "synchronized_statement",
117
+ "try_statement",
118
+ "try_with_resources_statement",
119
+ "method_declaration",
120
+ "constructor_declaration",
121
+ "explicit_constructor_invocation",
122
+ ]
123
+
124
+ if root_node.is_named and root_node.type in block_types:
125
+ """On entering a new block, increment the scope id and push it to the scope_stack"""
126
+ # current_scope = symbol_table['scope_stack'][-1]
127
+ symbol_table["scope_id"] = symbol_table["scope_id"] + 1
128
+ symbol_table["scope_stack"].append(symbol_table["scope_id"])
129
+
130
+ if (
131
+ root_node.is_named
132
+ and (len(root_node.children) == 0 or root_node.type == "string")
133
+ and root_node.type != "comment"
134
+ ): # All identifiers
135
+ index = self.index[
136
+ (root_node.start_point, root_node.end_point, root_node.type)
137
+ ]
138
+ label[index] = root_node.text.decode("UTF-8")
139
+ start_line[index] = root_node.start_point[0]
140
+ all_tokens.append(index)
141
+ """Store a copy of the current scope stack in the scope map for each token. This token belongs to all the scopes in the current scope stack."""
142
+
143
+ symbol_table["scope_map"][index] = symbol_table["scope_stack"].copy()
144
+
145
+ current_node = root_node
146
+ if (
147
+ current_node.parent is not None
148
+ and current_node.parent.type in remove_list
149
+ ):
150
+ method_map.append(index)
151
+ if current_node.next_named_sibling.type == "argument_list":
152
+ method_calls.append(index)
153
+
154
+ if (
155
+ current_node.parent is not None
156
+ and current_node.parent.type == "field_access"
157
+ ):
158
+ object_node = current_node.parent.child_by_field_name("field")
159
+ object_index = self.index[
160
+ (object_node.start_point, object_node.end_point, object_node.type)
161
+ ]
162
+ current_index = self.index[
163
+ (
164
+ current_node.start_point,
165
+ current_node.end_point,
166
+ current_node.type,
167
+ )
168
+ ]
169
+ if object_index == current_index:
170
+ method_map.append(current_index)
171
+
172
+ while (
173
+ current_node.parent is not None
174
+ and current_node.parent.type == "field_access"
175
+ ):
176
+ current_node = current_node.parent
177
+
178
+ if (
179
+ current_node.parent is not None
180
+ and current_node.parent.type == "method_invocation"
181
+ ):
182
+ method_map.append(index)
183
+ label[index] = current_node.text.decode("UTF-8")
184
+
185
+ if self.check_declaration(current_node):
186
+ variable_name = label[index]
187
+ declaration[index] = variable_name
188
+
189
+ variable_type = self.get_type(current_node.parent)
190
+ if variable_type is not None:
191
+ symbol_table["data_type"][index] = variable_type
192
+ else:
193
+ current_scope = symbol_table["scope_map"][index]
194
+
195
+ if current_node.type == "field_access":
196
+ field_variable = current_node.children[-1]
197
+ # entire_variable_name = current_node.text.decode('utf-8')
198
+ field_variable_name = field_variable.text.decode("utf-8")
199
+
200
+ for ind, var in declaration.items():
201
+ if var == field_variable_name:
202
+ parent_scope = symbol_table["scope_map"][ind]
203
+ if self.scope_check(parent_scope, current_scope):
204
+ declaration_map[index] = ind
205
+ break
206
+
207
+ # Identify the leftmost - that is the reference - identify its class
208
+ # TODO: Handle field accesses
209
+ # If we can add the coorect declaration_map entry, we should be done.
210
+ # For this we need to identify the class to which it belongs, and the corresponding field variable
211
+ else:
212
+ name_matches = []
213
+ for ind, var in declaration.items():
214
+ if var == label[index]:
215
+ parent_scope = symbol_table["scope_map"][ind]
216
+ if self.scope_check(parent_scope, current_scope):
217
+ name_matches.append((ind, var))
218
+ for ind, var in name_matches:
219
+ parent_scope = symbol_table["scope_map"][ind]
220
+ closest_index = self.longest_scope_match(
221
+ name_matches, symbol_table
222
+ )
223
+ declaration_map[index] = closest_index
224
+ break
225
+
226
+ else:
227
+ for child in root_node.children:
228
+ self.create_all_tokens(
229
+ src_code,
230
+ child,
231
+ all_tokens,
232
+ label,
233
+ method_map,
234
+ method_calls,
235
+ start_line,
236
+ declaration,
237
+ declaration_map,
238
+ symbol_table,
239
+ )
240
+
241
+ if root_node.is_named and root_node.type in block_types:
242
+ """On exiting a block, pop the scope id from the scope_stack"""
243
+ symbol_table["scope_stack"].pop(-1)
244
+
245
+ return (
246
+ all_tokens,
247
+ label,
248
+ method_map,
249
+ method_calls,
250
+ start_line,
251
+ declaration,
252
+ declaration_map,
253
+ symbol_table,
254
+ )
@@ -0,0 +1,54 @@
1
+ from ..tree_parser.c_parser import CParser
2
+ from ..tree_parser.cpp_parser import CppParser
3
+ from ..tree_parser.java_parser import JavaParser
4
+ from ..utils import preprocessor
5
+
6
+
7
+ class ParserDriver:
8
+ """Driver class for the parser"""
9
+
10
+ def __init__(self, src_language, src_code):
11
+ """Initialize the driver. Preprocess the code before parsing"""
12
+ self.src_language = src_language
13
+ self.src_code = self.pre_process_src_code(src_language, src_code)
14
+
15
+ self.parser_map = {
16
+ "c": CParser,
17
+ "cpp": CppParser,
18
+ "java": JavaParser,
19
+ }
20
+ self.parser = self.parser_map[self.src_language](
21
+ self.src_language, self.src_code
22
+ )
23
+ self.root_node, self.tree = self.parser.parse()
24
+ (
25
+ self.all_tokens,
26
+ self.label,
27
+ self.method_map,
28
+ self.method_calls,
29
+ self.start_line,
30
+ self.declaration,
31
+ self.declaration_map,
32
+ self.symbol_table,
33
+ ) = self.create_all_tokens()
34
+
35
+ def pre_process_src_code(self, src_language, src_code):
36
+ """Pre-process the source code"""
37
+ src_code = preprocessor.remove_empty_lines(src_code)
38
+ src_code = preprocessor.remove_comments(src_language, src_code)
39
+ return src_code
40
+
41
+ def create_all_tokens(self):
42
+ """Return the variable list"""
43
+ return self.parser.create_all_tokens(
44
+ self.src_code,
45
+ self.parser.root_node,
46
+ self.parser.all_tokens,
47
+ self.parser.label,
48
+ self.parser.method_map,
49
+ self.parser.method_calls,
50
+ self.parser.start_line,
51
+ self.parser.declaration,
52
+ self.parser.declaration_map,
53
+ self.parser.symbol_table,
54
+ )
@@ -0,0 +1,44 @@
1
+ def tree_to_token_index(root_node):
2
+ """Returns all tokens in the tree rooted at the given root node using index values"""
3
+ if (
4
+ len(root_node.children) == 0 or root_node.type == "string"
5
+ ) and root_node.type != "comment":
6
+ return [(root_node.start_point, root_node.end_point, root_node.type)]
7
+ else:
8
+ code_tokens = []
9
+ for child in root_node.children:
10
+ code_tokens += tree_to_token_index(child)
11
+ return code_tokens
12
+
13
+
14
+ def tree_to_variable_index(root_node, index_to_code):
15
+ """Returns all tokens in the tree rooted at the given root node"""
16
+ if (
17
+ len(root_node.children) == 0 or root_node.type == "string"
18
+ ) and root_node.type != "comment":
19
+ index = (root_node.start_point, root_node.end_point, root_node.type)
20
+ _, code = index_to_code[index]
21
+ if root_node.type != code:
22
+ return [(root_node.start_point, root_node.end_point, root_node.type)]
23
+ else:
24
+ return []
25
+ else:
26
+ code_tokens = []
27
+ for child in root_node.children:
28
+ code_tokens += tree_to_variable_index(child, index_to_code)
29
+ return code_tokens
30
+
31
+
32
+ def index_to_code_token(index, code):
33
+ """Returns code value given the indexes of a particular token"""
34
+ start_point = index[0]
35
+ end_point = index[1]
36
+ if start_point[0] == end_point[0]:
37
+ s = code[start_point[0]][start_point[1] : end_point[1]]
38
+ else:
39
+ s = ""
40
+ s += code[start_point[0]][start_point[1] :]
41
+ for i in range(start_point[0] + 1, end_point[0]):
42
+ s += code[i]
43
+ s += code[end_point[0]][: end_point[1]]
44
+ return s
File without changes