########################################################
##	IMPORTS
########################################################
from strings_with_arrows import *
import string
import os
import math
import constants

########################################################
##	ERROR
########################################################

##class to handle the errors 

class Error:
	def __init__(self, pos_start, pos_end, error_name, details):
		self.pos_start = pos_start
		self.pos_end = pos_end
		self.error_name = error_name
		self.details = details

	def as_string(self):
		result = f'{self.error_name}:{self.details}\n' ##display error and Details
		result += f'File {self.pos_start.fn}, Line{self.pos_start.ln+1}'
		result += '\n\n' + string_with_arrows(self.pos_start.ftxt, self.pos_start, self.pos_end)
		return result

class IllegalCharError(Error): ##sub class of error invoked when a lexer comes across a character it doesnt support
	def __init__(self, pos_start, pos_end, details):
		super().__init__(pos_start,pos_end,'Illegal Character',details)

class ExpectedCharError(Error): ##sub class of error invoked when a parser comes across an invalid syntax
	def __init__(self, pos_start, pos_end, details):
		super().__init__(pos_start,pos_end,'Expected Character',details)

class InvalidSyntaxError(Error): ##sub class of error invoked when a parser comes across an invalid syntax
	def __init__(self, pos_start, pos_end, details):
		super().__init__(pos_start,pos_end,'Invalid Syntax',details)

class RTError(Error): ##sub class of error invoked when a parser comes across an invalid syntax
	def __init__(self, pos_start, pos_end, details,context):
		super().__init__(pos_start,pos_end,'Run Time Error',details)
		self.context = context


	def as_string(self):
		result = self.generate_traceback() ##to show the contexts
		result += f'{self.error_name}: {self.details}'
		result += '\n\n' + string_with_arrows(self.pos_start.ftxt, self.pos_start, self.pos_end)
		return result

	def generate_traceback(self):
		result = ''
		pos = self.pos_start
		ctx = self.context
		while ctx:
			result = f'  File {pos.fn}, line {str(pos.ln + 1)}, in {ctx.display_name}\n' + result
			pos = ctx.parent_entry_pos
			ctx = ctx.parent
		return 'Traceback (most recent call last):\n' + result