zexus 1.6.2

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 (227) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +2513 -0
  3. package/bin/zexus +2 -0
  4. package/bin/zpics +2 -0
  5. package/bin/zpm +2 -0
  6. package/bin/zx +2 -0
  7. package/bin/zx-deploy +2 -0
  8. package/bin/zx-dev +2 -0
  9. package/bin/zx-run +2 -0
  10. package/package.json +66 -0
  11. package/scripts/README.md +24 -0
  12. package/scripts/postinstall.js +44 -0
  13. package/shared_config.json +24 -0
  14. package/src/README.md +1525 -0
  15. package/src/tests/run_zexus_tests.py +117 -0
  16. package/src/tests/test_all_phases.zx +346 -0
  17. package/src/tests/test_blockchain_features.zx +306 -0
  18. package/src/tests/test_complexity_features.zx +321 -0
  19. package/src/tests/test_core_integration.py +185 -0
  20. package/src/tests/test_phase10_ecosystem.zx +177 -0
  21. package/src/tests/test_phase1_modifiers.zx +87 -0
  22. package/src/tests/test_phase2_plugins.zx +80 -0
  23. package/src/tests/test_phase3_security.zx +97 -0
  24. package/src/tests/test_phase4_vfs.zx +116 -0
  25. package/src/tests/test_phase5_types.zx +117 -0
  26. package/src/tests/test_phase6_metaprogramming.zx +125 -0
  27. package/src/tests/test_phase7_optimization.zx +132 -0
  28. package/src/tests/test_phase9_advanced_types.zx +157 -0
  29. package/src/tests/test_security_features.py +419 -0
  30. package/src/tests/test_security_features.zx +276 -0
  31. package/src/tests/test_simple_zx.zx +1 -0
  32. package/src/tests/test_verification_simple.zx +69 -0
  33. package/src/zexus/__init__.py +28 -0
  34. package/src/zexus/__main__.py +5 -0
  35. package/src/zexus/__pycache__/__init__.cpython-312.pyc +0 -0
  36. package/src/zexus/__pycache__/advanced_types.cpython-312.pyc +0 -0
  37. package/src/zexus/__pycache__/builtin_modules.cpython-312.pyc +0 -0
  38. package/src/zexus/__pycache__/capability_system.cpython-312.pyc +0 -0
  39. package/src/zexus/__pycache__/complexity_system.cpython-312.pyc +0 -0
  40. package/src/zexus/__pycache__/concurrency_system.cpython-312.pyc +0 -0
  41. package/src/zexus/__pycache__/config.cpython-312.pyc +0 -0
  42. package/src/zexus/__pycache__/dependency_injection.cpython-312.pyc +0 -0
  43. package/src/zexus/__pycache__/ecosystem.cpython-312.pyc +0 -0
  44. package/src/zexus/__pycache__/environment.cpython-312.pyc +0 -0
  45. package/src/zexus/__pycache__/error_reporter.cpython-312.pyc +0 -0
  46. package/src/zexus/__pycache__/hybrid_orchestrator.cpython-312.pyc +0 -0
  47. package/src/zexus/__pycache__/lexer.cpython-312.pyc +0 -0
  48. package/src/zexus/__pycache__/metaprogramming.cpython-312.pyc +0 -0
  49. package/src/zexus/__pycache__/module_cache.cpython-312.pyc +0 -0
  50. package/src/zexus/__pycache__/object.cpython-312.pyc +0 -0
  51. package/src/zexus/__pycache__/optimization.cpython-312.pyc +0 -0
  52. package/src/zexus/__pycache__/plugin_system.cpython-312.pyc +0 -0
  53. package/src/zexus/__pycache__/policy_engine.cpython-312.pyc +0 -0
  54. package/src/zexus/__pycache__/security.cpython-312.pyc +0 -0
  55. package/src/zexus/__pycache__/stdlib_integration.cpython-312.pyc +0 -0
  56. package/src/zexus/__pycache__/strategy_recovery.cpython-312.pyc +0 -0
  57. package/src/zexus/__pycache__/syntax_validator.cpython-312.pyc +0 -0
  58. package/src/zexus/__pycache__/type_system.cpython-312.pyc +0 -0
  59. package/src/zexus/__pycache__/virtual_filesystem.cpython-312.pyc +0 -0
  60. package/src/zexus/__pycache__/zexus_ast.cpython-312.pyc +0 -0
  61. package/src/zexus/__pycache__/zexus_token.cpython-312.pyc +0 -0
  62. package/src/zexus/advanced_types.py +401 -0
  63. package/src/zexus/blockchain/__init__.py +40 -0
  64. package/src/zexus/blockchain/__pycache__/__init__.cpython-312.pyc +0 -0
  65. package/src/zexus/blockchain/__pycache__/crypto.cpython-312.pyc +0 -0
  66. package/src/zexus/blockchain/__pycache__/ledger.cpython-312.pyc +0 -0
  67. package/src/zexus/blockchain/__pycache__/transaction.cpython-312.pyc +0 -0
  68. package/src/zexus/blockchain/crypto.py +463 -0
  69. package/src/zexus/blockchain/ledger.py +255 -0
  70. package/src/zexus/blockchain/transaction.py +267 -0
  71. package/src/zexus/builtin_modules.py +284 -0
  72. package/src/zexus/builtin_plugins.py +317 -0
  73. package/src/zexus/capability_system.py +372 -0
  74. package/src/zexus/cli/__init__.py +2 -0
  75. package/src/zexus/cli/__pycache__/__init__.cpython-312.pyc +0 -0
  76. package/src/zexus/cli/__pycache__/main.cpython-312.pyc +0 -0
  77. package/src/zexus/cli/main.py +707 -0
  78. package/src/zexus/cli/zpm.py +203 -0
  79. package/src/zexus/compare_interpreter_compiler.py +146 -0
  80. package/src/zexus/compiler/__init__.py +169 -0
  81. package/src/zexus/compiler/__pycache__/__init__.cpython-312.pyc +0 -0
  82. package/src/zexus/compiler/__pycache__/lexer.cpython-312.pyc +0 -0
  83. package/src/zexus/compiler/__pycache__/parser.cpython-312.pyc +0 -0
  84. package/src/zexus/compiler/__pycache__/zexus_ast.cpython-312.pyc +0 -0
  85. package/src/zexus/compiler/bytecode.py +266 -0
  86. package/src/zexus/compiler/compat_runtime.py +277 -0
  87. package/src/zexus/compiler/lexer.py +257 -0
  88. package/src/zexus/compiler/parser.py +779 -0
  89. package/src/zexus/compiler/semantic.py +118 -0
  90. package/src/zexus/compiler/zexus_ast.py +454 -0
  91. package/src/zexus/complexity_system.py +575 -0
  92. package/src/zexus/concurrency_system.py +493 -0
  93. package/src/zexus/config.py +201 -0
  94. package/src/zexus/crypto_bridge.py +19 -0
  95. package/src/zexus/dependency_injection.py +423 -0
  96. package/src/zexus/ecosystem.py +434 -0
  97. package/src/zexus/environment.py +101 -0
  98. package/src/zexus/environment_manager.py +119 -0
  99. package/src/zexus/error_reporter.py +314 -0
  100. package/src/zexus/evaluator/__init__.py +12 -0
  101. package/src/zexus/evaluator/__pycache__/__init__.cpython-312.pyc +0 -0
  102. package/src/zexus/evaluator/__pycache__/bytecode_compiler.cpython-312.pyc +0 -0
  103. package/src/zexus/evaluator/__pycache__/core.cpython-312.pyc +0 -0
  104. package/src/zexus/evaluator/__pycache__/expressions.cpython-312.pyc +0 -0
  105. package/src/zexus/evaluator/__pycache__/functions.cpython-312.pyc +0 -0
  106. package/src/zexus/evaluator/__pycache__/integration.cpython-312.pyc +0 -0
  107. package/src/zexus/evaluator/__pycache__/statements.cpython-312.pyc +0 -0
  108. package/src/zexus/evaluator/__pycache__/utils.cpython-312.pyc +0 -0
  109. package/src/zexus/evaluator/bytecode_compiler.py +700 -0
  110. package/src/zexus/evaluator/core.py +891 -0
  111. package/src/zexus/evaluator/expressions.py +827 -0
  112. package/src/zexus/evaluator/functions.py +3989 -0
  113. package/src/zexus/evaluator/integration.py +396 -0
  114. package/src/zexus/evaluator/statements.py +4303 -0
  115. package/src/zexus/evaluator/utils.py +126 -0
  116. package/src/zexus/evaluator_original.py +2041 -0
  117. package/src/zexus/external_bridge.py +16 -0
  118. package/src/zexus/find_affected_imports.sh +155 -0
  119. package/src/zexus/hybrid_orchestrator.py +152 -0
  120. package/src/zexus/input_validation.py +259 -0
  121. package/src/zexus/lexer.py +571 -0
  122. package/src/zexus/logging.py +89 -0
  123. package/src/zexus/lsp/__init__.py +9 -0
  124. package/src/zexus/lsp/completion_provider.py +207 -0
  125. package/src/zexus/lsp/definition_provider.py +22 -0
  126. package/src/zexus/lsp/hover_provider.py +71 -0
  127. package/src/zexus/lsp/server.py +269 -0
  128. package/src/zexus/lsp/symbol_provider.py +31 -0
  129. package/src/zexus/metaprogramming.py +321 -0
  130. package/src/zexus/module_cache.py +89 -0
  131. package/src/zexus/module_manager.py +107 -0
  132. package/src/zexus/object.py +973 -0
  133. package/src/zexus/optimization.py +424 -0
  134. package/src/zexus/parser/__init__.py +31 -0
  135. package/src/zexus/parser/__pycache__/__init__.cpython-312.pyc +0 -0
  136. package/src/zexus/parser/__pycache__/parser.cpython-312.pyc +0 -0
  137. package/src/zexus/parser/__pycache__/strategy_context.cpython-312.pyc +0 -0
  138. package/src/zexus/parser/__pycache__/strategy_structural.cpython-312.pyc +0 -0
  139. package/src/zexus/parser/integration.py +86 -0
  140. package/src/zexus/parser/parser.py +3977 -0
  141. package/src/zexus/parser/strategy_context.py +7254 -0
  142. package/src/zexus/parser/strategy_structural.py +1033 -0
  143. package/src/zexus/persistence.py +391 -0
  144. package/src/zexus/plugin_system.py +290 -0
  145. package/src/zexus/policy_engine.py +365 -0
  146. package/src/zexus/profiler/__init__.py +5 -0
  147. package/src/zexus/profiler/profiler.py +233 -0
  148. package/src/zexus/purity_system.py +398 -0
  149. package/src/zexus/runtime/__init__.py +20 -0
  150. package/src/zexus/runtime/async_runtime.py +324 -0
  151. package/src/zexus/search_old_imports.sh +65 -0
  152. package/src/zexus/security.py +1407 -0
  153. package/src/zexus/stack_trace.py +233 -0
  154. package/src/zexus/stdlib/__init__.py +27 -0
  155. package/src/zexus/stdlib/blockchain.py +341 -0
  156. package/src/zexus/stdlib/compression.py +167 -0
  157. package/src/zexus/stdlib/crypto.py +124 -0
  158. package/src/zexus/stdlib/datetime.py +163 -0
  159. package/src/zexus/stdlib/db_mongo.py +199 -0
  160. package/src/zexus/stdlib/db_mysql.py +162 -0
  161. package/src/zexus/stdlib/db_postgres.py +163 -0
  162. package/src/zexus/stdlib/db_sqlite.py +133 -0
  163. package/src/zexus/stdlib/encoding.py +230 -0
  164. package/src/zexus/stdlib/fs.py +195 -0
  165. package/src/zexus/stdlib/http.py +219 -0
  166. package/src/zexus/stdlib/http_server.py +248 -0
  167. package/src/zexus/stdlib/json_module.py +61 -0
  168. package/src/zexus/stdlib/math.py +360 -0
  169. package/src/zexus/stdlib/os_module.py +265 -0
  170. package/src/zexus/stdlib/regex.py +148 -0
  171. package/src/zexus/stdlib/sockets.py +253 -0
  172. package/src/zexus/stdlib/test_framework.zx +208 -0
  173. package/src/zexus/stdlib/test_runner.zx +119 -0
  174. package/src/zexus/stdlib_integration.py +341 -0
  175. package/src/zexus/strategy_recovery.py +256 -0
  176. package/src/zexus/syntax_validator.py +356 -0
  177. package/src/zexus/testing/zpics.py +407 -0
  178. package/src/zexus/testing/zpics_runtime.py +369 -0
  179. package/src/zexus/type_system.py +374 -0
  180. package/src/zexus/validation_system.py +569 -0
  181. package/src/zexus/virtual_filesystem.py +355 -0
  182. package/src/zexus/vm/__init__.py +8 -0
  183. package/src/zexus/vm/__pycache__/__init__.cpython-312.pyc +0 -0
  184. package/src/zexus/vm/__pycache__/async_optimizer.cpython-312.pyc +0 -0
  185. package/src/zexus/vm/__pycache__/bytecode.cpython-312.pyc +0 -0
  186. package/src/zexus/vm/__pycache__/cache.cpython-312.pyc +0 -0
  187. package/src/zexus/vm/__pycache__/jit.cpython-312.pyc +0 -0
  188. package/src/zexus/vm/__pycache__/memory_manager.cpython-312.pyc +0 -0
  189. package/src/zexus/vm/__pycache__/memory_pool.cpython-312.pyc +0 -0
  190. package/src/zexus/vm/__pycache__/optimizer.cpython-312.pyc +0 -0
  191. package/src/zexus/vm/__pycache__/parallel_vm.cpython-312.pyc +0 -0
  192. package/src/zexus/vm/__pycache__/peephole_optimizer.cpython-312.pyc +0 -0
  193. package/src/zexus/vm/__pycache__/profiler.cpython-312.pyc +0 -0
  194. package/src/zexus/vm/__pycache__/register_allocator.cpython-312.pyc +0 -0
  195. package/src/zexus/vm/__pycache__/register_vm.cpython-312.pyc +0 -0
  196. package/src/zexus/vm/__pycache__/ssa_converter.cpython-312.pyc +0 -0
  197. package/src/zexus/vm/__pycache__/vm.cpython-312.pyc +0 -0
  198. package/src/zexus/vm/async_optimizer.py +420 -0
  199. package/src/zexus/vm/bytecode.py +428 -0
  200. package/src/zexus/vm/bytecode_converter.py +297 -0
  201. package/src/zexus/vm/cache.py +532 -0
  202. package/src/zexus/vm/jit.py +720 -0
  203. package/src/zexus/vm/memory_manager.py +520 -0
  204. package/src/zexus/vm/memory_pool.py +511 -0
  205. package/src/zexus/vm/optimizer.py +478 -0
  206. package/src/zexus/vm/parallel_vm.py +899 -0
  207. package/src/zexus/vm/peephole_optimizer.py +452 -0
  208. package/src/zexus/vm/profiler.py +527 -0
  209. package/src/zexus/vm/register_allocator.py +462 -0
  210. package/src/zexus/vm/register_vm.py +520 -0
  211. package/src/zexus/vm/ssa_converter.py +757 -0
  212. package/src/zexus/vm/vm.py +1392 -0
  213. package/src/zexus/zexus_ast.py +1782 -0
  214. package/src/zexus/zexus_token.py +253 -0
  215. package/src/zexus/zpm/__init__.py +15 -0
  216. package/src/zexus/zpm/installer.py +116 -0
  217. package/src/zexus/zpm/package_manager.py +208 -0
  218. package/src/zexus/zpm/publisher.py +98 -0
  219. package/src/zexus/zpm/registry.py +110 -0
  220. package/src/zexus.egg-info/PKG-INFO +2235 -0
  221. package/src/zexus.egg-info/SOURCES.txt +876 -0
  222. package/src/zexus.egg-info/dependency_links.txt +1 -0
  223. package/src/zexus.egg-info/entry_points.txt +3 -0
  224. package/src/zexus.egg-info/not-zip-safe +1 -0
  225. package/src/zexus.egg-info/requires.txt +14 -0
  226. package/src/zexus.egg-info/top_level.txt +2 -0
  227. package/zexus.json +14 -0
