from typing import Text

DIGITS='0123456789'
###########################################
#自定义错误类类似于其他语言的抛出异常的异常类
###########################################

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}'
        result+=f'File {self.pos_start.fn},line {self.pos_start.ln+1}'
        return result

class Position:
    def __init__(self,idx,ln,col,fn,ftext):
        self.idx=idx
        self.ln=ln
        self.col=col
        self.fn=fn
        self.ftext=ftext

    def advance(self,current_char):
        self.idx+=1
        self.col+=1

        if current_char=='\n':
            self.ln+=1
            self.col+=1

        return self

    def copy(self):
        return Position(self.idx,self.ln,self.col,self.fn,self.ftext)
        
class IllegalCharError(Error):
    def __init__(self, pos_start,pos_end,details):
        super().__init__(pos_start,pos_end, 'Illegal Charactor', details)
        
TT_INT  ='INT'# int类型
TT_FLOAT='FLOAT'# float类型
TT_PLUS ='PLUS'# 加
TT_MINUS='MINUS'# 减
TT_MUL  ='MUL'# 乘
TT_DIV  ='DIV'# 除
TT_LPAREN='LPAREN'# 左括号
TT_RPAREN='RPAREN'# 右括号
TT_EQUASL ='EQUAL'# 等于号

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}'

class Lexer:
    def __init__(self,fn,text):
        self.fn=fn
        self.text=text
        self.pos=Position(-1,0,-1,fn,text)
        self.current_char=None
        self.advance()

    def advance(self):
        self.pos.advance(self.current_char)
        self.current_char=self.text[self.pos.idx] if self.pos.idx<len(self.text)else None

    def make_tokens(self):
        tokens=[]
        while self.current_char !=None:
            if self.current_char in ' \t':
                self.advance()
            elif self.current_char in DIGITS:
                tokens.append(self.make_number())
            elif self.current_char=='+':
                tokens.append(Token(TT_PLUS))
                self.advance()
            elif self.current_char == '-':
                tokens.append(Token(TT_MINUS))
                self.advance()
            elif self.current_char == '*':
                tokens.append(Token(TT_MUL))
                self.advance()
            elif self.current_char == '/':
                tokens.append(Token(TT_DIV))
                self.advance()
            elif self.current_char == '(':
                tokens.append(Token(TT_LPAREN))
                self.advance()
            elif self.current_char == ')':
                tokens.append(Token(TT_RPAREN))
                self.advance()
            elif self.current_char == '=':
                tokens.append(Token(TT_EQUASL))
                self.advance()
            else:#输入非法字符
                pos_start=self.pos.copy()
                char=self.current_char
                self.advance()
                return [],IllegalCharError(pos_start,self.pos, "' "+char+" '")
        return tokens,None

    def make_number(self):
        num_str=''
        dot_count=0

        while self.current_char != None and self.current_char in DIGITS+ '.':
            if self.current_char=='.':
                if dot_count==1:break
                dot_count+=1
                num_str+='.'
            else:
                num_str+=self.current_char
            self.advance()
        if dot_count==0:
            return Token(TT_INT,int(num_str))
        else:
            return Token(TT_FLOAT,float(num_str))

def run(fn,text):
    lexer=Lexer(fn,text)
    tokens,error=lexer.make_tokens()
    return tokens,error