mylanguage
unknown
python
9 months ago
5.8 kB
13
Indexable
import re # Token types NUMBER = 'NUMBER' PLUS = 'PLUS' MINUS = 'MINUS' MUL = 'MUL' DIV = 'DIV' ASSIGN = 'ASSIGN' ID = 'ID' PRINT = 'PRINT' LPAREN = 'LPAREN' RPAREN = 'RPAREN' EOF = 'EOF' # End of File / End of Input # A simple lexer/tokenizer class Lexer: def __init__(self, text): self.text = text self.pos = 0 self.current_char = self.text[self.pos] def advance(self): """Advance the position and update the current_char.""" self.pos += 1 if self.pos > len(self.text) - 1: self.current_char = None # Indicates end of input else: self.current_char = self.text[self.pos] def skip_whitespace(self): while self.current_char is not None and self.current_char.isspace(): self.advance() def number(self): """Return a multi-digit number.""" result = '' while self.current_char is not None and self.current_char.isdigit(): result += self.current_char self.advance() return int(result) def get_next_token(self): """Tokenizes the input one token at a time.""" while self.current_char is not None: if self.current_char.isspace(): self.skip_whitespace() continue if self.current_char.isdigit(): return (NUMBER, self.number()) if self.current_char.isalpha(): return (ID, self.identifier()) if self.current_char == '=': self.advance() return (ASSIGN, '=') if self.current_char == '+': self.advance() return (PLUS, '+') if self.current_char == '-': self.advance() return (MINUS, '-') if self.current_char == '*': self.advance() return (MUL, '*') if self.current_char == '/': self.advance() return (DIV, '/') if self.current_char == '(': self.advance() return (LPAREN, '(') if self.current_char == ')': self.advance() return (RPAREN, ')') raise Exception(f"Invalid character: {self.current_char}") return (EOF, None) def identifier(self): """Return an identifier or a reserved keyword like 'print'.""" result = '' while self.current_char is not None and self.current_char.isalnum(): result += self.current_char self.advance() if result == 'print': return PRINT return result # Parser that converts tokens into statements class Parser: def __init__(self, lexer): self.lexer = lexer self.current_token = self.lexer.get_next_token() def eat(self, token_type): if self.current_token[0] == token_type: self.current_token = self.lexer.get_next_token() else: raise Exception(f"Invalid token {self.current_token}, expected {token_type}") def factor(self): """Handles numbers and parentheses""" token = self.current_token if token[0] == NUMBER: self.eat(NUMBER) return token[1] elif token[0] == LPAREN: self.eat(LPAREN) result = self.expr() self.eat(RPAREN) return result else: raise Exception("Factor: Invalid Syntax") def term(self): """Handles *, /""" result = self.factor() while self.current_token[0] in (MUL, DIV): token = self.current_token if token[0] == MUL: self.eat(MUL) result *= self.factor() elif token[0] == DIV: self.eat(DIV) result /= self.factor() return result def expr(self): """Handles +, -""" result = self.term() while self.current_token[0] in (PLUS, MINUS): token = self.current_token if token[0] == PLUS: self.eat(PLUS) result += self.term() elif token[0] == MINUS: self.eat(MINUS) result -= self.term() return result def assignment(self): """Handles variable assignments and print""" if self.current_token[0] == ID: var_name = self.current_token[1] self.eat(ID) self.eat(ASSIGN) value = self.expr() return ('assign', var_name, value) elif self.current_token[0] == PRINT: self.eat(PRINT) var_name = self.current_token[1] return ('print', var_name) else: raise Exception("Invalid Syntax") # Interpreter to evaluate the parsed expressions class Interpreter: def __init__(self, parser): self.parser = parser self.variables = {} def eval(self): node = self.parser.assignment() if node[0] == 'assign': self.variables[node[1]] = node[2] elif node[0] == 'print': var_name = node[1] if var_name in self.variables: print(self.variables[var_name]) else: raise Exception(f"Variable '{var_name}' is not defined") # Main program def main(): while True: try: text = input('basic_lang> ') if text.strip() == 'exit': break lexer = Lexer(text) parser = Parser(lexer) interpreter = Interpreter(parser) interpreter.eval() except Exception as e: print(e) if __name__ == '__main__': main()
Editor is loading...
Leave a Comment