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 {
min len 3, max len 4:
<public> class test {
min len 5
<public> func test() {
<public> func test(): void {
<public> var: bool <= test <<Bool, String, Num, Any, Instance>> >;

View File

@ -1,12 +1,12 @@
lib Tests {
public class test2 {
var string_a = string1();
var string_a = strings();
public func continue(): void {
input(string_a.string1 + ': ');
}
}
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.__validator = Validator(repo, utils)
def interpret(self, line_int: int, line_str: str) -> bool:
toks = []
ast = []
def interpret(self, line_str: str) -> None:
"""
Interprets code line
:param line_str:
:return:
"""
tokens = []
self.__utils.line_number = line_int
if self.__repo.error is None:
toks = self.__lexer.tokenize(line_str)
if self.__repo.is_error is None:
tokens = 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:
ast = self.__parser.parse(toks)
# self.__repo.output_ast(ast)
if self.__repo.error is None:
self.__validator.validate(ast)
return self.__repo.error is None
# if self.__repo.is_error is None:
# self.__validator.validate(self.__repo.AST)

View File

@ -1,6 +1,10 @@
from typing import List
from Interpreter.Repo import Repo
from Interpreter.Utils import Utils
from Models.Interpreter.Token import Token
from Models.Interpreter.TokenTypes import TokenTypes
from Models.Interpreter.UnresolvedTokenTypes import UnresolvedTokenTypes
class Lexer:
@ -9,31 +13,58 @@ class Lexer:
self.__repo = repo
self.__utils = utils
self.__ml_comment = False
self.__toks = []
self.__is_ml_comment = False
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 type == 'word':
if input_token_type == UnresolvedTokenTypes.Word:
if value in self.__repo.keywords:
type = 'keyword'
token_type = TokenTypes.Keyword
elif value in self.__repo.types:
type = 'type'
token_type = TokenTypes.Type
elif value in self.__repo.bool_values:
type = 'bool'
token_type = TokenTypes.Bool
elif value == 'empty':
type = 'emptyType'
elif value == UnresolvedTokenTypes.Empty:
token_type = TokenTypes.Empty
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:
self.__toks = []
elif input_token_type == UnresolvedTokenTypes.String:
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 = ''
ol_comment = False
is_string1 = False # 'hello'
@ -44,7 +75,7 @@ class Lexer:
for i in range(0, len(line)):
c = line[i]
# 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
if c == '#' and not is_string1 and not is_string2:
ol_comment = True
@ -53,18 +84,18 @@ class Lexer:
ol_comment = True
elif line[i - 1] == '/' and c == '*':
self.__ml_comment = True
self.__is_ml_comment = True
i += 2
# end of number
elif not c.isdigit() and c != '.' and is_number:
self.__add_tok(word, 'number')
self.__add_tok(tokens, word, UnresolvedTokenTypes.Number)
word = ''
is_number = False
# end of expression 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 = ''
is_expr_char = False
@ -76,7 +107,7 @@ class Lexer:
# end of is_string1
elif c == '\'' and is_string1:
is_string1 = False
self.__add_tok(word, 'string')
self.__add_tok(tokens, word, UnresolvedTokenTypes.String)
word = ''
# begin of is_string2
@ -87,13 +118,13 @@ class Lexer:
# end of is_string2
elif c == '\"' and is_string2:
is_string2 = False
self.__add_tok(word, 'string')
self.__add_tok(tokens, word, UnresolvedTokenTypes.String)
word = ''
# format char
elif c in self.__repo.format_chars:
self.__add_tok(word, 'word')
self.__add_tok(c, 'format_char')
self.__add_tok(tokens, word, UnresolvedTokenTypes.Word)
self.__add_tok(tokens, c, UnresolvedTokenTypes.Format_Character)
word = ''
# begin of number
@ -116,13 +147,13 @@ class Lexer:
# bool expression char
elif c in self.__repo.bool_expr_chars:
self.__add_tok(word, 'word')
self.__add_tok(c, 'bool_expr_char')
self.__add_tok(tokens, word, UnresolvedTokenTypes.Word)
self.__add_tok(tokens, c, UnresolvedTokenTypes.Bool_Expression_Character)
word = ''
# end of word
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 = ''
else:
@ -132,6 +163,6 @@ class Lexer:
ol_comment = False
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.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.Nodes.Class import Class
from Models.Nodes.Func import Func
from Models.Nodes.Lib import Lib
from Models.Interpreter.TokenTypes import TokenTypes
from Models.Interpreter.Types import Types
class Parser:
@ -13,37 +23,295 @@ class Parser:
self.__repo = repo
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) -> []:
self.__tokens = toks
self.__ast = []
# class status
self.__is_creating_class = False
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
if len(toks) > 0:
tokens = []
for t in toks:
tokens.append({t.value: t.type})
if len(tokens) == 0:
return None
# 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
if len(self.__repo.ast) > 1:
print('___')
for a_lib in self.__repo.ast:
print(a_lib.name)
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)
""" error status checks """
# check if var name is valid
if i-1 >= 0 and self.__is_creating_variable and tokens[i-1].value == Keywords.Variable:
if token.type != TokenTypes.Name:
self.__utils.error(Error(ErrorCode.Unexpected, f'{token.type.name}: {token.value}'))
print('___')
# print(self.__repo.ast, '\n')
""" normal status checks """
# 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:
for i in range(0, len(self.__tokens)):
tok = self.__tokens[i]
# print(tok.value, tok.type)
# token type format character
elif token.type == TokenTypes.Format_Character:
self.__check_token_format_character(token)
# 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:
def __init__(self) -> None:
@ -5,56 +12,58 @@ class Repo:
# interpreter
self.keywords = [
# define keys
'lib',
'class',
'func',
'var',
'use',
'from',
# define keywords
Keywords.Library,
Keywords.Class,
Keywords.Function,
Keywords.Variable,
Keywords.Use,
Keywords.From,
# builtin functions
'output',
'input',
'length',
'range',
'exit',
Keywords.Output,
Keywords.Input,
Keywords.Length,
Keywords.Range,
Keywords.Exit,
# normal keywords
'if',
'elseif',
'else',
'pass',
'in',
Keywords.If,
Keywords.ElseIf,
Keywords.Else,
Keywords.Pass,
Keywords.If,
Keywords.Return,
# loops
'while',
'for',
Keywords.While,
Keywords.For,
# access
'public'
Keywords.Public
]
self.types = [
'any',
'number',
'string',
'bool',
'list',
'dict',
'emptyType',
'void'
Types.strings.value[Types.Any.value],
Types.strings.value[Types.Number.value],
Types.strings.value[Types.String.value],
Types.strings.value[Types.Bool.value],
Types.strings.value[Types.List.value],
Types.strings.value[Types.Dict.value],
Types.strings.value[Types.Empty.value],
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.bool_expr_chars = ['<', '>', '!', '!=', '==', '>=', '<=', '&&', '||']
self.bool_values = ['true', 'false']
self.bool_values = [Booleans.Right, Booleans.Wrong]
# runtime
self.error = None
self.ast = []
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')
self.is_error = None
self.AST: RuntimeAbstractSyntaxTree = RuntimeAbstractSyntaxTree()

View File

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

View File

@ -1,7 +1,8 @@
import os
import sys
from pprint import pprint
from Models.Interpreter.Error import Error
from Models.Interpreter.Error import Error, ErrorCode
from ServiceInitializer import ServiceInitializer
@ -14,20 +15,31 @@ class Main:
self.__interpreter = self.__services.interpreter
def console(self) -> None:
print('sh-edraft.de basic language interpreter:')
"""
Getting code from console input
:return:
"""
i = 0
cont = True
while cont:
cont = self.__interpreter.interpret(i+1, input('> '))
while self.__repo.is_error is not None:
self.__utils.line_number = i + 1
self.__interpreter.interpret(self.__utils.line_number, input('> '))
i += 1
def files(self, file: str) -> None:
"""
Getting input from file
:param file:
:return:
"""
if os.path.isfile(file):
f = open(file, 'r', encoding='utf-8').readlines()
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:
self.__utils.error(Error(1.1))
self.__utils.is_error(Error(ErrorCode.FileNotFound))
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:
def __init__(self, code: float, msg: str = ''):
def __init__(self, code: ErrorCode, msg: str = ''):
self.code = code
self.__msgs = {
# 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)
self.msg = code.value.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:
def __init__(self, type: str, value: str) -> None:
self.type = type
def __init__(self, token_type: TokenTypes, value: str) -> None:
self.type: TokenTypes = token_type
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