Pin / pine_parser.py
Alikhani099961's picture
Update pine_parser.py
16c6a84 verified
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)