mylanguage
unknown
python
a year ago
5.8 kB
15
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