@@ -0,0 +1,256 @@
1
+ # strategy_recovery.py
2
+ from .zexus_token import *
3
+ from .zexus_ast import (
4
+ EntityStatement,
5
+ UseStatement,
6
+ ExportStatement,
7
+ TryCatchStatement,
8
+ BlockStatement,
9
+ ExpressionStatement,
10
+ Identifier,
11
+ StringLiteral,
12
+ )
13
+
14
+ class ErrorRecoveryEngine:
15
+ def __init__(self, structural_analyzer, context_parser):
16
+ self.structural_analyzer = structural_analyzer
17
+ self.context_parser = context_parser
18
+ self.recovery_strategies = {
19
+ 'expected_catch': self._recover_expected_catch,
20
+ 'unexpected_token': self._recover_unexpected_token,
21
+ 'missing_parenthesis': self._recover_missing_parenthesis,
22
+ 'missing_brace': self._recover_missing_brace,
23
+ 'syntax_error': self._recover_generic_syntax
24
+ }
25
+
26
+ def create_recovery_plan(self, error, current_block_info, current_tokens, token_index):
27
+ """Create intelligent recovery plan based on error type and context"""
28
+ print(f"🛠️ [Recovery] Analyzing error: {error}")
29
+
30
+ error_type = self._classify_error(error)
31
+ current_context = self.context_parser.get_current_context()
32
+
33
+ if error_type in self.recovery_strategies:
34
+ recovery_plan = self.recovery_strategies[error_type](
35
+ error, current_block_info, current_context, current_tokens, token_index
36
+ )
37
+
38
+ if recovery_plan['can_recover']:
39
+ print(f"✅ [Recovery] {recovery_plan['message']}")
40
+ return recovery_plan
41
+
42
+ # Final fallback
43
+ return self._create_fallback_recovery(error, current_block_info, current_context)
44
+
45
+ def _classify_error(self, error):
46
+ """Classify the error type for appropriate recovery strategy"""
47
+ error_msg = str(error).lower()
48
+
49
+ if "expected catch" in error_msg or "catch" in error_msg:
50
+ return 'expected_catch'
51
+ elif "unexpected token" in error_msg:
52
+ return 'unexpected_token'
53
+ elif "missing )" in error_msg or "parenthesis" in error_msg:
54
+ return 'missing_parenthesis'
55
+ elif "missing }" in error_msg or "brace" in error_msg:
56
+ return 'missing_brace'
57
+ else:
58
+ return 'syntax_error'
59
+
60
+ def _recover_expected_catch(self, error, block_info, context, tokens, token_index):
61
+ """Recover from 'expected catch' errors using structural analysis"""
62
+ print("🛠️ [Recovery] Handling 'expected catch' error")
63
+
64
+ # Check if structural analysis shows a catch block exists
65
+ current_block_id = block_info.get('id') if block_info else None
66
+ catch_block = self._find_catch_block_in_structure(current_block_id)
67
+
68
+ if catch_block:
69
+ return {
70
+ 'can_recover': True,
71
+ 'recovered_statement': self._create_dummy_try_catch(),
72
+ 'next_action': 'skip_to_block',
73
+ 'target_block': catch_block['id'],
74
+ 'message': 'Structural analysis shows catch block exists later - skipping to catch'
75
+ }
76
+
77
+ # If no catch block found, create a synthetic one
78
+ return {
79
+ 'can_recover': True,
80
+ 'recovered_statement': self._create_synthetic_catch_block(),
81
+ 'next_action': 'continue',
82
+ 'message': 'Created synthetic catch block for recovery'
83
+ }
84
+
85
+ def _recover_unexpected_token(self, error, block_info, context, tokens, token_index):
86
+ """Recover from unexpected token errors"""
87
+ print(f"🛠️ [Recovery] Handling unexpected token at index {token_index}")
88
+
89
+ # Extract the problematic token from error message or use current token
90
+ problematic_token = self._extract_problematic_token(error, tokens, token_index)
91
+
92
+ if problematic_token:
93
+ return {
94
+ 'can_recover': True,
95
+ 'recovered_statement': self._create_skip_statement(problematic_token),
96
+ 'next_action': 'skip_tokens',
97
+ 'skip_count': 1,
98
+ 'message': f'Skipped problematic token: {problematic_token}'
99
+ }
100
+
101
+ return {'can_recover': False}
102
+
103
+ def _recover_missing_parenthesis(self, error, block_info, context, tokens, token_index):
104
+ """Recover from missing parenthesis errors"""
105
+ print("🛠️ [Recovery] Handling missing parenthesis")
106
+
107
+ # Look ahead to find a likely closing parenthesis
108
+ for i in range(token_index, min(token_index + 10, len(tokens))):
109
+ if tokens[i].type == RPAREN:
110
+ return {
111
+ 'can_recover': True,
112
+ 'recovered_statement': self._create_dummy_expression(),
113
+ 'next_action': 'skip_to_token',
114
+ 'target_token_index': i + 1,
115
+ 'message': 'Found potential closing parenthesis ahead'
116
+ }
117
+
118
+ # Insert synthetic closing parenthesis
119
+ return {
120
+ 'can_recover': True,
121
+ 'recovered_statement': self._create_dummy_expression(),
122
+ 'next_action': 'insert_token',
123
+ 'insert_token': Token(RPAREN, ')', line=tokens[token_index].line, column=tokens[token_index].column + 1),
124
+ 'message': 'Inserted synthetic closing parenthesis'
125
+ }
126
+
127
+ def _recover_missing_brace(self, error, block_info, context, tokens, token_index):
128
+ """Recover from missing brace errors using structural analysis"""
129
+ print("🛠️ [Recovery] Handling missing brace")
130
+
131
+ # Use structural analysis to find matching brace
132
+ if block_info:
133
+ # Structural analyzer already found the block boundaries
134
+ return {
135
+ 'can_recover': True,
136
+ 'recovered_statement': BlockStatement(),
137
+ 'next_action': 'skip_to_block_end',
138
+ 'target_block': block_info['id'],
139
+ 'message': 'Using structural analysis to find block end'
140
+ }
141
+
142
+ return {'can_recover': False}
143
+
144
+ def _recover_generic_syntax(self, error, block_info, context, tokens, token_index):
145
+ """Generic syntax error recovery"""
146
+ print("🛠️ [Recovery] Handling generic syntax error")
147
+
148
+ # Try to skip a few tokens and continue
149
+ return {
150
+ 'can_recover': True,
151
+ 'recovered_statement': self._create_dummy_statement(),
152
+ 'next_action': 'skip_tokens',
153
+ 'skip_count': 3, # Skip next 3 tokens
154
+ 'message': 'Skipping ahead to recover from syntax error'
155
+ }
156
+
157
+ def _find_catch_block_in_structure(self, current_block_id):
158
+ """Find a catch block in the structural analysis"""
159
+ blocks = self.structural_analyzer.blocks
160
+
161
+ # Look for catch blocks in current block or parent blocks
162
+ for block_id, block in blocks.items():
163
+ if block.get('subtype') == 'try_catch':
164
+ if block.get('catch_section'):
165
+ return block
166
+ # Check nested blocks
167
+ for nested in block.get('nested_blocks', []):
168
+ if nested.get('subtype') == 'try_catch' and nested.get('catch_section'):
169
+ return nested
170
+
171
+ return None
172
+
173
+ def _extract_problematic_token(self, error, tokens, token_index):
174
+ """Extract the problematic token from error message or token stream"""
175
+ if token_index < len(tokens):
176
+ return tokens[token_index]
177
+
178
+ # Try to extract from error message
179
+ error_str = str(error)
180
+ if "'" in error_str:
181
+ # Extract token literal from error message like "Unexpected token 'catch'"
182
+ start = error_str.find("'") + 1
183
+ end = error_str.find("'", start)
184
+ if start > 0 and end > start:
185
+ token_literal = error_str[start:end]
186
+ # Find matching token in stream
187
+ for token in tokens:
188
+ if token.literal == token_literal:
189
+ return token
190
+
191
+ return None
192
+
193
+ def _create_dummy_try_catch(self):
194
+ """Create a placeholder try-catch statement for recovery"""
195
+ return TryCatchStatement(
196
+ try_block=BlockStatement(),
197
+ error_variable=Identifier("error"),
198
+ catch_block=BlockStatement()
199
+ )
200
+
201
+ def _create_synthetic_catch_block(self):
202
+ """Create a synthetic catch block when none exists"""
203
+ return TryCatchStatement(
204
+ try_block=BlockStatement(),
205
+ error_variable=Identifier("error"),
206
+ catch_block=BlockStatement([ExpressionStatement(StringLiteral("Recovery catch block"))])
207
+ )
208
+
209
+ def _create_skip_statement(self, skipped_token):
210
+ """Create a statement that represents skipping a token"""
211
+ return ExpressionStatement(StringLiteral(f"Skipped: {skipped_token.literal}"))
212
+
213
+ def _create_dummy_expression(self):
214
+ """Create a placeholder expression"""
215
+ return ExpressionStatement(Identifier("recovery_expression"))
216
+
217
+ def _create_dummy_statement(self):
218
+ """Create a placeholder statement"""
219
+ return ExpressionStatement(StringLiteral("Recovery statement"))
220
+
221
+ def _create_fallback_recovery(self, error, block_info, context):
222
+ """Final fallback recovery strategy"""
223
+ return {
224
+ 'can_recover': True,
225
+ 'recovered_statement': self._create_dummy_statement(),
226
+ 'next_action': 'skip_tokens',
227
+ 'skip_count': 5,
228
+ 'message': 'Using fallback recovery - skipping ahead'
229
+ }
230
+
231
+ def apply_recovery_plan(self, recovery_plan, current_tokens, current_index):
232
+ """Apply the recovery plan to adjust parsing state"""
233
+ if not recovery_plan['can_recover']:
234
+ return current_index
235
+
236
+ action = recovery_plan.get('next_action', 'continue')
237
+
238
+ if action == 'skip_tokens':
239
+ skip_count = recovery_plan.get('skip_count', 1)
240
+ return min(current_index + skip_count, len(current_tokens) - 1)
241
+
242
+ elif action == 'skip_to_token':
243
+ target_index = recovery_plan.get('target_token_index', current_index)
244
+ return min(target_index, len(current_tokens) - 1)
245
+
246
+ elif action == 'skip_to_block':
247
+ # This would require coordination with the main parser
248
+ print("⚠️ [Recovery] Block skipping requires parser integration")
249
+ return current_index + 1
250
+
251
+ elif action == 'insert_token':
252
+ # This would modify the token stream
253
+ print("⚠️ [Recovery] Token insertion requires stream modification")
254
+ return current_index
255
+
256
+ return current_index + 1 # Default: move to next token
@@ -0,0 +1,356 @@
1
+ # syntax_validator.py
2
+ # Updated to match actual parser capabilities (parser.py, strategy_context.py, strategy_structural.py)
3
+ # The parsers support flexible syntax: both with and without parentheses, both {} and : block styles
4
+ import re
5
+
6
+ class SyntaxValidator:
7
+ def __init__(self):
8
+ self.suggestions = []
9
+ self.warnings = []
10
+
11
+ def validate_code(self, code, desired_style="flexible"):
12
+ """Validate code and suggest improvements
13
+
14
+ Styles:
15
+ - flexible: Accept both syntaxes (matches parser behavior)
16
+ - universal: Prefer braces {} and parentheses
17
+ - tolerable: More relaxed, warn only on actual errors
18
+ """
19
+ self.suggestions = []
20
+ self.warnings = []
21
+
22
+ lines = code.split('\n')
23
+
24
+ for i, line in enumerate(lines):
25
+ line_num = i + 1
26
+ self._validate_line(line, line_num, desired_style)
27
+
28
+ return {
29
+ 'is_valid': len(self.suggestions) == 0,
30
+ 'suggestions': self.suggestions,
31
+ 'warnings': self.warnings,
32
+ 'error_count': len(self.suggestions)
33
+ }
34
+
35
+ def _validate_line(self, line, line_num, style):
36
+ """Validate a single line against the desired style
37
+
38
+ Parser accepts BOTH styles - with/without parentheses, {}/: blocks
39
+ Validation should only flag actual syntax errors, not style preferences
40
+ """
41
+ stripped_line = line.strip()
42
+ if not stripped_line or stripped_line.startswith('#'):
43
+ return
44
+
45
+ # Flexible validation (default - matches parser behavior)
46
+ if style == "flexible":
47
+ self._validate_flexible_syntax(stripped_line, line_num, line)
48
+ # Universal style validations (prefer specific style but accept both)
49
+ elif style == "universal":
50
+ self._validate_universal_syntax(stripped_line, line_num, line)
51
+ # Tolerable style validations
52
+ elif style == "tolerable":
53
+ self._validate_tolerable_syntax(stripped_line, line_num, line)
54
+
55
+ # Common validations for all styles (actual errors only)
56
+ self._validate_common_syntax(stripped_line, line_num, line)
57
+
58
+ def _validate_flexible_syntax(self, stripped_line, line_num, original_line):
59
+ """Validate for actual syntax errors only - accept both styles
60
+
61
+ The parser supports:
62
+ - if (condition) { } AND if condition { } AND if condition:
63
+ - while (condition) { } AND while condition { } AND while condition:
64
+ - action name(params) { } AND action name params { }
65
+ - catch(error) { } AND catch (error) { }
66
+ - print(value) AND print (value) - both are valid
67
+ """
68
+ # Only flag actual errors that parser would reject
69
+
70
+ # Check for space between function name and parenthesis (commonly flagged but actually valid)
71
+ # DON'T warn about "print (" - parser accepts this
72
+
73
+ # Check for unmatched braces (actual error)
74
+ open_braces = stripped_line.count('{') - stripped_line.count('}')
75
+ open_parens = stripped_line.count('(') - stripped_line.count(')')
76
+ open_brackets = stripped_line.count('[') - stripped_line.count(']')
77
+
78
+ if abs(open_braces) > 2 or abs(open_parens) > 2 or abs(open_brackets) > 2:
79
+ # Only warn if significantly unbalanced (might span multiple lines)
80
+ self.warnings.append({
81
+ 'line': line_num,
82
+ 'message': "Potentially unmatched delimiters - check braces/parentheses/brackets",
83
+ 'severity': 'warning'
84
+ })
85
+
86
+ # Check for obvious typos in keywords
87
+ common_typos = {
88
+ 'fucntion': 'function',
89
+ 'acton': 'action',
90
+ 'retrun': 'return',
91
+ 'esle': 'else',
92
+ 'wile': 'while',
93
+ 'forach': 'foreach',
94
+ }
95
+ for typo, correct in common_typos.items():
96
+ if typo in stripped_line:
97
+ self.suggestions.append({
98
+ 'line': line_num,
99
+ 'message': f"Possible typo: '{typo}' should be '{correct}'",
100
+ 'fix': original_line.replace(typo, correct),
101
+ 'severity': 'error'
102
+ })
103
+
104
+ def _validate_universal_syntax(self, stripped_line, line_num, original_line):
105
+ """Validate and suggest universal syntax style (preference, not requirement)
106
+
107
+ NOTE: Parser accepts BOTH styles, so these are style suggestions, not errors
108
+ """
109
+ # REMOVED: Colon block check - parser fully supports colon blocks
110
+ # The parser accepts both: if condition { } AND if condition:
111
+ # So we should NOT suggest changing : to {}
112
+
113
+ # REMOVED: Parentheses suggestions for if/while
114
+ # Parser accepts: if (x) { }, if x { }, if x:
115
+ # All are valid, so don't suggest changes
116
+
117
+ # Check for double parentheses in catch (actual syntax issue)
118
+ if 'catch' in stripped_line and 'catch((' in stripped_line and '))' in stripped_line:
119
+ self.suggestions.append({
120
+ 'line': line_num,
121
+ 'message': "Remove extra parentheses in catch: catch(error) { }",
122
+ 'fix': self._fix_double_parentheses_catch(original_line),
123
+ 'severity': 'error'
124
+ })
125
+
126
+ def _validate_tolerable_syntax(self, stripped_line, line_num, original_line):
127
+ """Validate against tolerable syntax rules"""
128
+ # Check for potentially confusing syntax
129
+ if stripped_line.count('{') != stripped_line.count('}'):
130
+ self.warnings.append({
131
+ 'line': line_num,
132
+ 'message': "Mismatched braces - this can cause parsing issues",
133
+ 'severity': 'warning'
134
+ })
135
+
136
+ # Check for mixed block styles in same context
137
+ if (any(stripped_line.startswith(keyword) for keyword in ['if', 'for each', 'while'])
138
+ and ':' in stripped_line and '{' in stripped_line):
139
+ self.suggestions.append({
140
+ 'line': line_num,
141
+ 'message': "Mixed block syntax - prefer consistent use of : or {}",
142
+ 'fix': original_line,
143
+ 'severity': 'warning'
144
+ })
145
+
146
+ def _validate_common_syntax(self, stripped_line, line_num, original_line):
147
+ """Common validations for all syntax styles - only flag real errors"""
148
+
149
+ # DON'T check for missing parentheses - parser accepts both styles
150
+ # The old check was:
151
+ # if 'if' in line and '(' not in line: suggest parentheses
152
+ # This is WRONG - parser accepts: if condition { }
153
+
154
+ # Check for assignment in conditions (common bug - actual error)
155
+ if 'if' in stripped_line and ' = ' in stripped_line and ' == ' not in stripped_line:
156
+ # Make sure it's not a string literal
157
+ if stripped_line.count('"') % 2 == 0 and stripped_line.count("'") % 2 == 0:
158
+ self.warnings.append({
159
+ 'line': line_num,
160
+ 'message': "Possible assignment in condition - did you mean '=='?",
161
+ 'severity': 'warning'
162
+ })
163
+
164
+ # Check try-catch structure
165
+ self._validate_try_catch_structure(stripped_line, line_num, original_line)
166
+
167
+ def _validate_try_catch_structure(self, stripped_line, line_num, original_line):
168
+ """Validate try-catch block structure
169
+
170
+ Parser accepts multiple catch formats:
171
+ - catch(error) { }
172
+ - catch (error) { } (space before paren is OK)
173
+ - catch error { } (no parens in some contexts)
174
+ """
175
+ # Only check for catch without ANY error parameter
176
+ if 'catch' in stripped_line:
177
+ # Check for catch immediately followed by { (no error variable at all)
178
+ if re.search(r'catch\s*\{', stripped_line):
179
+ self.suggestions.append({
180
+ 'line': line_num,
181
+ 'message': "Catch block should include error parameter: catch(error) { }",
182
+ 'fix': original_line.replace('catch{', 'catch(error) {').replace('catch {', 'catch(error) {'),
183
+ 'severity': 'warning'
184
+ })
185
+ # Check for double parentheses (actual error)
186
+ elif 'catch((' in stripped_line and '))' in stripped_line:
187
+ self.suggestions.append({
188
+ 'line': line_num,
189
+ 'message': "Remove extra parentheses in catch: catch(error) { }",
190
+ 'fix': self._fix_double_parentheses_catch(original_line),
191
+ 'severity': 'error'
192
+ })
193
+
194
+ def _fix_catch_syntax(self, line):
195
+ """Fix catch syntax from 'catch error { }' to 'catch(error) { }'"""
196
+ # Pattern: catch followed by identifier then {
197
+ pattern = r'catch\s+(\w+)\s*\{'
198
+ replacement = r'catch(\1) {'
199
+ fixed_line = re.sub(pattern, replacement, line)
200
+
201
+ if fixed_line != line:
202
+ return fixed_line
203
+
204
+ # Fallback: simple string replacement
205
+ if 'catch ' in line and '{' in line:
206
+ # Extract the error variable name
207
+ parts = line.split('catch ', 1)[1].split('{', 1)
208
+ if len(parts) == 2:
209
+ error_var = parts[0].strip()
210
+ rest = parts[1]
211
+ return line.split('catch ', 1)[0] + f'catch({error_var}) {{' + rest
212
+
213
+ return line
214
+
215
+ def _fix_double_parentheses_catch(self, line):
216
+ """Fix catch with double parentheses: catch((error)) to catch(error)"""
217
+ # Pattern: catch((...))
218
+ pattern = r'catch\(\s*\(\s*(\w+)\s*\)\s*\)'
219
+ replacement = r'catch(\1)'
220
+ fixed_line = re.sub(pattern, replacement, line)
221
+
222
+ if fixed_line != line:
223
+ return fixed_line
224
+
225
+ # Fallback: simple string replacement
226
+ if 'catch((' in line and '))' in line:
227
+ start = line.find('catch((') + 7 # after 'catch(('
228
+ end = line.find('))', start)
229
+ if start > 0 and end > start:
230
+ error_var = line[start:end].strip()
231
+ return line.replace(f'catch(({error_var}))', f'catch({error_var})')
232
+
233
+ return line
234
+
235
+ def _fix_lambda_syntax(self, line):
236
+ """Fix lambda syntax to universal style"""
237
+ if 'lambda ' in line:
238
+ # Simple case: lambda x: expr -> lambda(x) -> expr
239
+ if ':' in line:
240
+ return line.replace('lambda ', 'lambda(', 1).replace(':', ') ->', 1)
241
+ # Case with arrow: lambda x -> expr -> lambda(x) -> expr
242
+ elif '->' in line:
243
+ return line.replace('lambda ', 'lambda(', 1).replace(' ->', ') ->', 1)
244
+ return line
245
+
246
+ def _add_parentheses_to_condition(self, line):
247
+ """Add parentheses around condition"""
248
+ if line.startswith('if '):
249
+ return line.replace('if ', 'if (', 1) + ')'
250
+ elif line.startswith('while '):
251
+ return line.replace('while ', 'while (', 1) + ')'
252
+ return line
253
+
254
+ def auto_fix(self, code, desired_style="flexible"):
255
+ """Attempt to automatically fix syntax issues
256
+
257
+ Only fixes actual errors, not style preferences (when using flexible mode)
258
+ """
259
+ validation = self.validate_code(code, desired_style)
260
+
261
+ if validation['is_valid']:
262
+ return code, validation
263
+
264
+ lines = code.split('\n')
265
+ fixed_lines = lines.copy()
266
+ applied_fixes = 0
267
+
268
+ # Group suggestions by line to avoid conflicts
269
+ line_suggestions = {}
270
+ for suggestion in validation['suggestions']:
271
+ # In flexible mode, only auto-fix errors, not suggestions/warnings
272
+ if desired_style == "flexible" and suggestion['severity'] not in ['error']:
273
+ continue
274
+
275
+ if suggestion['severity'] in ['error', 'warning']:
276
+ line_num = suggestion['line'] - 1
277
+ if line_num not in line_suggestions:
278
+ line_suggestions[line_num] = []
279
+ line_suggestions[line_num].append(suggestion)
280
+
281
+ # Apply fixes line by line
282
+ for line_num, suggestions in line_suggestions.items():
283
+ if line_num < len(fixed_lines):
284
+ current_line = fixed_lines[line_num]
285
+ fixed_line = current_line
286
+
287
+ # Apply fixes in order
288
+ for suggestion in suggestions:
289
+ if 'fix' in suggestion:
290
+ fixed_line = suggestion['fix']
291
+ applied_fixes += 1
292
+
293
+ fixed_lines[line_num] = fixed_line
294
+
295
+ fixed_code = '\n'.join(fixed_lines)
296
+
297
+ # Re-validate after fixes
298
+ final_validation = self.validate_code(fixed_code, desired_style)
299
+ final_validation['applied_fixes'] = applied_fixes
300
+
301
+ return fixed_code, final_validation
302
+
303
+ def suggest_syntax_style(self, code):
304
+ """Analyze code and suggest which syntax style it follows"""
305
+ lines = code.split('\n')
306
+
307
+ universal_indicators = 0
308
+ tolerable_indicators = 0
309
+
310
+ for line in lines:
311
+ stripped = line.strip()
312
+ if not stripped or stripped.startswith('#'):
313
+ continue
314
+
315
+ # Universal indicators
316
+ if any(stripped.startswith(kw + '(') for kw in ['if', 'while', 'debug']):
317
+ universal_indicators += 1
318
+ if 'lambda(' in stripped:
319
+ universal_indicators += 1
320
+ if stripped.endswith('{'):
321
+ universal_indicators += 1
322
+ if 'catch(' in stripped and 'catch((' not in stripped:
323
+ universal_indicators += 1
324
+
325
+ # Tolerable indicators
326
+ if any(stripped.startswith(kw + ' ') and stripped.endswith(':')
327
+ for kw in ['if', 'for each', 'while', 'action']):
328
+ tolerable_indicators += 1
329
+ if 'debug ' in stripped and not stripped.startswith('debug('):
330
+ tolerable_indicators += 1
331
+ if 'lambda ' in stripped and not 'lambda(' in stripped:
332
+ tolerable_indicators += 1
333
+ if 'catch ' in stripped and not 'catch(' in stripped:
334
+ tolerable_indicators += 1
335
+ if 'catch((' in stripped:
336
+ tolerable_indicators += 1
337
+
338
+ if universal_indicators > tolerable_indicators:
339
+ return "universal"
340
+ elif tolerable_indicators > universal_indicators:
341
+ return "tolerable"
342
+ else:
343
+ return "mixed"
344
+
345
+ def get_fix_summary(self, validation_result):
346
+ """Get a summary of fixes that will be applied"""
347
+ error_fixes = [s for s in validation_result['suggestions'] if s['severity'] == 'error']
348
+ warning_fixes = [s for s in validation_result['suggestions'] if s['severity'] == 'warning']
349
+
350
+ return {
351
+ 'total_fixes': len(validation_result['suggestions']),
352
+ 'error_fixes': len(error_fixes),
353
+ 'warning_fixes': len(warning_fixes),
354
+ 'will_fix_errors': len(error_fixes) > 0,
355
+ 'will_fix_warnings': len(warning_fixes) > 0
356
+ }