added structure & interpreter & lexer & first ast stucture
This commit is contained in:
28
src/Interpreter/Interpreter.py
Normal file
28
src/Interpreter/Interpreter.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from Interpreter.Validator import Validator
|
||||
from Interpreter.Lexer import Lexer
|
||||
from Interpreter.Parser import Parser
|
||||
from Interpreter.Repo import Repo
|
||||
from Interpreter.Utils import Utils
|
||||
|
||||
|
||||
class Interpreter:
|
||||
|
||||
def __init__(self, repo: Repo, utils: Utils) -> None:
|
||||
self.__repo = repo
|
||||
self.__utils = utils
|
||||
self.__lexer = Lexer(repo, utils)
|
||||
self.__parser = Parser(repo, utils)
|
||||
self.__validator = Validator(repo, utils)
|
||||
|
||||
def interpret(self, line: str) -> bool:
|
||||
toks = []
|
||||
if self.__repo.error is None:
|
||||
toks = self.__lexer.tokenize(line)
|
||||
|
||||
if self.__repo.error is None:
|
||||
self.__parser.parse(toks)
|
||||
|
||||
if self.__repo.error is None:
|
||||
self.__validator.validate()
|
||||
|
||||
return self.__repo.error is None
|
139
src/Interpreter/Lexer.py
Normal file
139
src/Interpreter/Lexer.py
Normal file
@@ -0,0 +1,139 @@
|
||||
from Interpreter.Repo import Repo
|
||||
from Interpreter.Utils import Utils
|
||||
from Models.Token import Token
|
||||
|
||||
|
||||
class Lexer:
|
||||
|
||||
def __init__(self, repo: Repo, utils: Utils) -> None:
|
||||
self.__repo = repo
|
||||
self.__utils = utils
|
||||
|
||||
self.__ml_comment = False
|
||||
self.__toks = []
|
||||
|
||||
def __add_tok(self, value: str, type: str) -> None:
|
||||
if value != '':
|
||||
if type == 'word':
|
||||
if value in self.__repo.keywords:
|
||||
type = 'keyword'
|
||||
|
||||
elif value in self.__repo.types:
|
||||
type = 'type'
|
||||
|
||||
elif value in self.__repo.bool_values:
|
||||
type = 'bool'
|
||||
|
||||
elif value == 'empty':
|
||||
type = 'emptyType'
|
||||
|
||||
else:
|
||||
type = 'name'
|
||||
|
||||
self.__toks.append(Token(type, value))
|
||||
|
||||
def tokenize(self, line: str) -> list:
|
||||
self.__toks = []
|
||||
word = ''
|
||||
ol_comment = False
|
||||
is_string1 = False # 'hello'
|
||||
is_string2 = False # "hello"
|
||||
is_number = False
|
||||
is_expr_char = False
|
||||
|
||||
for i in range(0, len(line)):
|
||||
c = line[i]
|
||||
# ignore comments and spaces
|
||||
if not ol_comment and not self.__ml_comment:
|
||||
|
||||
# end of number
|
||||
if not c.isdigit() and is_number:
|
||||
self.__add_tok(word, 'number')
|
||||
word = ''
|
||||
is_number = False
|
||||
|
||||
# end of expression char
|
||||
if c not in self.__repo.expr_chars and is_expr_char:
|
||||
self.__add_tok(word, 'expr_char')
|
||||
word = ''
|
||||
is_expr_char = False
|
||||
|
||||
# comment filtering
|
||||
if c == '#' and not is_string1 and not is_string2:
|
||||
ol_comment = True
|
||||
|
||||
elif c == '/' and line[+1] == '/':
|
||||
ol_comment = True
|
||||
|
||||
elif c == '/' and line[+1] == '*':
|
||||
self.__ml_comment = True
|
||||
i += 2
|
||||
|
||||
# begin of is_string1
|
||||
elif c == '\'' and not is_string1:
|
||||
is_string1 = True
|
||||
word = ''
|
||||
|
||||
# end of is_string1
|
||||
elif c == '\'' and is_string1:
|
||||
is_string1 = False
|
||||
self.__add_tok(word, 'string')
|
||||
word = ''
|
||||
|
||||
# begin of is_string2
|
||||
elif c == '\"' and not is_string2:
|
||||
is_string2 = True
|
||||
word = ''
|
||||
|
||||
# end of is_string2
|
||||
elif c == '\"' and is_string2:
|
||||
is_string2 = False
|
||||
self.__add_tok(word, 'string')
|
||||
word = ''
|
||||
|
||||
# format char
|
||||
elif c in self.__repo.format_chars:
|
||||
self.__add_tok(word, 'word')
|
||||
self.__add_tok(c, 'format_char')
|
||||
word = ''
|
||||
|
||||
# begin of number
|
||||
elif c.isdigit() and not is_number and word == '':
|
||||
word += c
|
||||
is_number = True
|
||||
|
||||
# continue number
|
||||
elif c.isdigit() and is_number:
|
||||
word += c
|
||||
|
||||
# begin expression char
|
||||
elif c in self.__repo.expr_chars and not is_expr_char:
|
||||
word += c
|
||||
is_expr_char = True
|
||||
|
||||
# continue expression char
|
||||
elif c in self.__repo.expr_chars and is_expr_char:
|
||||
word += c
|
||||
|
||||
# bool expression char
|
||||
elif c in self.__repo.expr_chars:
|
||||
self.__add_tok(word, 'word')
|
||||
self.__add_tok(c, 'bool_expr_char')
|
||||
word = ''
|
||||
|
||||
# end of word
|
||||
elif c == ' ' and not is_string1 and not is_string2 or c == '\n':
|
||||
self.__add_tok(word, 'word')
|
||||
word = ''
|
||||
|
||||
else:
|
||||
word += c
|
||||
|
||||
if c == '\n' and ol_comment:
|
||||
ol_comment = False
|
||||
|
||||
if c == '*' and line[i + 1] == '/':
|
||||
self.__ml_comment = False
|
||||
|
||||
# self.__repo.output_tokens(self.__toks)
|
||||
return self.__toks
|
12
src/Interpreter/Parser.py
Normal file
12
src/Interpreter/Parser.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from Interpreter.Repo import Repo
|
||||
from Interpreter.Utils import Utils
|
||||
|
||||
|
||||
class Parser:
|
||||
|
||||
def __init__(self, repo: Repo, utils: Utils) -> None:
|
||||
self.__repo = repo
|
||||
self.__utils = utils
|
||||
|
||||
def parse(self, toks: list) -> None:
|
||||
self.__repo.output_tokens(toks)
|
54
src/Interpreter/Repo.py
Normal file
54
src/Interpreter/Repo.py
Normal file
@@ -0,0 +1,54 @@
|
||||
class Repo:
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.debug = True
|
||||
|
||||
# interpreter
|
||||
self.keywords = [
|
||||
# define keys
|
||||
'lib',
|
||||
'class',
|
||||
'func',
|
||||
# builtin functions
|
||||
'output',
|
||||
'input',
|
||||
'length',
|
||||
'range',
|
||||
# normal keywords
|
||||
'if',
|
||||
'elseif',
|
||||
'else',
|
||||
'pass',
|
||||
'in',
|
||||
# loops
|
||||
'while',
|
||||
'for',
|
||||
# access
|
||||
'public'
|
||||
]
|
||||
self.types = [
|
||||
'number',
|
||||
'string',
|
||||
'bool',
|
||||
'list',
|
||||
'dict',
|
||||
'emptyType',
|
||||
'void'
|
||||
]
|
||||
self.expr_chars = ['+', '-', '*', '/', '=']
|
||||
self.bool_expr_chars = ['<', '>', '!', '!=', '==', '>=', '<=']
|
||||
self.bool_values = ['true', 'false']
|
||||
self.format_chars = ['{', '}', '(', ')', ';', ':', ',']
|
||||
|
||||
# runtime
|
||||
self.error = None
|
||||
|
||||
def output_tokens(self, toks: list) -> None:
|
||||
if self.debug and len(toks) > 0:
|
||||
# outp_toks = []
|
||||
for tok in toks:
|
||||
# outp_toks.append({tok.value: tok.type})
|
||||
print({tok.value: tok.type})
|
||||
|
||||
# print(outp_toks)
|
||||
print('\n')
|
19
src/Interpreter/Utils.py
Normal file
19
src/Interpreter/Utils.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from termcolor import colored
|
||||
|
||||
from Interpreter.Repo import Repo
|
||||
|
||||
|
||||
class Utils:
|
||||
|
||||
def __init__(self, repo: Repo) -> None:
|
||||
self.__repo = repo
|
||||
|
||||
def input(self, prefix: str) -> str:
|
||||
return input(prefix)
|
||||
|
||||
def output(self, text: str) -> None:
|
||||
print(f'-> {text}')
|
||||
|
||||
def error(self) -> None:
|
||||
if self.__repo is not None:
|
||||
print(colored(f'{self.__repo.error.code}: {self.__repo.error.msg}', 'red'))
|
12
src/Interpreter/Validator.py
Normal file
12
src/Interpreter/Validator.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from Interpreter.Repo import Repo
|
||||
from Interpreter.Utils import Utils
|
||||
|
||||
|
||||
class Validator:
|
||||
|
||||
def __init__(self, repo: Repo, utils: Utils) -> None:
|
||||
self.__repo = repo
|
||||
self.__utils = utils
|
||||
|
||||
def validate(self) -> None:
|
||||
pass
|
0
src/Interpreter/__init__.py
Normal file
0
src/Interpreter/__init__.py
Normal file
Reference in New Issue
Block a user