import re from typing import List, Dict, Optional, Tuple import numpy as np class PineScriptParser: """Professional-grade Pine Script analyzer with advanced features""" def __init__(self, code: str): self.original_code = code self.code = code.strip() self.version = self._detect_version() self.errors: List[str] = [] self.warnings: List[str] = [] self.optimizations: List[str] = [] self.formatting_issues: List[str] = [] self._analyzed = False def _detect_version(self) -> Optional[str]: """Detect Pine Script version with advanced pattern matching""" patterns = [ r'//\s*@version\s*=\s*(\d+)', r'//\s*version\s*=\s*(\d+)', r'@version\s*(\d+)' ] for pattern in patterns: match = re.search(pattern, self.code, re.IGNORECASE) if match: version = match.group(1) if version in ['4', '5', '6']: return version return None def _full_analysis(self): """Comprehensive code analysis""" if self._analyzed: return self._check_syntax() self._check_semantics() self._check_performance() self._check_formatting() self._analyzed = True def find_errors(self) -> List[str]: """Find all syntax and semantic errors""" self._full_analysis() return self.errors def find_warnings(self) -> List[str]: """Find all warnings and deprecations""" self._full_analysis() return self.warnings def find_optimizations(self) -> List[str]: """Find performance optimization opportunities""" self._full_analysis() return self.optimizations def get_formatting_suggestions(self) -> List[str]: """Get professional formatting recommendations""" self._full_analysis() return self.formatting_issues def _check_syntax(self): """Advanced syntax validation""" # Check for version declaration if not self.version: self.errors.append("Critical: Missing version declaration (//@version=X)") # Check for required components required_patterns = [ (r'(indicator|strategy)\s*\(', "Missing indicator/strategy declaration"), (r'plot|barcolor|fill', "No output functions found (plot, barcolor, etc.)") ] for pattern, message in required_patterns: if not re.search(pattern, self.code): self.warnings.append(message) # Check bracket balance if self.code.count('(') != self.code.count(')'): self.errors.append("Syntax Error: Unbalanced parentheses") if self.code.count('[') != self.code.count(']'): self.errors.append("Syntax Error: Unbalanced square brackets") if self.code.count('{') != self.code.count('}'): self.errors.append("Syntax Error: Unbalanced curly braces") def _check_semantics(self): """Deep semantic analysis""" # Check for common semantic issues if re.search(r'close\s*[+\-*/]\s*open', self.code): self.optimizations.append("Consider using 'close - open' instead of arithmetic operations for better performance") if re.search(r'length\s*=\s*\d+', self.code): self.warnings.append("Warning: Hardcoded lengths should be configurable via inputs") # Check for version-specific issues if self.version == '4': if re.search(r'request\.', self.code): self.errors.append("Error: request.* functions are not available in v4") def _check_performance(self): """Performance optimization checks""" # Check for inefficient loops if re.search(r'for\s+i\s+from\s+\d+\s+to\s+\d+', self.code): self.optimizations.append("Optimization: Consider using array functions instead of for-loops for better performance") # Check for redundant calculations if re.search(r'sma\(sma\(', self.code): self.optimizations.append("Optimization: Nested SMA calls can be combined for better efficiency") def _check_formatting(self): """Professional formatting checks""" lines = self.code.split('\n') # Check indentation indent_problems = 0 for i, line in enumerate(lines): if line.strip() and not line.startswith(' '): indent_problems += 1 if indent_problems > len(lines) * 0.1: # More than 10% lines have issues self.formatting_issues.append(f"Formatting: {indent_problems} lines with incorrect indentation (recommend 4 spaces)") # Check line length long_lines = [i+1 for i, line in enumerate(lines) if len(line) > 120] if long_lines: self.formatting_issues.append(f"Formatting: Long lines detected (lines: {', '.join(map(str, long_lines))})") def generate_fixed_code(self) -> str: """Generate professionally formatted and optimized code""" self._full_analysis() # Basic formatting fixes fixed_code = [] lines = self.original_code.split('\n') # Apply consistent indentation indent_level = 0 for line in lines: stripped = line.strip() if stripped.startswith(('if', 'for', 'while', 'else')) and stripped.endswith(':'): fixed_code.append(' ' * indent_level + stripped) indent_level += 1 elif stripped in ('end', 'else'): indent_level = max(0, indent_level - 1) fixed_code.append(' ' * indent_level + stripped) else: fixed_code.append(' ' * indent_level + stripped) # Ensure version declaration if not self.version: fixed_code.insert(0, "//@version=5") return '\n'.join(fixed_code)