bugfixes & improved language design
This commit is contained in:
parent
b9e938f8a1
commit
b01204fdd4
10
doc/test.bl
10
doc/test.bl
@ -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');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user