Improved parsing

This commit is contained in:
Sven Heidemann 2020-09-17 19:33:52 +02:00
parent cb54261118
commit dfc4b44b25
31 changed files with 717 additions and 189 deletions

View File

@ -1,9 +1,7 @@
len 3: lib main {
lib main { <public> class test {
min len 3, max len 4: <public> func test(): void {
<public> class test {
min len 5 <public> var: bool <= test <<Bool, String, Num, Any, Instance>> >;
<public> func test() {

View File

@ -1,12 +1,12 @@
lib Tests { lib Tests {
public class test2 { public class test2 {
var string_a = string1(); var string_a = strings();
public func continue(): void { public func continue(): void {
input(string_a.string1 + ': '); input(string_a.string1 + ': ');
} }
} }
class strings { class strings {
var public string1 = "hello world"; public var string1 = "hello world";
} }
} }

25
src/First.bl Normal file
View File

@ -0,0 +1,25 @@
// hi1
# hi2
/*
hi3
*/
public lib Main {
class Program {
var test: bool = false;
var test2: Program2 = empty;
var test3: Program2 = Test();
func Main(): void {
#func Main {
var hallo: any;
#output('Hello');
#output(this.isTrue(false));
}
func isTrue(value: bool): bool {
#func isTrue {
#return value;
}
}
}

View File

@ -14,22 +14,19 @@ 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_int: int, line_str: str) -> bool: def interpret(self, line_str: str) -> None:
toks = [] """
ast = [] Interprets code line
:param line_str:
:return:
"""
tokens = []
self.__utils.line_number = line_int if self.__repo.is_error is None:
if self.__repo.error is None: tokens = self.__lexer.tokenize(line_str)
toks = self.__lexer.tokenize(line_str)
self.__repo.output_tokens(toks) if self.__repo.is_error is None:
self.__parser.parse(tokens)
if self.__repo.error is None: # if self.__repo.is_error is None:
ast = self.__parser.parse(toks) # self.__validator.validate(self.__repo.AST)
# self.__repo.output_ast(ast)
if self.__repo.error is None:
self.__validator.validate(ast)
return self.__repo.error is None

View File

@ -1,6 +1,10 @@
from typing import List
from Interpreter.Repo import Repo from Interpreter.Repo import Repo
from Interpreter.Utils import Utils from Interpreter.Utils import Utils
from Models.Interpreter.Token import Token from Models.Interpreter.Token import Token
from Models.Interpreter.TokenTypes import TokenTypes
from Models.Interpreter.UnresolvedTokenTypes import UnresolvedTokenTypes
class Lexer: class Lexer:
@ -9,31 +13,58 @@ class Lexer:
self.__repo = repo self.__repo = repo
self.__utils = utils self.__utils = utils
self.__ml_comment = False self.__is_ml_comment = False
self.__toks = []
def __add_tok(self, tokens: List[Token], value: str, input_token_type: UnresolvedTokenTypes) -> None:
"""
Creates token object
:param value:
:param token_type:
:return:
"""
token_type: TokenTypes = TokenTypes.Empty
def __add_tok(self, value: str, type: str) -> None:
if value != '': if value != '':
if type == 'word': if input_token_type == UnresolvedTokenTypes.Word:
if value in self.__repo.keywords: if value in self.__repo.keywords:
type = 'keyword' token_type = TokenTypes.Keyword
elif value in self.__repo.types: elif value in self.__repo.types:
type = 'type' token_type = TokenTypes.Type
elif value in self.__repo.bool_values: elif value in self.__repo.bool_values:
type = 'bool' token_type = TokenTypes.Bool
elif value == 'empty': elif value == UnresolvedTokenTypes.Empty:
type = 'emptyType' token_type = TokenTypes.Empty
else: else:
type = 'name' token_type = TokenTypes.Name
self.__toks.append(Token(type, value)) elif input_token_type == UnresolvedTokenTypes.Number:
token_type = TokenTypes.Number
def tokenize(self, line: str) -> list: elif input_token_type == UnresolvedTokenTypes.String:
self.__toks = [] token_type = TokenTypes.String
elif input_token_type == UnresolvedTokenTypes.Expression_Character:
token_type = TokenTypes.Expression_Character
elif input_token_type == UnresolvedTokenTypes.Bool_Expression_Character:
token_type = TokenTypes.Bool_Expression_Character
elif input_token_type == UnresolvedTokenTypes.Format_Character:
token_type = TokenTypes.Format_Character
tokens.append(Token(token_type, value))
def tokenize(self, line: str) -> List[Token]:
"""
Creates token list from code line
:param line:
:return:
"""
tokens: List[Token] = []
word = '' word = ''
ol_comment = False ol_comment = False
is_string1 = False # 'hello' is_string1 = False # 'hello'
@ -44,27 +75,27 @@ class Lexer:
for i in range(0, len(line)): for i in range(0, len(line)):
c = line[i] c = line[i]
# ignore comments and spaces # ignore comments and spaces
if not ol_comment and not self.__ml_comment: if not ol_comment and not self.__is_ml_comment:
# comment filtering # comment filtering
if c == '#' and not is_string1 and not is_string2: if c == '#' and not is_string1 and not is_string2:
ol_comment = True ol_comment = True
elif line[i-1] == '/' and c == '/': elif line[i - 1] == '/' and c == '/':
ol_comment = True ol_comment = True
elif line[i-1] == '/' and c == '*': elif line[i - 1] == '/' and c == '*':
self.__ml_comment = True self.__is_ml_comment = True
i += 2 i += 2
# end of number # end of number
elif not c.isdigit() and c != '.' and is_number: elif not c.isdigit() and c != '.' and is_number:
self.__add_tok(word, 'number') self.__add_tok(tokens, word, UnresolvedTokenTypes.Number)
word = '' word = ''
is_number = False is_number = False
# end of expression char # end of expression char
elif c not in self.__repo.expr_chars and is_expr_char: elif c not in self.__repo.expr_chars and is_expr_char:
self.__add_tok(word, 'expr_char') self.__add_tok(tokens, word, UnresolvedTokenTypes.Expression_Character)
word = '' word = ''
is_expr_char = False is_expr_char = False
@ -76,7 +107,7 @@ class Lexer:
# end of is_string1 # end of is_string1
elif c == '\'' and is_string1: elif c == '\'' and is_string1:
is_string1 = False is_string1 = False
self.__add_tok(word, 'string') self.__add_tok(tokens, word, UnresolvedTokenTypes.String)
word = '' word = ''
# begin of is_string2 # begin of is_string2
@ -87,13 +118,13 @@ class Lexer:
# end of is_string2 # end of is_string2
elif c == '\"' and is_string2: elif c == '\"' and is_string2:
is_string2 = False is_string2 = False
self.__add_tok(word, 'string') self.__add_tok(tokens, word, UnresolvedTokenTypes.String)
word = '' word = ''
# format char # format char
elif c in self.__repo.format_chars: elif c in self.__repo.format_chars:
self.__add_tok(word, 'word') self.__add_tok(tokens, word, UnresolvedTokenTypes.Word)
self.__add_tok(c, 'format_char') self.__add_tok(tokens, c, UnresolvedTokenTypes.Format_Character)
word = '' word = ''
# begin of number # begin of number
@ -116,13 +147,13 @@ class Lexer:
# bool expression char # bool expression char
elif c in self.__repo.bool_expr_chars: elif c in self.__repo.bool_expr_chars:
self.__add_tok(word, 'word') self.__add_tok(tokens, word, UnresolvedTokenTypes.Word)
self.__add_tok(c, 'bool_expr_char') self.__add_tok(tokens, c, UnresolvedTokenTypes.Bool_Expression_Character)
word = '' word = ''
# end of word # end of word
elif c == ' ' and not is_string1 and not is_string2 or c == '\n': elif c == ' ' and not is_string1 and not is_string2 or c == '\n':
self.__add_tok(word, 'word') self.__add_tok(tokens, word, UnresolvedTokenTypes.Word)
word = '' word = ''
else: else:
@ -132,6 +163,6 @@ class Lexer:
ol_comment = False ol_comment = False
if line[i - 1] == '*' and c == '/': if line[i - 1] == '*' and c == '/':
self.__ml_comment = False self.__is_ml_comment = False
return self.__toks return tokens

View File

@ -1,10 +1,20 @@
from typing import List, Optional
from termcolor import colored
from Interpreter.Repo import Repo from Interpreter.Repo import Repo
from Interpreter.Utils import Utils from Interpreter.Utils import Utils
from Models.Interpreter.Error import Error from Models.AbstractSyntaxTree.Class import Class
from Models.AbstractSyntaxTree.Function import Function
from Models.AbstractSyntaxTree.Library import Library
from Models.AbstractSyntaxTree.Variable import Variable
from Models.Interpreter.Error import Error, ErrorCode
from Models.Interpreter.ExpressionCharacters import ExpressionCharacters
from Models.Interpreter.FormatCharacters import FormatCharacters
from Models.Interpreter.Keywords import Keywords
from Models.Interpreter.Token import Token from Models.Interpreter.Token import Token
from Models.Nodes.Class import Class from Models.Interpreter.TokenTypes import TokenTypes
from Models.Nodes.Func import Func from Models.Interpreter.Types import Types
from Models.Nodes.Lib import Lib
class Parser: class Parser:
@ -13,37 +23,295 @@ class Parser:
self.__repo = repo self.__repo = repo
self.__utils = utils self.__utils = utils
self.__ast = [] # library status
self.__is_creating_library = False
self.__is_saving_library = False
self.__library: Optional[Library] = None
def parse(self, toks: list) -> []: # class status
self.__tokens = toks self.__is_creating_class = False
self.__ast = [] self.__is_saving_class = False
self.__class: Optional[Class] = None
# function status
self.__is_creating_function = False
self.__is_creating_function_parameters = False
self.__is_saving_function = False
self.__function: Optional[Function] = None
# variable status
self.__is_creating_variable = False
self.__is_saving_variable = False
self.__variable: Optional[Variable] = None
# type status
self.__is_creating_type = False
self.__type: Optional[Types] = None
# common
self.__next_is_public = True
def parse(self, tokens: List[Token]) -> None:
"""
Creates abstract syntax tree from token list
:param tokens:
:return:
"""
# output # output
if len(toks) > 0: if len(tokens) == 0:
tokens = [] return None
for t in toks:
tokens.append({t.value: t.type})
# print(tokens) output_tokens = []
for t in tokens:
output_tokens.append({t.value: t.type})
# print(output_tokens)
self.__check() for i in range(0, len(tokens)):
token = tokens[i]
print(colored(f'>> {self.__utils.line_number}: {token.type} {token.value}', 'blue'))
# output """ error status checks """
if len(self.__repo.ast) > 1: # check if var name is valid
print('___') if i-1 >= 0 and self.__is_creating_variable and tokens[i-1].value == Keywords.Variable:
for a_lib in self.__repo.ast: if token.type != TokenTypes.Name:
print(a_lib.name) self.__utils.error(Error(ErrorCode.Unexpected, f'{token.type.name}: {token.value}'))
for a_class in a_lib.ast:
print(a_class.name, a_class.access)
for a_funcs in a_class.ast:
print(a_funcs.name, a_funcs.return_type, a_funcs.access)
print('___') """ normal status checks """
# print(self.__repo.ast, '\n') # token is member of variable value
if self.__is_saving_variable and token.value != FormatCharacters.chars.value[FormatCharacters.Semicolon.value] and self.__variable is not None:
print(6, 'save variable value')
self.__variable.value.append(token)
return self.__ast # token type keyword
if token.type == TokenTypes.Keyword:
self.__check_token_keyword(tokens, i, token)
def __check(self) -> None: # token type format character
for i in range(0, len(self.__tokens)): elif token.type == TokenTypes.Format_Character:
tok = self.__tokens[i] self.__check_token_format_character(token)
# print(tok.value, tok.type)
# token type expression character
elif token.type == TokenTypes.Expression_Character:
self.__check_token_expression_character(token)
# token type name
elif token.type == TokenTypes.Name:
self.__check_token_name(token)
# token type type
elif token.type == TokenTypes.Type:
self.__check_token_type(token)
""" validation function """
def __check_token_keyword(self, tokens: List[Token], i: int, token: Token) -> None:
if token.value == Keywords.Library:
# create library
self.__is_creating_library = True
self.__library = Library()
self.__set_is_public(self.__library)
print(1, 'create lib')
elif token.value == Keywords.Class:
# create class
self.__is_creating_class = True
self.__class = Class()
self.__set_is_public(self.__class)
print(2, 'create class')
elif token.value == Keywords.Function:
# create function
self.__is_creating_function = True
self.__function = Function()
self.__set_is_public(self.__function)
print(3, 'create function')
elif token.value == Keywords.Variable:
self.__is_creating_variable = True
self.__variable = Variable()
print(6, 'create variable')
elif token.value == Keywords.Public:
if self.__is_saving_function:
self.__utils.error(Error(ErrorCode.Unexpected, f'{token.type.name}: {token.value}'))
return
self.__next_is_public = True
print(0, 'Next is public')
elif self.__next_is_public:
if i - 1 > 0:
error_msg = f'{token.type.name}: {tokens[i - 1].value}'
else:
error_msg = 'keyword: public'
self.__utils.error(Error(ErrorCode.Unexpected, error_msg))
def __check_token_format_character(self, token: Token) -> None:
if token.value == FormatCharacters.chars.value[FormatCharacters.Left_Brace.value]:
if self.__is_creating_library:
# set status to save vars and funcs to library
self.__is_creating_library = False
self.__is_saving_library = True
print(1, 'status save lib')
elif self.__is_creating_class:
# set status to save vars and funcs to class
self.__is_creating_class = False
self.__is_saving_class = True
print(2, 'status save class')
elif self.__is_creating_function:
# set status to save vars and commands to function
self.__is_creating_function = False
self.__is_saving_function = True
print(3, 'status save function')
# check for type end
if self.__is_creating_type:
self.__check_for_type_end()
elif token.value == FormatCharacters.chars.value[FormatCharacters.Right_Brace.value]:
if self.__is_saving_function:
# save function to class
self.__is_saving_function = False
if self.__class is not None:
self.__class.functions.append(self.__function)
print(3, f'saved function {self.__function.name}')
else:
self.__utils.error(Error(ErrorCode.Unexpected, f'function: {self.__function.name}'))
self.__function = None
elif self.__is_saving_class:
# save class to library
self.__is_saving_class = False
if self.__library is not None:
self.__library.classes.append(self.__class)
print(2, f'saved class {self.__class.name}')
else:
self.__utils.error(Error(ErrorCode.Unexpected, f'class: {self.__class.name}'))
self.__class = None
elif self.__is_saving_library:
# save library to ast
self.__is_saving_library = False
self.__repo.AST.libs.append(self.__library)
print(1, f'saved lib {self.__library.name}')
self.__library = None
elif token.value == FormatCharacters.chars.value[FormatCharacters.Left_Parenthesis.value]:
if self.__is_creating_function:
self.__is_creating_function_parameters = True
print(4, 'create function parameters')
elif token.value == FormatCharacters.chars.value[FormatCharacters.Right_Parenthesis.value]:
if self.__is_creating_function:
self.__is_creating_function_parameters = False
self.__type = None
print(4, 'save function parameters')
# check for type end
if self.__is_creating_type:
self.__check_for_type_end()
elif token.value == FormatCharacters.chars.value[FormatCharacters.Colon.value]:
self.__check_create_type(token)
elif token.value == FormatCharacters.chars.value[FormatCharacters.Semicolon.value]:
if self.__is_creating_type:
self.__check_for_type_end()
if self.__is_saving_variable:
self.__is_saving_variable = False
self.__add_variable()
self.__variable = None
print(6, 'status saved variable')
elif self.__is_creating_variable:
self.__is_creating_variable = False
self.__is_saving_variable = True
self.__add_variable()
self.__variable = None
print(6, 'status saved variable')
def __check_token_expression_character(self, token: Token) -> None:
if token.value == ExpressionCharacters.chars.value[ExpressionCharacters.Equal.value]:
# check for type end
if self.__is_creating_type:
self.__is_creating_variable = False
self.__is_saving_variable = True
self.__check_for_type_end()
def __check_token_name(self, token: Token) -> None:
if self.__is_creating_type and self.__type is not None:
self.__type = token.value
print(5, 'save type')
elif self.__is_creating_variable and self.__variable is not None:
self.__variable.name = token.value
print(6, 'save variable name')
elif self.__is_creating_library:
# save library name
self.__library.name = token.value
print(1, 'lib name')
elif self.__is_creating_class:
# save class name
self.__class.name = token.value
print(2, 'class name')
elif self.__is_creating_function and not self.__is_creating_function_parameters:
# save function name
self.__function.name = token.value
print(3, 'function name')
def __check_token_type(self, token: Token) -> None:
if self.__is_creating_function and self.__function is not None and not self.__is_creating_function_parameters:
self.__function.return_type = Types(Types.strings.value.index(token.value))
print(3, 'save function type')
elif self.__is_creating_type:
self.__type = Types(Types.strings.value.index(token.value))
print(5, 'save type')
""" util functions """
def __set_is_public(self, ast_element):
if ast_element is not None and self.__next_is_public:
ast_element.is_public = True
self.__next_is_public = False
def __check_for_type_end(self):
# end status creating type
self.__is_creating_type = False
print(5, 'status saved type')
def __check_create_type(self, token: Token):
if self.__is_creating_function or self.__is_creating_function_parameters or self.__is_creating_variable:
self.__is_creating_type = True
print(5, 'create type')
else:
self.__utils.error(Error(ErrorCode.Unexpected, f'{token.type.name}: {token.value}'))
def __add_variable(self):
if len(self.__variable.value) == 0:
self.__variable.value.append(Token(TokenTypes.Empty, Types.strings.value[Types.Empty.value]))
if self.__type is not None:
self.__variable.type = self.__type
else:
self.__utils.error(Error(ErrorCode.Expected, f'type'))
if self.__is_saving_function and self.__function is not None:
self.__function.variables.append(self.__variable)
elif self.__is_saving_class and self.__class is not None:
self.__class.variables.append(self.__variable)
else:
self.__utils.error(Error(ErrorCode.Unexpected, f'variable: {self.__variable.name}'))

View File

@ -1,3 +1,10 @@
from Models.AbstractSyntaxTree.RuntimeAbstractSyntaxTree import RuntimeAbstractSyntaxTree
from Models.Interpreter.Booleans import Booleans
from Models.Interpreter.FormatCharacters import FormatCharacters
from Models.Interpreter.Keywords import Keywords
from Models.Interpreter.Types import Types
class Repo: class Repo:
def __init__(self) -> None: def __init__(self) -> None:
@ -5,56 +12,58 @@ class Repo:
# interpreter # interpreter
self.keywords = [ self.keywords = [
# define keys # define keywords
'lib', Keywords.Library,
'class', Keywords.Class,
'func', Keywords.Function,
'var', Keywords.Variable,
'use', Keywords.Use,
'from', Keywords.From,
# builtin functions # builtin functions
'output', Keywords.Output,
'input', Keywords.Input,
'length', Keywords.Length,
'range', Keywords.Range,
'exit', Keywords.Exit,
# normal keywords # normal keywords
'if', Keywords.If,
'elseif', Keywords.ElseIf,
'else', Keywords.Else,
'pass', Keywords.Pass,
'in', Keywords.If,
Keywords.Return,
# loops # loops
'while', Keywords.While,
'for', Keywords.For,
# access # access
'public' Keywords.Public
] ]
self.types = [ self.types = [
'any', Types.strings.value[Types.Any.value],
'number', Types.strings.value[Types.Number.value],
'string', Types.strings.value[Types.String.value],
'bool', Types.strings.value[Types.Bool.value],
'list', Types.strings.value[Types.List.value],
'dict', Types.strings.value[Types.Dict.value],
'emptyType', Types.strings.value[Types.Empty.value],
'void' Types.strings.value[Types.Void.value]
]
self.format_chars = [
FormatCharacters.chars.value[FormatCharacters.Left_Brace.value],
FormatCharacters.chars.value[FormatCharacters.Right_Brace.value],
FormatCharacters.chars.value[FormatCharacters.Left_Parenthesis.value],
FormatCharacters.chars.value[FormatCharacters.Right_Parenthesis.value],
FormatCharacters.chars.value[FormatCharacters.Left_Bracket.value],
FormatCharacters.chars.value[FormatCharacters.Right_Bracket.value],
FormatCharacters.chars.value[FormatCharacters.Semicolon.value],
FormatCharacters.chars.value[FormatCharacters.Colon.value],
FormatCharacters.chars.value[FormatCharacters.Comma.value],
FormatCharacters.chars.value[FormatCharacters.Point.value]
] ]
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 = [Booleans.Right, Booleans.Wrong]
# runtime # runtime
self.error = None self.is_error = None
self.ast = [] self.AST: RuntimeAbstractSyntaxTree = RuntimeAbstractSyntaxTree()
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')

View File

@ -17,6 +17,6 @@ class Utils:
print(f'-> {text}') print(f'-> {text}')
def error(self, error: Error) -> None: def error(self, error: Error) -> None:
self.__repo.error = error self.__repo.is_error = error
print(colored(f'Error in line {self.line_number}\n{self.__repo.error.code}: {self.__repo.error.msg}', 'red')) print(colored(f'Error in line {self.line_number}\n{self.__repo.is_error.msg}', 'red'))
# exit() # exit()

View File

@ -1,7 +1,8 @@
import os import os
import sys import sys
from pprint import pprint
from Models.Interpreter.Error import Error from Models.Interpreter.Error import Error, ErrorCode
from ServiceInitializer import ServiceInitializer from ServiceInitializer import ServiceInitializer
@ -14,20 +15,31 @@ class Main:
self.__interpreter = self.__services.interpreter self.__interpreter = self.__services.interpreter
def console(self) -> None: def console(self) -> None:
print('sh-edraft.de basic language interpreter:') """
Getting code from console input
:return:
"""
i = 0 i = 0
cont = True while self.__repo.is_error is not None:
while cont: self.__utils.line_number = i + 1
cont = self.__interpreter.interpret(i+1, input('> ')) self.__interpreter.interpret(self.__utils.line_number, input('> '))
i += 1 i += 1
def files(self, file: str) -> None: def files(self, file: str) -> None:
"""
Getting input from file
:param file:
:return:
"""
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 i in range(0, len(f)): for i in range(0, len(f)):
self.__interpreter.interpret(i+1, f[i]) self.__utils.line_number = i + 1
self.__interpreter.interpret(f[i])
print(self.__repo.AST)
else: else:
self.__utils.error(Error(1.1)) self.__utils.is_error(Error(ErrorCode.FileNotFound))
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -0,0 +1,9 @@
from typing import List
from Models.Interpreter.Token import Token
class AbstractSyntaxTree:
def __init__(self):
self.tokens: List[Token] = []

View File

@ -0,0 +1,13 @@
from typing import List
from Models.AbstractSyntaxTree.Function import Function
from Models.AbstractSyntaxTree.Variable import Variable
class Class:
def __init__(self):
self.name: str = ''
self.variables: List[Variable] = []
self.functions: List[Function] = []
self.is_public = False

View File

@ -0,0 +1,14 @@
from typing import List
from Models.AbstractSyntaxTree.Variable import Variable
from Models.Interpreter.Types import Types
class Function:
def __init__(self) -> None:
self.name: str = ''
self.variables: List[Variable] = []
self.instructions: [] = []
self.return_type: Types = Types.Any
self.is_public = False

View File

@ -0,0 +1,9 @@
from Models.AbstractSyntaxTree.AbstractSyntaxTree import AbstractSyntaxTree
from Models.AbstractSyntaxTree.InstructionTypes import InstructionTypes
class Instruction:
def __init__(self):
self.type: InstructionTypes = InstructionTypes.Unknown
self.ast: AbstractSyntaxTree = AbstractSyntaxTree()

View File

@ -0,0 +1,10 @@
from enum import Enum
class InstructionTypes(Enum):
Unknown = 0
Expression = 1
Bool_Expression = 2
Assignment = 3
Call = 4

View File

@ -0,0 +1,11 @@
from typing import List
from Models.AbstractSyntaxTree.Class import Class
class Library:
def __init__(self):
self.name: str = ''
self.classes: List[Class] = []
self.is_public = False

View File

@ -0,0 +1,9 @@
from typing import List
from Models.AbstractSyntaxTree.Library import Library
class RuntimeAbstractSyntaxTree:
def __init__(self):
self.libs: List[Library] = []

View File

@ -0,0 +1,12 @@
from typing import List
from Models.Interpreter.Token import Token
class Variable:
def __init__(self):
self.name: str = ''
self.type: str = ''
self.value: List[Token] = []
self.is_public = False

View File

@ -0,0 +1,4 @@
class Booleans:
Right = 'true'
Wrong = 'false'

View File

@ -1,34 +1,27 @@
from enum import Enum
class ErrorCode(Enum):
StartFailed = 'Start failed'
FileNotFound = 'File not found'
Unknown = 'Unknown {}'
Inaccessible = '{} inaccessible'
Unexpected = 'Unexpected {}'
Expected = 'Expected {}'
LibInLib = 'Lib in lib'
LibInClass = 'Lib in class'
LibInFunc = 'Lib in func'
ClassInClass = 'Class in class'
ClassInFunc = 'Class in func'
FuncInLib = 'Func in lib'
FuncInFunc = 'Func in func'
class Error: class Error:
def __init__(self, code: float, msg: str = ''): def __init__(self, code: ErrorCode, msg: str = ''):
self.code = code self.code = code
self.__msgs = { self.msg = code.value.format(msg)
# Interpreter:
1.0: 'Start failed',
1.1: 'File not found',
# Runtime:
2.0: 'Unknown keyword',
2.1: 'Unknown type',
2.2: 'Unknown variable',
2.3: 'Unknown function',
2.4: 'Unknown class',
2.5: 'Unknown library',
# Parser:
3.0: 'Lib in lib',
3.1: 'Lib in class',
3.2: 'Lib in func',
3.3: 'Class in class',
3.4: 'Class in func',
3.5: 'Func in lib',
3.6: 'Func in func',
3.7: 'Expected: type',
3.8: 'Access error: no export',
3.9: 'Expression error',
3.10: 'Unexpected end of line',
3.11: 'Unexpected {}', # other types
}
self.msg = self.__msgs[code].format(msg)

View File

@ -0,0 +1,19 @@
from enum import Enum
class ExpressionCharacters(Enum):
Plus = 0
Minus = 1
Asterisk = 2
Slash = 3
Equal = 4
Caret = 5
chars = [
'+',
'-',
'*',
'/',
'=',
'^'
]

View File

@ -0,0 +1,27 @@
from enum import Enum
class FormatCharacters(Enum):
Left_Brace = 0
Right_Brace = 1
Left_Parenthesis = 2
Right_Parenthesis = 3
Left_Bracket = 4
Right_Bracket = 5
Semicolon = 6
Colon = 7
Comma = 8
Point = 9
chars = [
'{',
'}',
'(',
')',
'[',
']',
';',
':',
',',
'.'
]

View File

@ -0,0 +1,30 @@
class Keywords:
# define keywords
Library: str = 'lib'
Class: str = 'class'
Function: str = 'func'
Variable: str = 'var'
Use: str = 'use'
From: str = 'from'
# builtin functions
Output: str = 'output'
Input: str = 'input'
Length: str = 'length'
Range: str = 'range'
Exit: str = 'exit'
# normal keywords
If: str = 'if'
ElseIf: str = 'elseif'
Else: str = 'else'
Pass: str = 'pass'
In: str = 'in'
Return: str = 'return'
# loops
While: str = 'while'
For: str = 'for'
# access
Public: str = 'public'

View File

@ -1,5 +1,8 @@
from Models.Interpreter import TokenTypes
class Token: class Token:
def __init__(self, type: str, value: str) -> None: def __init__(self, token_type: TokenTypes, value: str) -> None:
self.type = type self.type: TokenTypes = token_type
self.value = value self.value = value

View File

@ -0,0 +1,14 @@
from enum import Enum
class TokenTypes(Enum):
Empty = 0
Keyword = 1
Type = 2
Name = 3
Bool = 4
String = 5
Number = 6
Expression_Character = 7
Bool_Expression_Character = 8
Format_Character = 9

View File

@ -0,0 +1,24 @@
from enum import Enum
class Types(Enum):
Any = 0
Number = 1
String = 2
Bool = 3
List = 4
Dict = 5
Empty = 6
Void = 7
strings = [
'any',
'number',
'string',
'bool',
'list',
'dict',
'empty',
'void'
]

View File

@ -0,0 +1,11 @@
from enum import Enum
class UnresolvedTokenTypes(Enum):
Empty = 0
Word = 1
Number = 2
String = 3
Expression_Character = 4
Bool_Expression_Character = 5
Format_Character = 6

View File

@ -1,6 +0,0 @@
class Class:
def __init__(self, name: str, access: str = '') -> None:
self.name = name
self.ast = [] # filled by parser
self.access = access

View File

@ -1,7 +0,0 @@
class Func:
def __init__(self, name: str, return_type: str, access: str = '') -> None:
self.name = name
self.return_type = return_type
self.ast = [] # filled by parser
self.access = access

View File

@ -1,5 +0,0 @@
class Lib:
def __init__(self, name: str) -> None:
self.name = name
self.ast = [] # filled by parser

View File

@ -1,6 +0,0 @@
class Var:
def __init__(self, name: str, type: str, access: str = ''):
self.name = name
self.type = type
self.access = access