[DevState] Improved Parsing for AST Lib, Class, Func, Var, Call
This commit is contained in:
parent
7058927970
commit
fa2a42dcc8
@ -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
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 {
|
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 {
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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')
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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'
|
|
||||||
]
|
|
||||||
|
@ -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 = [
|
|
||||||
'{',
|
|
||||||
'}',
|
|
||||||
'(',
|
|
||||||
')',
|
|
||||||
'[',
|
|
||||||
']',
|
|
||||||
';',
|
|
||||||
':',
|
|
||||||
',',
|
|
||||||
'.'
|
|
||||||
]
|
|
||||||
|
Loading…
Reference in New Issue
Block a user