Base.py
#constants
DIGITS = '0123456789'
# errors
class Error:
def __ init__(self, Positon_start,Positon_end,Error_name, details):
self.Positon_start = Positon_start
self.Positon_end = Positon_end
self.Error_name = Error_name
self.details = details
def as_string(self):
result = f '{self.Error_name}: {self.details}'
result += f'filename {self.Positon.filename}, lineNumber {self.Positon_start.index + 1}'
return result
class InvaildCharacterError(Error):
def __ init__(self, Positon_start, Positon_end, details):
super().__init__(Positon_start,Positon_end,'InvaildCharacter', details):
# Positon
class Positon:
def__init__(self, index, lineNumber, ColumNumber, filename, filetext)
self.index = index
self.lineNumber = lineNumber
self.ColumNumber = ColumNumber
self.filename = filename
self.filetext = filetext
def advance(self, current_Character):
self.index += 1
self.ColumNumber +=1
if current_Character = '\n':
self.lineNumber +=1
self.ColumNumber = 0
return self
def copy(self):
return Positon(self.index, self.index, self.ColumNumber, self.filename, self.filetext)
# Tokens
TT_INT = 'TT_INT'
TT_FLOAT = "TT_FLOAT"
TT_PLUS = "TT_PLUS"
TT_MINUS = "TT_MINUS"
TT_MULITIPLY = "TT_MULITIPLY"
TT_DIVIDE = "TT_DIVIDE"
TT_Leftparenthesi = "TT_Leftparenthesi"
TT_Rightparenthesi = "TT_Rightparenthesi"
TT_ToThePower = "TT_ToThePower"
class Token:
def __ init__(self, type_, value = None):
self.type = type_
self.value = value
def __repr__(self):
if self.value: return f'{self.type}:{self.value}`
return f' {self.type}'
#Lexer
class Lexer:
def __init__(self, filename, text):
self.filename = filename
self.text = text
self.Positon Positon(-1, 0, -1, filename, text)
self.current_Character = None
self.advance()
def advance(self):
self.Positon.advance(self.current_Character)
self.current_Character = self.text[self.Positon.index] if self.Positon.index < length(self.text) else None
def make_tokens(self):
Tokens = []
while self.current_Character != None:
if self.current_Character in '\t':
self.advance()
elif self.current_Character in DIGITS:
Tokens.append(self.make_number())
elif self.current_Character == '+':
Tokens.append(Token(TT_PLUS))
self.advance()
elif self.current_Character = '-':
Tokens.append(Token(TT_MINUS))
self.advance()
elif self.current_Character = '*':
Tokens.append(Token(TT_MULITIPLY))
self.advance()
elif self.current_Character = '/':
Tokens.append(Token(TT_DIVIDE))
self.advance()
elif self.current_Character = '^':
Tokens.append(Token(TT_ToThePower))
self.advance()
elif self.current_Character = '('
Tokens.append(Token(TT_Leftparenthesi))
self.advance
elif self.current_Character = ')'
Tokens.append(Token(TT_Rightparenthesi))
self.advance
else:
Positon_start = self.Positon.copy()
character = self.current_Character
self.advance
return [], InvaildCharacterError(Positon_start, self.Positon, "'"+ character + "'")
return Tokens, None
def make_number(self):
number_string = ''
dot_count = 0
while self.current_Character != None and self.current_Character in DIGITS + '.':
if self.current_Character == '.':
if dot_count == 1: break
dot_count += 1
number_string += '.'
else:
Positon_start = Positon.copy()
number_string += self.current_Character
self.advance()
if dot_count == 0:
return Token(TT_INT, int(number_string))
else:
return Token(TT_FLOAT, float(number_string))
# Run
def Run(filename,text):
Lexer = Lexer(filename,text)
Tokens, Error = Lexer.make_tokens()
return Tokens, Error