[DevState] Improved Parsing for AST Lib, Class, Func, Var, Call
This commit is contained in:
parent
7058927970
commit
fa2a42dcc8
@ -1,40 +1,6 @@
|
||||
LibraryDefinition:
|
||||
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>
|
||||
|
||||
operation: number <+, -, *, /> 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
64
doc/ast_test.json
Normal 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
2
doc/todo.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Todo:
|
||||
- parse function
|
@ -8,7 +8,7 @@ public lib Main {
|
||||
class Program {
|
||||
var test: bool = false;
|
||||
var test2: Program2 = empty;
|
||||
var test3: Program2 = Test();
|
||||
var test3: Program2 = Test(34);
|
||||
|
||||
func Main(): empty {
|
||||
#func Main {
|
||||
|
@ -1,9 +1,12 @@
|
||||
from typing import Optional
|
||||
|
||||
from Interpreter.Validator import Validator
|
||||
from Interpreter.Lexer import Lexer
|
||||
# from Interpreter.Parser_Old import Parser
|
||||
from Interpreter.Parser import Parser
|
||||
from Interpreter.Repo import Repo
|
||||
from Interpreter.Utils import Utils
|
||||
from Models.AbstractSyntaxTree.AbstractSyntaxTree import AbstractSyntaxTree
|
||||
|
||||
|
||||
class Interpreter:
|
||||
@ -22,12 +25,34 @@ class Interpreter:
|
||||
:return:
|
||||
"""
|
||||
tokens = []
|
||||
ast: Optional[AbstractSyntaxTree] = None
|
||||
|
||||
if self.__repo.is_error is None:
|
||||
tokens = self.__lexer.tokenize(line_str)
|
||||
|
||||
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:
|
||||
# self.__validator.validate(self.__repo.AST)
|
||||
# self.__validator.validate(self.__repo.AST)
|
||||
|
@ -89,6 +89,10 @@ class Lexer:
|
||||
# end of number
|
||||
elif not c.isdigit() and c != '.' and is_number:
|
||||
self.__add_tok(tokens, word, UnresolvedTokenTypes.Number)
|
||||
local_tokens = self.tokenize(c)
|
||||
for local_token in local_tokens:
|
||||
tokens.append(local_token)
|
||||
|
||||
word = ''
|
||||
is_number = False
|
||||
|
||||
|
@ -1,8 +1,14 @@
|
||||
from typing import List, Optional
|
||||
from typing import List, Optional, Union
|
||||
|
||||
from Interpreter.Repo import Repo
|
||||
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.TokenTypes import TokenTypes
|
||||
from Models.Token.TokenValueTypes import Keywords, FormatCharacters, ExpressionCharacters
|
||||
|
||||
|
||||
class Parser:
|
||||
@ -11,16 +17,399 @@ class Parser:
|
||||
self.__repo = repo
|
||||
self.__utils = utils
|
||||
|
||||
self.__next_is_public = False
|
||||
|
||||
self.__ast: AbstractSyntaxTree = AbstractSyntaxTree()
|
||||
self.__saved_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:
|
||||
toks = []
|
||||
for tok in tokens:
|
||||
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')
|
||||
|
@ -11,62 +11,63 @@ class Repo:
|
||||
# interpreter
|
||||
self.keywords = [
|
||||
# define keywords
|
||||
Keywords.Library,
|
||||
Keywords.Class,
|
||||
Keywords.Function,
|
||||
Keywords.Variable,
|
||||
Keywords.Use,
|
||||
Keywords.From,
|
||||
Keywords.Library.value,
|
||||
Keywords.Class.value,
|
||||
Keywords.Function.value,
|
||||
Keywords.Variable.value,
|
||||
Keywords.Use.value,
|
||||
Keywords.From.value,
|
||||
# builtin functions
|
||||
Keywords.Output,
|
||||
Keywords.Input,
|
||||
Keywords.Length,
|
||||
Keywords.Range,
|
||||
Keywords.Exit,
|
||||
Keywords.Output.value,
|
||||
Keywords.Input.value,
|
||||
Keywords.Length.value,
|
||||
Keywords.Range.value,
|
||||
Keywords.Exit.value,
|
||||
# normal keywords
|
||||
Keywords.If,
|
||||
Keywords.ElseIf,
|
||||
Keywords.Else,
|
||||
Keywords.Continue,
|
||||
Keywords.If,
|
||||
Keywords.Return,
|
||||
Keywords.If.value,
|
||||
Keywords.ElseIf.value,
|
||||
Keywords.Else.value,
|
||||
Keywords.Continue.value,
|
||||
Keywords.If.value,
|
||||
Keywords.Return.value,
|
||||
# loops
|
||||
Keywords.While,
|
||||
Keywords.For,
|
||||
Keywords.While.value,
|
||||
Keywords.For.value,
|
||||
# access
|
||||
Keywords.Public
|
||||
Keywords.Public.value,
|
||||
Keywords.This.value
|
||||
]
|
||||
self.datatypes = [
|
||||
Datatypes.strings.value[Datatypes.Empty.value],
|
||||
Datatypes.strings.value[Datatypes.Any.value],
|
||||
Datatypes.strings.value[Datatypes.Number.value],
|
||||
Datatypes.strings.value[Datatypes.String.value],
|
||||
Datatypes.strings.value[Datatypes.Bool.value],
|
||||
Datatypes.strings.value[Datatypes.List.value],
|
||||
Datatypes.strings.value[Datatypes.Dict.value]
|
||||
Datatypes.Empty.value,
|
||||
Datatypes.Any.value,
|
||||
Datatypes.Number.value,
|
||||
Datatypes.String.value,
|
||||
Datatypes.Bool.value,
|
||||
Datatypes.List.value,
|
||||
Datatypes.Dict.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]
|
||||
FormatCharacters.Left_Brace.value,
|
||||
FormatCharacters.Right_Brace.value,
|
||||
FormatCharacters.Left_Parenthesis.value,
|
||||
FormatCharacters.Right_Parenthesis.value,
|
||||
FormatCharacters.Left_Bracket.value,
|
||||
FormatCharacters.Right_Bracket.value,
|
||||
FormatCharacters.Semicolon.value,
|
||||
FormatCharacters.Colon.value,
|
||||
FormatCharacters.Comma.value,
|
||||
FormatCharacters.Point.value
|
||||
]
|
||||
self.expr_chars = [
|
||||
ExpressionCharacters.chars.value[ExpressionCharacters.Plus.value],
|
||||
ExpressionCharacters.chars.value[ExpressionCharacters.Minus.value],
|
||||
ExpressionCharacters.chars.value[ExpressionCharacters.Asterisk.value],
|
||||
ExpressionCharacters.chars.value[ExpressionCharacters.Slash.value],
|
||||
ExpressionCharacters.chars.value[ExpressionCharacters.Equal.value],
|
||||
ExpressionCharacters.chars.value[ExpressionCharacters.Caret.value]
|
||||
ExpressionCharacters.Plus.value,
|
||||
ExpressionCharacters.Minus.value,
|
||||
ExpressionCharacters.Asterisk.value,
|
||||
ExpressionCharacters.Slash.value,
|
||||
ExpressionCharacters.Equal.value,
|
||||
ExpressionCharacters.Caret.value
|
||||
]
|
||||
self.bool_expr_chars = ['<', '>', '!', '!=', '==', '>=', '<=', '&&', '||']
|
||||
self.bool_values = [Booleans.Right, Booleans.Wrong]
|
||||
self.bool_values = [Booleans.Right.value, Booleans.Wrong.value]
|
||||
|
||||
# runtime
|
||||
self.is_error = None
|
||||
|
@ -1,30 +1,92 @@
|
||||
from typing import List, Union
|
||||
|
||||
from Models.Interpreter.Datatypes import Datatypes
|
||||
from Models.Token.Token import Token
|
||||
from Models.Token.TokenTypes import TokenTypes
|
||||
from Models.Token.TokenValueTypes import ExpressionCharacters
|
||||
|
||||
|
||||
class ValueNode:
|
||||
def __init__(self, value: Token = 'empty', datatype: Token = Token(TokenTypes.Type, Datatypes.strings.value[Datatypes.Empty.value])):
|
||||
class AbstractSyntaxTree:
|
||||
|
||||
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.type = datatype
|
||||
|
||||
|
||||
class BinaryOperationNode:
|
||||
def __init__(self, left: Token, op_token: Token, right: Token):
|
||||
class BinaryOperationNode(ASTElement):
|
||||
def __init__(self, left: str, op_token: str, right: str):
|
||||
super().__init__()
|
||||
self.left = left
|
||||
self.op_token = op_token
|
||||
self.right = right
|
||||
|
||||
self.operation_chars = [
|
||||
ExpressionCharacters.chars.value[ExpressionCharacters.Plus.value],
|
||||
ExpressionCharacters.chars.value[ExpressionCharacters.Minus.value],
|
||||
ExpressionCharacters.chars.value[ExpressionCharacters.Asterisk.value],
|
||||
ExpressionCharacters.chars.value[ExpressionCharacters.Slash.value],
|
||||
ExpressionCharacters.chars.value[ExpressionCharacters.Caret.value]
|
||||
ExpressionCharacters.Plus.value,
|
||||
ExpressionCharacters.Minus.value,
|
||||
ExpressionCharacters.Asterisk.value,
|
||||
ExpressionCharacters.Slash.value,
|
||||
ExpressionCharacters.Caret.value
|
||||
]
|
||||
|
||||
def eval(self):
|
||||
if self.op_token.value not in self.operation_chars:
|
||||
return eval(f'{self.left.value} {self.op_token.value} {self.right.value}')
|
||||
if self.op_token in self.operation_chars:
|
||||
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
|
||||
|
@ -3,20 +3,10 @@ from enum import Enum
|
||||
|
||||
class Datatypes(Enum):
|
||||
|
||||
Empty = 0
|
||||
Any = 1
|
||||
Number = 2
|
||||
String = 3
|
||||
Bool = 4
|
||||
List = 5
|
||||
Dict = 6
|
||||
|
||||
strings = [
|
||||
'empty',
|
||||
'any',
|
||||
'number',
|
||||
'string',
|
||||
'bool',
|
||||
'list',
|
||||
'dict'
|
||||
]
|
||||
Empty = 'empty'
|
||||
Any = 'any'
|
||||
Number = 'number'
|
||||
String = 'string'
|
||||
Bool = 'bool'
|
||||
List = 'list'
|
||||
Dict = 'dict'
|
||||
|
@ -1,82 +1,62 @@
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class Keywords:
|
||||
class Keywords(Enum):
|
||||
# define keywords
|
||||
Library: str = 'lib'
|
||||
Class: str = 'class'
|
||||
Function: str = 'func'
|
||||
Variable: str = 'var'
|
||||
Use: str = 'use'
|
||||
From: str = 'from'
|
||||
Library = 'lib'
|
||||
Class = 'class'
|
||||
Function = 'func'
|
||||
Variable = 'var'
|
||||
Use = 'use'
|
||||
From = 'from'
|
||||
|
||||
# builtin functions
|
||||
Output: str = 'output'
|
||||
Input: str = 'input'
|
||||
Length: str = 'length'
|
||||
Range: str = 'range'
|
||||
Exit: str = 'exit'
|
||||
Output = 'output'
|
||||
Input = 'input'
|
||||
Length = 'length'
|
||||
Range = 'range'
|
||||
Exit = 'exit'
|
||||
|
||||
# normal keywords
|
||||
If: str = 'if'
|
||||
ElseIf: str = 'elseif'
|
||||
Else: str = 'else'
|
||||
Continue: str = 'continue'
|
||||
In: str = 'in'
|
||||
Return: str = 'return'
|
||||
If = 'if'
|
||||
ElseIf = 'elseif'
|
||||
Else = 'else'
|
||||
Continue = 'continue'
|
||||
In = 'in'
|
||||
Return = 'return'
|
||||
|
||||
# loops
|
||||
While: str = 'while'
|
||||
For: str = 'for'
|
||||
While = 'while'
|
||||
For = 'for'
|
||||
|
||||
# access
|
||||
Public: str = 'public'
|
||||
Public = 'public'
|
||||
This = 'this'
|
||||
|
||||
|
||||
class Booleans:
|
||||
class Booleans(Enum):
|
||||
Right = 'true'
|
||||
Wrong = 'false'
|
||||
|
||||
|
||||
class ExpressionCharacters(Enum):
|
||||
Plus = 0
|
||||
Minus = 1
|
||||
Asterisk = 2
|
||||
Slash = 3
|
||||
Equal = 4
|
||||
Caret = 5
|
||||
|
||||
chars = [
|
||||
'+',
|
||||
'-',
|
||||
'*',
|
||||
'/',
|
||||
'=',
|
||||
'^'
|
||||
]
|
||||
Plus = '+'
|
||||
Minus = '-'
|
||||
Asterisk = '*'
|
||||
Slash = '/'
|
||||
Equal = '='
|
||||
Caret = '^'
|
||||
|
||||
|
||||
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
|
||||
Left_Brace = '{'
|
||||
Right_Brace = '}'
|
||||
Left_Parenthesis = '('
|
||||
Right_Parenthesis = ')'
|
||||
Left_Bracket = '['
|
||||
Right_Bracket = ']'
|
||||
Semicolon = ';'
|
||||
Colon = ':'
|
||||
Comma = ','
|
||||
Point = '.'
|
||||
|
||||
chars = [
|
||||
'{',
|
||||
'}',
|
||||
'(',
|
||||
')',
|
||||
'[',
|
||||
']',
|
||||
';',
|
||||
':',
|
||||
',',
|
||||
'.'
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user