[DevState] Improved Parsing for AST Lib, Class, Func, Var, Call

This commit is contained in:
Sven Heidemann 2020-09-23 19:38:14 +02:00
parent 7058927970
commit fa2a42dcc8
11 changed files with 664 additions and 181 deletions

View File

@ -1,40 +1,6 @@
LibraryDefinition: operation: number <+, -, *, /> number
IsPublic: <True, False>
Name: <NAME>
ClassDefinition:
IsPublic: <True, False>
Name: <NAME>
Instructions: <LIST OF SUB AST>
FunctionDefinition:
IsPublic: <True, False>
Name: <NAME>
Arguments: <LIST OF VariableDefinition>
ReturnType: <Bool, String, Num, Empty, Any>
Instructions: <LIST OF SUB AST>
VariableDefinition:
IsPublic: <True, False>
Name: <NAME>
Type: <Bool, String, Num, Empty, Any>
Value: <LIST OF SUB AST>
IsAbleToBeEmpty: <True, False>
FunctionCall:
Function: <NAME, ID>
Arguments: <LIST OF SUB AST>
Assignment:
Target: <NAME, ID>
Value: <LIST OF SUB AST>
Operation:
Type: <+, -, *, />
Arguments: <LIST OF SUB AST>
Value:
Value: <1-9, '', true/false>
Type: <Bool, String, Number>
lib def: <public> lib Name {
class def: <public> class Name {
func def: <public> func Name(arg: type<, more args>) {
var def: <public> var Name: type<= value>;

64
doc/ast_test.json Normal file
View File

@ -0,0 +1,64 @@
{
"libraries": [
{
"is_public": "True",
"name": "Main",
"classes": [
{
"is_public": "False",
"name": "Program",
"variables": [
{
"is_public": "False",
"name": "test",
"type": "bool",
"value": "false"
},
{
"is_public": "False",
"name": "test2",
"type": "Program2",
"value": "empty"
},
{
"is_public": "False",
"name": "test3",
"type": "Program2",
"value": {}
}
],
"functions": [
{
"is_public": "False",
"name": "Main",
"args": [],
"return_type": "empty",
"instructions": [
{
"is_public": "False",
"name": "hallo",
"type": "any",
"value": "empty"
}
]
},
{
"is_public": "False",
"name": "isTrue",
"args": [
{
"is_public": "False",
"name": "value",
"type": "bool",
"value": "empty"
}
],
"return_type": "bool",
"instructions": []
}
]
}
]
}
]
}

2
doc/todo.txt Normal file
View File

@ -0,0 +1,2 @@
Todo:
- parse function

View File

@ -8,7 +8,7 @@ public lib Main {
class Program { class Program {
var test: bool = false; var test: bool = false;
var test2: Program2 = empty; var test2: Program2 = empty;
var test3: Program2 = Test(); var test3: Program2 = Test(34);
func Main(): empty { func Main(): empty {
#func Main { #func Main {

View File

@ -1,9 +1,12 @@
from typing import Optional
from Interpreter.Validator import Validator from Interpreter.Validator import Validator
from Interpreter.Lexer import Lexer from Interpreter.Lexer import Lexer
# from Interpreter.Parser_Old import Parser # from Interpreter.Parser_Old import Parser
from Interpreter.Parser import Parser from Interpreter.Parser import Parser
from Interpreter.Repo import Repo from Interpreter.Repo import Repo
from Interpreter.Utils import Utils from Interpreter.Utils import Utils
from Models.AbstractSyntaxTree.AbstractSyntaxTree import AbstractSyntaxTree
class Interpreter: class Interpreter:
@ -22,12 +25,34 @@ class Interpreter:
:return: :return:
""" """
tokens = [] tokens = []
ast: Optional[AbstractSyntaxTree] = None
if self.__repo.is_error is None: if self.__repo.is_error is None:
tokens = self.__lexer.tokenize(line_str) tokens = self.__lexer.tokenize(line_str)
if self.__repo.is_error is None: if self.__repo.is_error is None:
self.__parser.parse(tokens) ast = self.__parser.parse(tokens)
""" print('#####\n')
if ast is not None:
for lib in ast.libraries:
print('lib', lib.name)
for cl in lib.classes:
print('class', cl.name)
for var in cl.variables:
print('cl var', var.name)
for func in cl.functions:
print('func', func.name)
for arg in func.args:
print('func arg', arg.name)
for var in func.variables:
print('func var', var.name)
for ins in func.instructions:
print('ins', ins)
"""
# if self.__repo.is_error is None: # if self.__repo.is_error is None:
# self.__validator.validate(self.__repo.AST) # self.__validator.validate(self.__repo.AST)

View File

@ -89,6 +89,10 @@ class Lexer:
# 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(tokens, word, UnresolvedTokenTypes.Number) self.__add_tok(tokens, word, UnresolvedTokenTypes.Number)
local_tokens = self.tokenize(c)
for local_token in local_tokens:
tokens.append(local_token)
word = '' word = ''
is_number = False is_number = False

View File

@ -1,8 +1,14 @@
from typing import List, Optional from typing import List, Optional, Union
from Interpreter.Repo import Repo from Interpreter.Repo import Repo
from Interpreter.Utils import Utils from Interpreter.Utils import Utils
from Models.AbstractSyntaxTree.AbstractSyntaxTree import LibraryDefinitionNode, ClassDefinitionNode, AbstractSyntaxTree, \
FunctionDefinitionNode, VariableDefinitionNode, CallDefinitionNode, ValueNode, ASTElement
from Models.Interpreter.Datatypes import Datatypes
from Models.Interpreter.Error import Error, ErrorCodes
from Models.Token.Token import Token from Models.Token.Token import Token
from Models.Token.TokenTypes import TokenTypes
from Models.Token.TokenValueTypes import Keywords, FormatCharacters, ExpressionCharacters
class Parser: class Parser:
@ -11,16 +17,399 @@ class Parser:
self.__repo = repo self.__repo = repo
self.__utils = utils self.__utils = utils
self.__next_is_public = False self.__ast: AbstractSyntaxTree = AbstractSyntaxTree()
self.__saved_tokens: List[Token] = []
self.__expected_tokens: List[Token] = [] self.__expected_tokens: List[Token] = []
self.__ast: Optional[None] = None # for validation if type is created
self.__is_saving_type = False
self.__is_saving_value = False
self.__is_saving_call = False
self.__is_end = False
self.__saved_ast_elements: List[ASTElement] = []
def parse(self, tokens: List[Token]) -> AbstractSyntaxTree:
self.__is_end = False
def parse(self, tokens: List[Token]) -> None:
if len(tokens) > 0: if len(tokens) > 0:
toks = [] toks = []
for tok in tokens: for tok in tokens:
toks.append({tok.type.name, tok.value}) toks.append({tok.type.name, tok.value})
print(toks) print(self.__repo.line_number, toks)
for i in range(0, len(tokens)):
token = tokens[i]
self.__check_for_expected_tokens(token)
# keywords
if token.type == TokenTypes.Keyword:
if token.value == Keywords.Public.value:
self.__saved_tokens.append(token)
print('save public')
self.__add_expected_token(TokenTypes.Keyword, Keywords.Library.value)
self.__add_expected_token(TokenTypes.Keyword, Keywords.Class.value)
self.__add_expected_token(TokenTypes.Keyword, Keywords.Function.value)
self.__add_expected_token(TokenTypes.Keyword, Keywords.Variable.value)
elif token.value == Keywords.Library.value:
self.__saved_tokens.append(token)
print('save lib')
self.__add_expected_token(TokenTypes.Name)
elif token.value == Keywords.Class.value:
self.__saved_tokens.append(token)
print('save class')
self.__add_expected_token(TokenTypes.Name)
elif token.value == Keywords.Function.value:
self.__saved_tokens.append(token)
print('save function')
self.__add_expected_token(TokenTypes.Name)
elif token.value == Keywords.Variable.value:
self.__saved_tokens.append(token)
print('save var')
self.__add_expected_token(TokenTypes.Name)
# names
elif token.type == TokenTypes.Name:
if self.__is_saving_variable() and self.__is_saving_value:
self.__save_name(token)
if self.__is_saving_variable():
self.__is_saving_call = True
# names could be variable types, validation check in evaluator
elif self.__is_saving_variable() and self.__is_saving_type:
self.__save_type(token)
self.__add_expected_token(TokenTypes.Format_Character, FormatCharacters.Left_Parenthesis.value)
elif self.__is_saving_variable():
self.__save_name(token)
self.__add_expected_token(TokenTypes.Format_Character, FormatCharacters.Colon.value)
elif self.__is_saving_function():
self.__save_name(token)
self.__add_expected_token(TokenTypes.Format_Character, FormatCharacters.Left_Parenthesis.value)
elif self.__is_saving_library() or self.__is_saving_class():
self.__save_name(token)
self.__add_expected_token(TokenTypes.Format_Character, FormatCharacters.Left_Brace.value)
# format chars
elif token.type == TokenTypes.Format_Character:
if token.value == FormatCharacters.Left_Brace.value:
if self.__is_saving_library():
self.__save_library()
elif self.__is_saving_class():
self.__save_class()
elif token.value == FormatCharacters.Colon.value:
if self.__is_saving_variable():
self.__is_saving_type = True
self.__add_expected_token(TokenTypes.Type)
self.__add_expected_token(TokenTypes.Name)
elif token.value == FormatCharacters.Semicolon.value:
self.__end_line()
elif token.value == FormatCharacters.Left_Parenthesis.value:
self.__add_expected_token(TokenTypes.Name)
self.__add_expected_token(TokenTypes.Format_Character, FormatCharacters.Right_Parenthesis.value)
self.__add_expected_token(TokenTypes.Keyword, Keywords.This.value)
self.__add_expected_token(TokenTypes.Name)
self.__add_expected_token(TokenTypes.Empty)
self.__add_expected_token(TokenTypes.Number)
self.__add_expected_token(TokenTypes.String)
self.__add_expected_token(TokenTypes.Bool)
if self.__is_saving_call:
self.__saved_tokens.append(token)
elif token.value == FormatCharacters.Right_Parenthesis.value:
self.__add_expected_token(TokenTypes.Format_Character, FormatCharacters.Semicolon.value)
self.__add_expected_token(TokenTypes.Format_Character, FormatCharacters.Colon.value)
if self.__is_saving_call:
self.__saved_tokens.append(token)
self.__save_call()
self.__is_saving_call = False
# expr chars
elif token.type == TokenTypes.Expression_Character:
if token.value == ExpressionCharacters.Equal.value:
self.__is_saving_value = True
self.__add_expected_token(TokenTypes.Bool)
self.__add_expected_token(TokenTypes.Number)
self.__add_expected_token(TokenTypes.String)
self.__add_expected_token(TokenTypes.Empty)
self.__add_expected_token(TokenTypes.Name)
self.__add_expected_token(TokenTypes.Keyword, Keywords.This.value)
self.__add_expected_token(TokenTypes.Keyword, Keywords.Input.value)
self.__add_expected_token(TokenTypes.Keyword, Keywords.Range.value)
self.__add_expected_token(TokenTypes.Keyword, Keywords.Length.value)
self.__add_expected_token(TokenTypes.Format_Character, FormatCharacters.Left_Parenthesis.value)
self.__add_expected_token(TokenTypes.Type, Datatypes.Empty.value)
# types
elif token.type == TokenTypes.Type:
if self.__is_saving_variable() and self.__is_saving_value:
self.__save_value(token)
elif self.__is_saving_variable():
self.__save_type(token)
# values
elif token.type == TokenTypes.Bool or token.type == TokenTypes.Number or token.type == TokenTypes.String:
if self.__is_saving_call:
self.__saved_tokens.append(token)
elif self.__is_saving_value:
self.__save_value(token)
return self.__ast
"""
Utils
"""
def __save_name(self, token: Token):
self.__saved_tokens.append(token)
print('save name')
def __add_expected_token(self, token_type: TokenTypes, value: str = ''):
self.__expected_tokens.append(Token(token_type, value))
def __check_for_expected_tokens(self, token: Token):
error_token: Optional[Token] = None
is_error = True
for expected_token in self.__expected_tokens:
if self.__is_end or token.type != expected_token.type or expected_token.value != '' and token.value != expected_token.value:
error_token = token
else:
is_error = False
if error_token is not None and is_error:
self.__utils.error(Error(ErrorCodes.Unexpected, f'{error_token.type.name} {error_token.value}'))
self.__expected_tokens = []
def __end_line(self):
if self.__is_saving_variable():
self.__save_variable()
self.__is_end = True
self.__expected_tokens = []
self.__is_saving_type = False
self.__is_saving_value = False
"""
Library
"""
def __is_saving_library(self) -> bool:
found = False
for token in self.__saved_tokens:
if token.type == TokenTypes.Keyword and token.value == Keywords.Library.value:
found = True
return found
def __save_library(self) -> None:
is_public = False
name_token: Optional[Token] = None
for token in self.__saved_tokens:
if token.type == TokenTypes.Name:
name_token = token
elif token.type == TokenTypes.Keyword and token.value == Keywords.Public.value:
is_public = True
if name_token is not None:
self.__ast.libraries.append(LibraryDefinitionNode(is_public, name_token.value))
self.__saved_tokens = []
self.__add_expected_token(TokenTypes.Keyword, Keywords.Public.value)
self.__add_expected_token(TokenTypes.Keyword, Keywords.Class.value)
print('saved library')
"""
Class
"""
def __is_saving_class(self) -> bool:
found = False
for token in self.__saved_tokens:
if token.type == TokenTypes.Keyword and token.value == Keywords.Class.value:
found = True
return found
def __save_class(self) -> None:
is_public = False
name_token: Optional[Token] = None
for token in self.__saved_tokens:
if token.type == TokenTypes.Name:
name_token = token
elif token.type == TokenTypes.Keyword and token.value == Keywords.Public.value:
is_public = True
if name_token is not None:
self.__ast.libraries[len(self.__ast.libraries) - 1].classes.append(ClassDefinitionNode(is_public, name_token.value))
self.__saved_tokens = []
self.__add_expected_token(TokenTypes.Keyword, Keywords.Public.value)
self.__add_expected_token(TokenTypes.Keyword, Keywords.Variable.value)
self.__add_expected_token(TokenTypes.Keyword, Keywords.Function.value)
print('saved class')
"""
Call
"""
def __save_call(self) -> None:
name_token: Optional[Token] = None
args: List[ValueNode] = []
remove_tokens = []
is_call = False
for i in range(0, len(self.__saved_tokens)):
token = self.__saved_tokens[i]
last_token: Optional[Token] = None
if i-1 > 0:
last_token = self.__saved_tokens[i-1]
if token.type == TokenTypes.Name and last_token is not None and last_token.type == TokenTypes.Format_Character and last_token.value == FormatCharacters.Left_Parenthesis.value:
pass
if token.type == TokenTypes.Format_Character and token.value == FormatCharacters.Left_Parenthesis.value and last_token is not None and last_token.type == TokenTypes.Name:
name_token = last_token
remove_tokens.append(last_token)
remove_tokens.append(token)
is_call = True
elif is_call and token.type == TokenTypes.Format_Character and token.value == FormatCharacters.Right_Parenthesis.value:
remove_tokens.append(token)
elif is_call and token.type == TokenTypes.Bool or token.type == TokenTypes.Number or token.type == TokenTypes.String:
args.append(ValueNode(token.value, Datatypes[token.type.name]))
remove_tokens.append(token)
if name_token is not None:
call = CallDefinitionNode(name_token.value)
call.args = args
self.__saved_ast_elements.append(call)
for token in remove_tokens:
self.__saved_tokens.remove(token)
self.__add_expected_token(TokenTypes.Format_Character, FormatCharacters.Semicolon.value)
print('saved call')
"""
Function
"""
def __is_saving_function(self) -> bool:
found = False
for token in self.__saved_tokens:
if token.type == TokenTypes.Keyword and token.value == Keywords.Function.value:
found = True
return found
def __save_function(self) -> None:
is_public = False
name_token: Optional[Token] = None
return_type: Optional[Token] = None
for token in self.__saved_tokens:
if token.type == TokenTypes.Name:
name_token = token
elif token.type == TokenTypes.Keyword and token.value == Keywords.Public.value:
is_public = True
elif token.type == TokenTypes.Type:
return_type = token
if name_token is not None and return_type is not None:
self.__ast.libraries[len(self.__ast.libraries) - 1].classes[len(self.__ast.libraries) - 1].functions.append(
FunctionDefinitionNode(is_public, name_token.value, Datatypes[return_type.value]))
self.__saved_tokens = []
print('saved function')
"""
Variable
"""
def __is_saving_variable(self) -> bool:
found = False
for token in self.__saved_tokens:
if token.type == TokenTypes.Keyword and token.value == Keywords.Variable.value:
found = True
return found
def __save_type(self, token: Token) -> None:
self.__saved_tokens.append(token)
self.__add_expected_token(TokenTypes.Format_Character, FormatCharacters.Semicolon.value)
self.__add_expected_token(TokenTypes.Expression_Character, ExpressionCharacters.Equal.value)
self.__is_saving_type = False
print('save type')
def __save_variable(self):
is_public = False
name_token: Optional[Token] = None
datatype: Optional[Token] = None
value: Optional[Union[str, Token, CallDefinitionNode]] = None
reset_saved_ast = False
for token in self.__saved_tokens:
if token.type == TokenTypes.Name and name_token is None:
name_token = token
elif token.type == TokenTypes.Keyword and token.value == Keywords.Public.value:
is_public = True
elif token.type == TokenTypes.Type or name_token is not None and token.type == TokenTypes.Name:
datatype = token
value = Token(TokenTypes.Empty, TokenTypes.Empty.value)
for saved_ast_element in self.__saved_ast_elements:
if isinstance(saved_ast_element, CallDefinitionNode):
value = saved_ast_element
reset_saved_ast = True
if reset_saved_ast:
self.__saved_ast_elements = []
if name_token is not None and datatype is not None and value is not None:
if not isinstance(value, CallDefinitionNode):
value = value.value
if datatype.type == TokenTypes.Name:
variable = VariableDefinitionNode(is_public, name_token.value, datatype.value, value)
else:
variable = VariableDefinitionNode(is_public, name_token.value, Datatypes[str(datatype.value).capitalize()], value)
if len(self.__ast.libraries) > 0:
lib = self.__ast.libraries[len(self.__ast.libraries) - 1]
if len(lib.classes) > 0:
cl = lib.classes[len(lib.classes) - 1]
if len(cl.functions) == 0:
cl.variables.append(variable)
else:
cl.functions[len(cl.functions) - 1].variables.append(variable)
self.__saved_tokens = []
print('saved variable')
"""
Value
"""
def __save_value(self, token: Token):
self.__saved_tokens.append(token)
self.__add_expected_token(TokenTypes.Format_Character, FormatCharacters.Left_Parenthesis.value)
self.__add_expected_token(TokenTypes.Format_Character, FormatCharacters.Semicolon.value)
self.__is_saving_value = False
print('save value')

View File

@ -11,62 +11,63 @@ class Repo:
# interpreter # interpreter
self.keywords = [ self.keywords = [
# define keywords # define keywords
Keywords.Library, Keywords.Library.value,
Keywords.Class, Keywords.Class.value,
Keywords.Function, Keywords.Function.value,
Keywords.Variable, Keywords.Variable.value,
Keywords.Use, Keywords.Use.value,
Keywords.From, Keywords.From.value,
# builtin functions # builtin functions
Keywords.Output, Keywords.Output.value,
Keywords.Input, Keywords.Input.value,
Keywords.Length, Keywords.Length.value,
Keywords.Range, Keywords.Range.value,
Keywords.Exit, Keywords.Exit.value,
# normal keywords # normal keywords
Keywords.If, Keywords.If.value,
Keywords.ElseIf, Keywords.ElseIf.value,
Keywords.Else, Keywords.Else.value,
Keywords.Continue, Keywords.Continue.value,
Keywords.If, Keywords.If.value,
Keywords.Return, Keywords.Return.value,
# loops # loops
Keywords.While, Keywords.While.value,
Keywords.For, Keywords.For.value,
# access # access
Keywords.Public Keywords.Public.value,
Keywords.This.value
] ]
self.datatypes = [ self.datatypes = [
Datatypes.strings.value[Datatypes.Empty.value], Datatypes.Empty.value,
Datatypes.strings.value[Datatypes.Any.value], Datatypes.Any.value,
Datatypes.strings.value[Datatypes.Number.value], Datatypes.Number.value,
Datatypes.strings.value[Datatypes.String.value], Datatypes.String.value,
Datatypes.strings.value[Datatypes.Bool.value], Datatypes.Bool.value,
Datatypes.strings.value[Datatypes.List.value], Datatypes.List.value,
Datatypes.strings.value[Datatypes.Dict.value] Datatypes.Dict.value
] ]
self.format_chars = [ self.format_chars = [
FormatCharacters.chars.value[FormatCharacters.Left_Brace.value], FormatCharacters.Left_Brace.value,
FormatCharacters.chars.value[FormatCharacters.Right_Brace.value], FormatCharacters.Right_Brace.value,
FormatCharacters.chars.value[FormatCharacters.Left_Parenthesis.value], FormatCharacters.Left_Parenthesis.value,
FormatCharacters.chars.value[FormatCharacters.Right_Parenthesis.value], FormatCharacters.Right_Parenthesis.value,
FormatCharacters.chars.value[FormatCharacters.Left_Bracket.value], FormatCharacters.Left_Bracket.value,
FormatCharacters.chars.value[FormatCharacters.Right_Bracket.value], FormatCharacters.Right_Bracket.value,
FormatCharacters.chars.value[FormatCharacters.Semicolon.value], FormatCharacters.Semicolon.value,
FormatCharacters.chars.value[FormatCharacters.Colon.value], FormatCharacters.Colon.value,
FormatCharacters.chars.value[FormatCharacters.Comma.value], FormatCharacters.Comma.value,
FormatCharacters.chars.value[FormatCharacters.Point.value] FormatCharacters.Point.value
] ]
self.expr_chars = [ self.expr_chars = [
ExpressionCharacters.chars.value[ExpressionCharacters.Plus.value], ExpressionCharacters.Plus.value,
ExpressionCharacters.chars.value[ExpressionCharacters.Minus.value], ExpressionCharacters.Minus.value,
ExpressionCharacters.chars.value[ExpressionCharacters.Asterisk.value], ExpressionCharacters.Asterisk.value,
ExpressionCharacters.chars.value[ExpressionCharacters.Slash.value], ExpressionCharacters.Slash.value,
ExpressionCharacters.chars.value[ExpressionCharacters.Equal.value], ExpressionCharacters.Equal.value,
ExpressionCharacters.chars.value[ExpressionCharacters.Caret.value] ExpressionCharacters.Caret.value
] ]
self.bool_expr_chars = ['<', '>', '!', '!=', '==', '>=', '<=', '&&', '||'] self.bool_expr_chars = ['<', '>', '!', '!=', '==', '>=', '<=', '&&', '||']
self.bool_values = [Booleans.Right, Booleans.Wrong] self.bool_values = [Booleans.Right.value, Booleans.Wrong.value]
# runtime # runtime
self.is_error = None self.is_error = None

View File

@ -1,30 +1,92 @@
from typing import List, Union
from Models.Interpreter.Datatypes import Datatypes from Models.Interpreter.Datatypes import Datatypes
from Models.Token.Token import Token
from Models.Token.TokenTypes import TokenTypes
from Models.Token.TokenValueTypes import ExpressionCharacters from Models.Token.TokenValueTypes import ExpressionCharacters
class ValueNode: class AbstractSyntaxTree:
def __init__(self, value: Token = 'empty', datatype: Token = Token(TokenTypes.Type, Datatypes.strings.value[Datatypes.Empty.value])):
def __init__(self):
self.libraries: List[LibraryDefinitionNode] = []
class ASTElement:
def __init__(self):
pass
class ValueNode(ASTElement):
def __init__(self, value: str, datatype: Datatypes):
super().__init__()
self.value = value self.value = value
self.type = datatype self.type = datatype
class BinaryOperationNode: class BinaryOperationNode(ASTElement):
def __init__(self, left: Token, op_token: Token, right: Token): def __init__(self, left: str, op_token: str, right: str):
super().__init__()
self.left = left self.left = left
self.op_token = op_token self.op_token = op_token
self.right = right self.right = right
self.operation_chars = [ self.operation_chars = [
ExpressionCharacters.chars.value[ExpressionCharacters.Plus.value], ExpressionCharacters.Plus.value,
ExpressionCharacters.chars.value[ExpressionCharacters.Minus.value], ExpressionCharacters.Minus.value,
ExpressionCharacters.chars.value[ExpressionCharacters.Asterisk.value], ExpressionCharacters.Asterisk.value,
ExpressionCharacters.chars.value[ExpressionCharacters.Slash.value], ExpressionCharacters.Slash.value,
ExpressionCharacters.chars.value[ExpressionCharacters.Caret.value] ExpressionCharacters.Caret.value
] ]
def eval(self): def eval(self):
if self.op_token.value not in self.operation_chars: if self.op_token in self.operation_chars:
return eval(f'{self.left.value} {self.op_token.value} {self.right.value}') return eval(f'{self.left} {self.op_token} {self.right}')
class LibraryDefinitionNode(ASTElement):
def __init__(self, is_public: bool, name: str):
super().__init__()
self.is_public = is_public
self.name = name
self.classes: List[ClassDefinitionNode] = []
class ClassDefinitionNode(ASTElement):
def __init__(self, is_public: bool, name: str):
super().__init__()
self.is_public = is_public
self.name = name
self.variables: [VariableDefinitionNode] = []
self.functions: List[FunctionDefinitionNode] = []
class CallDefinitionNode(ASTElement):
def __init__(self, name: str):
super().__init__()
self.name = name
self.args: List[ValueNode] = []
class FunctionDefinitionNode(ASTElement):
def __init__(self, is_public: bool, name: str, return_type: Datatypes):
super().__init__()
self.is_public = is_public
self.name = name
self.args: List[VariableDefinitionNode] = []
self.return_type = return_type
self.variables: [VariableDefinitionNode] = []
self.instructions: List[ASTElement] = []
class VariableDefinitionNode(ASTElement):
def __init__(self, is_public: bool, name: str, datatype: Union[str, Datatypes], value: Union[str, CallDefinitionNode]):
super().__init__()
self.is_public = is_public
self.name = name
self.datatype = datatype
self.value = value

View File

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

View File

@ -1,82 +1,62 @@
from enum import Enum from enum import Enum
class Keywords: class Keywords(Enum):
# define keywords # define keywords
Library: str = 'lib' Library = 'lib'
Class: str = 'class' Class = 'class'
Function: str = 'func' Function = 'func'
Variable: str = 'var' Variable = 'var'
Use: str = 'use' Use = 'use'
From: str = 'from' From = 'from'
# builtin functions # builtin functions
Output: str = 'output' Output = 'output'
Input: str = 'input' Input = 'input'
Length: str = 'length' Length = 'length'
Range: str = 'range' Range = 'range'
Exit: str = 'exit' Exit = 'exit'
# normal keywords # normal keywords
If: str = 'if' If = 'if'
ElseIf: str = 'elseif' ElseIf = 'elseif'
Else: str = 'else' Else = 'else'
Continue: str = 'continue' Continue = 'continue'
In: str = 'in' In = 'in'
Return: str = 'return' Return = 'return'
# loops # loops
While: str = 'while' While = 'while'
For: str = 'for' For = 'for'
# access # access
Public: str = 'public' Public = 'public'
This = 'this'
class Booleans: class Booleans(Enum):
Right = 'true' Right = 'true'
Wrong = 'false' Wrong = 'false'
class ExpressionCharacters(Enum): class ExpressionCharacters(Enum):
Plus = 0 Plus = '+'
Minus = 1 Minus = '-'
Asterisk = 2 Asterisk = '*'
Slash = 3 Slash = '/'
Equal = 4 Equal = '='
Caret = 5 Caret = '^'
chars = [
'+',
'-',
'*',
'/',
'=',
'^'
]
class FormatCharacters(Enum): class FormatCharacters(Enum):
Left_Brace = 0 Left_Brace = '{'
Right_Brace = 1 Right_Brace = '}'
Left_Parenthesis = 2 Left_Parenthesis = '('
Right_Parenthesis = 3 Right_Parenthesis = ')'
Left_Bracket = 4 Left_Bracket = '['
Right_Bracket = 5 Right_Bracket = ']'
Semicolon = 6 Semicolon = ';'
Colon = 7 Colon = ':'
Comma = 8 Comma = ','
Point = 9 Point = '.'
chars = [
'{',
'}',
'(',
')',
'[',
']',
';',
':',
',',
'.'
]