marluwe commited on
Commit
e6d77be
·
verified ·
1 Parent(s): ae7a494

Create JavaScriptToPythonConverter.py

Browse files
Files changed (1) hide show
  1. tools/JavaScriptToPythonConverter.py +207 -0
tools/JavaScriptToPythonConverter.py ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import esprima # For parsing JavaScript
2
+ import ast # For Python AST manipulation
3
+ from typing import Union, Dict, List, Any
4
+
5
+ class JavaScriptToPythonConverter:
6
+ def __init__(self):
7
+ self.variable_map: Dict[str, str] = {}
8
+
9
+ def convert_js_to_python(self, js_code: str) -> str:
10
+ """
11
+ Convert JavaScript code to Python code.
12
+
13
+ Args:
14
+ js_code (str): JavaScript code to convert
15
+
16
+ Returns:
17
+ str: Converted Python code
18
+ """
19
+ try:
20
+ # Parse JavaScript code into AST
21
+ js_ast = esprima.parseScript(js_code)
22
+
23
+ # Convert the AST to Python code
24
+ python_code = self._convert_node(js_ast)
25
+
26
+ return python_code
27
+
28
+ except Exception as e:
29
+ raise ValueError(f"Failed to convert JavaScript code: {str(e)}")
30
+
31
+ def _convert_node(self, node: Any) -> str:
32
+ """Convert a JavaScript AST node to Python code."""
33
+ node_type = node.type if hasattr(node, 'type') else type(node).__name__
34
+
35
+ # Map of JavaScript node types to conversion methods
36
+ converters = {
37
+ 'Program': self._convert_program,
38
+ 'VariableDeclaration': self._convert_variable_declaration,
39
+ 'FunctionDeclaration': self._convert_function_declaration,
40
+ 'ExpressionStatement': self._convert_expression_statement,
41
+ 'BinaryExpression': self._convert_binary_expression,
42
+ 'Identifier': self._convert_identifier,
43
+ 'Literal': self._convert_literal,
44
+ 'CallExpression': self._convert_call_expression,
45
+ 'ReturnStatement': self._convert_return_statement,
46
+ 'IfStatement': self._convert_if_statement,
47
+ 'ForStatement': self._convert_for_statement,
48
+ 'WhileStatement': self._convert_while_statement
49
+ }
50
+
51
+ converter = converters.get(node_type)
52
+ if converter:
53
+ return converter(node)
54
+ else:
55
+ raise ValueError(f"Unsupported node type: {node_type}")
56
+
57
+ def _convert_program(self, node: Any) -> str:
58
+ """Convert a JavaScript program node to Python code."""
59
+ return '\n'.join(self._convert_node(stmt) for stmt in node.body)
60
+
61
+ def _convert_variable_declaration(self, node: Any) -> str:
62
+ """Convert JavaScript variable declarations to Python assignments."""
63
+ declarations = []
64
+ for decl in node.declarations:
65
+ var_name = decl.id.name
66
+ self.variable_map[var_name] = var_name
67
+
68
+ if decl.init:
69
+ init = self._convert_node(decl.init)
70
+ declarations.append(f"{var_name} = {init}")
71
+ else:
72
+ declarations.append(f"{var_name} = None")
73
+
74
+ return '\n'.join(declarations)
75
+
76
+ def _convert_function_declaration(self, node: Any) -> str:
77
+ """Convert JavaScript function declarations to Python functions."""
78
+ func_name = node.id.name
79
+ params = [param.name for param in node.params]
80
+ body = self._convert_node(node.body)
81
+
82
+ return f"def {func_name}({', '.join(params)}):\n{self._indent(body)}"
83
+
84
+ def _convert_expression_statement(self, node: Any) -> str:
85
+ """Convert JavaScript expression statements to Python."""
86
+ return self._convert_node(node.expression)
87
+
88
+ def _convert_binary_expression(self, node: Any) -> str:
89
+ """Convert JavaScript binary expressions to Python."""
90
+ operator_map = {
91
+ '===': '==',
92
+ '!==': '!=',
93
+ '&&': 'and',
94
+ '||': 'or'
95
+ }
96
+
97
+ left = self._convert_node(node.left)
98
+ right = self._convert_node(node.right)
99
+ op = operator_map.get(node.operator, node.operator)
100
+
101
+ return f"{left} {op} {right}"
102
+
103
+ def _convert_identifier(self, node: Any) -> str:
104
+ """Convert JavaScript identifiers to Python."""
105
+ name = node.name
106
+ # Map JavaScript built-ins to Python equivalents
107
+ js_to_python_builtins = {
108
+ 'console.log': 'print',
109
+ 'undefined': 'None',
110
+ 'null': 'None',
111
+ 'true': 'True',
112
+ 'false': 'False'
113
+ }
114
+ return js_to_python_builtins.get(name, name)
115
+
116
+ def _convert_literal(self, node: Any) -> str:
117
+ """Convert JavaScript literals to Python literals."""
118
+ if node.value is None:
119
+ return 'None'
120
+ elif isinstance(node.value, (int, float)):
121
+ return str(node.value)
122
+ elif isinstance(node.value, str):
123
+ return repr(node.value)
124
+ elif isinstance(node.value, bool):
125
+ return str(node.value)
126
+ else:
127
+ raise ValueError(f"Unsupported literal type: {type(node.value)}")
128
+
129
+ def _convert_call_expression(self, node: Any) -> str:
130
+ """Convert JavaScript function calls to Python."""
131
+ callee = self._convert_node(node.callee)
132
+ args = [self._convert_node(arg) for arg in node.arguments]
133
+
134
+ # Handle special cases
135
+ if callee == 'console.log':
136
+ callee = 'print'
137
+
138
+ return f"{callee}({', '.join(args)})"
139
+
140
+ def _convert_return_statement(self, node: Any) -> str:
141
+ """Convert JavaScript return statements to Python."""
142
+ if node.argument:
143
+ return f"return {self._convert_node(node.argument)}"
144
+ return "return"
145
+
146
+ def _convert_if_statement(self, node: Any) -> str:
147
+ """Convert JavaScript if statements to Python."""
148
+ test = self._convert_node(node.test)
149
+ consequent = self._convert_node(node.consequent)
150
+
151
+ if_stmt = f"if {test}:\n{self._indent(consequent)}"
152
+
153
+ if node.alternate:
154
+ alternate = self._convert_node(node.alternate)
155
+ if_stmt += f"\nelse:\n{self._indent(alternate)}"
156
+
157
+ return if_stmt
158
+
159
+ def _convert_for_statement(self, node: Any) -> str:
160
+ """Convert JavaScript for loops to Python."""
161
+ init = self._convert_node(node.init) if node.init else ""
162
+ test = self._convert_node(node.test) if node.test else "True"
163
+ update = self._convert_node(node.update) if node.update else ""
164
+ body = self._convert_node(node.body)
165
+
166
+ # Convert C-style for loop to while loop
167
+ if init:
168
+ return f"{init}\nwhile {test}:\n{self._indent(body)}\n{self._indent(update)}"
169
+ else:
170
+ return f"while {test}:\n{self._indent(body)}"
171
+
172
+ def _convert_while_statement(self, node: Any) -> str:
173
+ """Convert JavaScript while loops to Python."""
174
+ test = self._convert_node(node.test)
175
+ body = self._convert_node(node.body)
176
+
177
+ return f"while {test}:\n{self._indent(body)}"
178
+
179
+ def _indent(self, code: str, level: int = 1) -> str:
180
+ """Indent Python code by specified number of levels."""
181
+ lines = code.split('\n')
182
+ return '\n'.join(' ' * level + line for line in lines)
183
+
184
+
185
+ # Example usage
186
+ if __name__ == "__main__":
187
+ converter = JavaScriptToPythonConverter()
188
+
189
+ # Example JavaScript code
190
+ js_code = """
191
+ function fibonacci(n) {
192
+ if (n <= 1) {
193
+ return n;
194
+ }
195
+ return fibonacci(n - 1) + fibonacci(n - 2);
196
+ }
197
+
198
+ var result = fibonacci(10);
199
+ console.log("Fibonacci result:", result);
200
+ """
201
+
202
+ try:
203
+ python_code = converter.convert_js_to_python(js_code)
204
+ print("Converted Python code:")
205
+ print(python_code)
206
+ except Exception as e:
207
+ print(f"Conversion error: {str(e)}")