bugfixes & improved language design

This commit is contained in:
Sven Heidemann 2020-05-25 20:32:46 +02:00
parent b9e938f8a1
commit b01204fdd4
6 changed files with 109 additions and 38 deletions

View File

@ -1,3 +1,5 @@
use Test from test;
// hi1 // hi1
# hi2 # hi2
/* /*
@ -11,6 +13,8 @@ lib Main {
var testEmpty: emptyType = empty; var testEmpty: emptyType = empty;
var testNum: number = 3.0; var testNum: number = 3.0;
var testBool_2: bool = 3 > 1; var testBool_2: bool = 3 > 1;
var testTest: Test = Test();
testTest.outp();
output('Hello World'); output('Hello World');
output(66); output(66);
output(3 + 3); output(3 + 3);
@ -24,7 +28,7 @@ lib Main {
test1234(range(0, 10)); test1234(range(0, 10));
} }
# public func test1234(param: list) { # public func test1234(param: list): list {
public func test1234(): void public func test1234(): void
{ {
/*for i in range(0, length(param)) { /*for i in range(0, length(param)) {
@ -40,5 +44,9 @@ lib test
public class Test public class Test
{ {
public func outp(): void {
output('Hello_world3');
}
} }
} }

View File

@ -14,10 +14,12 @@ class Interpreter:
self.__parser = Parser(repo, utils) self.__parser = Parser(repo, utils)
self.__validator = Validator(repo, utils) self.__validator = Validator(repo, utils)
def interpret(self, line: str) -> bool: def interpret(self, line_int: int, line_str: str) -> bool:
toks = [] toks = []
self.__utils.line_number = line_int
if self.__repo.error is None: if self.__repo.error is None:
toks = self.__lexer.tokenize(line) toks = self.__lexer.tokenize(line_str)
if self.__repo.error is None: if self.__repo.error is None:
self.__parser.parse(toks) self.__parser.parse(toks)

View File

@ -23,14 +23,15 @@ class Parser:
self.__i = 0 # for loop index self.__i = 0 # for loop index
self.__token_storage = [] self.__token_storage = []
self.__is_start_lib = False self.__is_start_lib = False
self.__is_start_class = False self.__is_start_class = False
self.__is_start_func = False self.__is_start_func = False
self.__is_public = False self.__is_public = False
def parse(self, toks: list) -> None: def parse(self, toks: list) -> None:
self.__tokens = toks self.__tokens = toks
# self.__repo.output_tokens(toks)
# output # output
if len(toks) > 0: if len(toks) > 0:
tokens = [] tokens = []
@ -68,14 +69,26 @@ class Parser:
return Token('EOL', 'EOL') return Token('EOL', 'EOL')
def __get_token_by_i_dif(self, delta: int) -> Token: def __get_token_by_i_dif(self, delta: int) -> Token:
if 0 < self.__i + delta < len(self.__tokens):
return self.__tokens[self.__i + delta] return self.__tokens[self.__i + delta]
else:
return Token('EOL', 'EOL')
def __is_scope_started(self) -> bool: def __is_scope_started(self) -> bool:
return self.__is_start_lib or self.__is_start_class or self.__is_start_func return self.__is_start_lib or self.__is_start_class or self.__is_start_func
def __is_only_lib_started(self) -> bool:
return self.__is_start_lib and not self.__is_start_class and not self.__is_start_func
def __is_only_class_started(self) -> bool:
return not self.__is_start_lib and self.__is_start_class and not self.__is_start_func
def __is_only_func_started(self) -> bool: def __is_only_func_started(self) -> bool:
return not self.__is_start_lib and not self.__is_start_class and self.__is_start_func return not self.__is_start_lib and not self.__is_start_class and self.__is_start_func
def __is_only_var_started(self) -> bool:
return not self.__is_start_lib and not self.__is_start_class and not self.__is_start_func
""" token checks """ """ token checks """
def __check(self): def __check(self):
# check tokens # check tokens
@ -86,28 +99,31 @@ class Parser:
self.__check_keyword(tok) self.__check_keyword(tok)
elif tok.type == 'type' or tok.type in self.__repo.types: elif tok.type == 'type' or tok.type in self.__repo.types:
pass self.__check_type(tok)
elif not self.__is_scope_started() and tok.type in self.__repo.var_types:
pass
elif tok.type == 'format_char': elif tok.type == 'format_char':
self.__check_format_char(tok) self.__check_format_char(tok)
elif not self.__is_scope_started() and tok.type == 'expr_char': elif not self.__is_scope_started() and tok.type == 'expr_char':
pass self.__check_expr_char(tok)
elif not self.__is_scope_started() and tok.type == 'bool_expr_char': elif not self.__is_scope_started() and tok.type == 'bool_expr_char':
self.__check_name(tok) self.__check_bool_expr_char(tok)
elif tok.type == 'name': elif tok.type == 'name':
self.__check_name(tok) self.__check_name(tok)
else: else:
self.__utils.error(Error(2.9, f'{tok.type}: {tok.value}')) self.__utils.error(Error(3.11, f'{tok.type}: {tok.value}'))
def __check_keyword(self, tok: Token) -> None: def __check_keyword(self, tok: Token) -> None:
if tok.value == 'lib': if tok.value == 'use':
pass
elif tok.value == 'from':
pass
elif tok.value == 'lib':
self.__is_start_lib = True self.__is_start_lib = True
elif tok.value == 'class': elif tok.value == 'class':
@ -122,22 +138,53 @@ class Parser:
self.__is_public = True self.__is_public = True
else: else:
if next.type == 'EOL': if next.type == 'EOL':
self.__utils.error(Error(2.8)) self.__utils.error(Error(3.10))
else: else:
self.__utils.error(Error(2.9, next.value)) self.__utils.error(Error(3.11, next.value))
elif tok.value == 'var':
next = self.__get_next_token()
if next.type == 'name':
self.__is_start_var = True
else:
if next.type == 'EOL':
self.__utils.error(Error(3.10))
else:
self.__utils.error(Error(3.11, next.value))
elif tok.value == 'output':
pass
elif tok.value == 'input':
pass
elif tok.value == 'range':
pass
elif tok.value == 'length':
pass
elif tok.value == 'pass':
pass
elif tok.value == 'exit':
pass
else:
self.__utils.error(Error(3.11, f'{tok.type}: {tok.value}'))
def __check_format_char(self, tok: Token) -> None: def __check_format_char(self, tok: Token) -> None:
if tok.value == '{': if tok.value == '{':
# token in storage must be name! # token in storage must be name!
if len(self.__token_storage) > 0 and self.__token_storage[0].type == 'name': if len(self.__token_storage) > 0 and self.__token_storage[0].type == 'name':
# lib # lib
if self.__is_start_lib and not self.__is_start_class and not self.__is_start_func: if self.__is_only_lib_started():
self.__lib = Lib(self.__token_storage[0].value) self.__lib = Lib(self.__token_storage[0].value)
self.__token_storage = [] self.__token_storage = []
self.__is_start_lib = False self.__is_start_lib = False
# class # class
elif not self.__is_start_lib and self.__is_start_class and not self.__is_start_func: elif self.__is_only_class_started():
access = '' access = ''
if self.__is_public: if self.__is_public:
access = 'public' access = 'public'
@ -148,7 +195,7 @@ class Parser:
self.__is_start_class = False self.__is_start_class = False
# func # func
elif not self.__is_start_lib and not self.__is_start_class and self.__is_start_func: elif self.__is_only_func_started():
access = '' access = ''
if len(self.__token_storage) > 1 and self.__token_storage[1].type == 'type': if len(self.__token_storage) > 1 and self.__token_storage[1].type == 'type':
@ -163,7 +210,7 @@ class Parser:
self.__utils.error(Error(3.7)) self.__utils.error(Error(3.7))
else: else:
self.__utils.error(Error(2.9, f'{tok.type}: {tok.value}')) self.__utils.error(Error(3.11, f'{tok.type}: {tok.value}'))
elif not self.__is_scope_started() and tok.value == '}': elif not self.__is_scope_started() and tok.value == '}':
if self.__lib is not None and self.__class is None and self.__func is None: if self.__lib is not None and self.__class is None and self.__func is None:
@ -179,10 +226,7 @@ class Parser:
self.__func = None self.__func = None
else: else:
self.__utils.error(Error(2.9, f'{tok.type}: {tok.value}')) self.__utils.error(Error(3.11, f'{tok.type}: {tok.value}'))
elif self.__is_only_func_started() and (tok.value == '(' or tok.value == ')'):
pass
elif not self.__is_scope_started() and tok.value in self.__repo.format_chars: elif not self.__is_scope_started() and tok.value in self.__repo.format_chars:
pass pass
@ -196,11 +240,31 @@ class Parser:
self.__utils.error(Error(3.7)) self.__utils.error(Error(3.7))
else: else:
self.__utils.error(Error(2.9, f'{tok.type}: {tok.value}')) self.__utils.error(Error(3.11, f'{tok.type}: {tok.value}'))
elif tok.value == '(':
pass
elif tok.value == ')':
pass
else:
self.__utils.error(Error(3.11, f'{tok.type}: {tok.value}'))
def __check_name(self, tok: Token) -> None: def __check_name(self, tok: Token) -> None:
if self.__is_start_lib or self.__is_start_class or self.__is_start_func: if self.__is_start_lib or self.__is_start_class or self.__is_start_func:
if len(self.__token_storage) == 0: if len(self.__token_storage) == 0:
self.__token_storage.append(tok) self.__token_storage.append(tok)
else: else:
self.__utils.error(Error(2.9, f'{tok.type}: {tok.value}')) self.__utils.error(Error(3.11, f'{tok.type}: {tok.value}'))
def __check_type(self, tok: Token) -> None:
pass
# self.__utils.error(Error(3.11, f'{tok.type}: {tok.value}'))
def __check_expr_char(self, tok: Token) -> None:
pass
def __check_bool_expr_char(self, tok: Token) -> None:
pass

View File

@ -10,11 +10,14 @@ class Repo:
'class', 'class',
'func', 'func',
'var', 'var',
'use',
'from',
# builtin functions # builtin functions
'output', 'output',
'input', 'input',
'length', 'length',
'range', 'range',
'exit',
# normal keywords # normal keywords
'if', 'if',
'elseif', 'elseif',
@ -37,17 +40,9 @@ class Repo:
'emptyType', 'emptyType',
'void' 'void'
] ]
self.var_types = [ self.format_chars = ['{', '}', '(', ')', ';', ':', ',', '.']
'any',
'number',
'string',
'bool',
'list',
'dict'
]
self.format_chars = ['{', '}', '(', ')', ';', ':', ',']
self.expr_chars = ['+', '-', '*', '/', '=', '^'] self.expr_chars = ['+', '-', '*', '/', '=', '^']
self.bool_expr_chars = ['<', '>', '!', '!=', '==', '>=', '<='] self.bool_expr_chars = ['<', '>', '!', '!=', '==', '>=', '<=', '&&', '||']
self.bool_values = ['true', 'false'] self.bool_values = ['true', 'false']
# runtime # runtime

View File

@ -8,6 +8,7 @@ class Utils:
def __init__(self, repo: Repo) -> None: def __init__(self, repo: Repo) -> None:
self.__repo = repo self.__repo = repo
self.line_number: int = 0
def input(self, prefix: str) -> str: def input(self, prefix: str) -> str:
return input(prefix) return input(prefix)
@ -17,4 +18,5 @@ class Utils:
def error(self, error: Error) -> None: def error(self, error: Error) -> None:
self.__repo.error = error self.__repo.error = error
print(colored(f'{self.__repo.error.code}: {self.__repo.error.msg}', 'red')) print(colored(f'Error in line {self.line_number}\n{self.__repo.error.code}: {self.__repo.error.msg}', 'red'))
# exit()

View File

@ -22,8 +22,8 @@ class Main:
def files(self, file: str) -> None: def files(self, file: str) -> None:
if os.path.isfile(file): if os.path.isfile(file):
f = open(file, 'r', encoding='utf-8').readlines() f = open(file, 'r', encoding='utf-8').readlines()
for line in f: for i in range(0, len(f)):
self.__interpreter.interpret(line) self.__interpreter.interpret(i+1, f[i])
else: else:
self.__utils.error(Error(1.1)) self.__utils.error(Error(1.1))