From 2a65a66a869a94b20e21125c7c59d13aa432e34e Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 28 Oct 2021 22:29:00 +0200 Subject: [PATCH] Added functionallity to handle functions --- cc_code_preview/Preview/classes.ccl | 2 +- cc_code_preview/Preview/functions.ccl | 4 + cc_code_preview/Program/main.ccl | 4 +- src/parser/model/ast_types_enum.py | 1 + src/parser/service/parser_service.py | 125 +++++++++++++++++++++++++- 5 files changed, 132 insertions(+), 4 deletions(-) diff --git a/cc_code_preview/Preview/classes.ccl b/cc_code_preview/Preview/classes.ccl index 621a9e9..26c1321 100644 --- a/cc_code_preview/Preview/classes.ccl +++ b/cc_code_preview/Preview/classes.ccl @@ -6,7 +6,7 @@ public lib Preview.Classes { this._name = name; } - public getName(): string { + public func getName(): string { return this._name; } } diff --git a/cc_code_preview/Preview/functions.ccl b/cc_code_preview/Preview/functions.ccl index 3deeddc..f4bc6f4 100644 --- a/cc_code_preview/Preview/functions.ccl +++ b/cc_code_preview/Preview/functions.ccl @@ -2,4 +2,8 @@ public lib Preview.Functions { public func isTrue(value: bool): bool { return value; } + + public func add(value1: number, value2: number): number { + return value1 + value2; + } } \ No newline at end of file diff --git a/cc_code_preview/Program/main.ccl b/cc_code_preview/Program/main.ccl index 009df31..7c17321 100644 --- a/cc_code_preview/Program/main.ccl +++ b/cc_code_preview/Program/main.ccl @@ -10,13 +10,13 @@ public lib Main { this.test = Test(str); } - public func Main(): void { + public func Main(): empty { output(str, test, test2, test3); output(isTrue(test)); output(this.test.getName()); } - private func testForEach(): void { + private func testForEach(): empty { var loopList = []; loopList.forEach(e => { output(e); diff --git a/src/parser/model/ast_types_enum.py b/src/parser/model/ast_types_enum.py index fc8e081..4fb78b6 100644 --- a/src/parser/model/ast_types_enum.py +++ b/src/parser/model/ast_types_enum.py @@ -13,3 +13,4 @@ class ASTTypesEnum(Enum): VariableDeclaration = 'variable_declaration' VariableValue = 'variable_value' UseDirective = 'use_directive' + Arguments = 'arguments' diff --git a/src/parser/service/parser_service.py b/src/parser/service/parser_service.py index 29f668a..01b4b35 100644 --- a/src/parser/service/parser_service.py +++ b/src/parser/service/parser_service.py @@ -45,7 +45,7 @@ class ParserService(ParserABC): name = '' last_token: Optional[Token] = None for i in range(0, tokens.count()): - token = tokens[i] + token: Token = tokens[i] if i == tokens.count() and token.type == TokenTypes.Format_Character and token.value == FormatCharacters.Point: self._runtime.error(Error(ErrorCodesEnum.Unexpected), FormatCharacters.Point.value) @@ -59,6 +59,66 @@ class ParserService(ParserABC): return (AST(ASTTypesEnum.Name, name, self._runtime.line_count, self._runtime.line_count), last_token) + def _parse_args(self, tokens: List[Token]) -> Tuple[AST, Token]: + """ Parses args + + Args: + tokens (List[Token]): Tokens from lexer + + AST: + () + + (i: number) + <:> + (i: number, name: string) + <:> <,> <:> + + Returns: + Tuple[AST, Token]: Name as AST and last Token of Name + """ + if tokens.where(lambda t: t.type == TokenTypes.Format_Character and t.value == FormatCharacters.Left_Parenthesis.value).count() < 1: + self._runtime.error(Error(ErrorCodesEnum.Expected, FormatCharacters.Left_Parenthesis.value)) + else: + i = 1 + + if tokens.where(lambda t: t.type == TokenTypes.Format_Character and t.value == FormatCharacters.Right_Parenthesis.value).count() < 1: + self._runtime.error(Error(ErrorCodesEnum.Expected, FormatCharacters.Right_Parenthesis.value)) + + ast = List(AST) + last_token: Optional[Token] = None + expected_var = False + # for i in range(0, tokens.count()): + while i < tokens.count(): + token: Token = tokens[i] + + if token.type == TokenTypes.Format_Character and token.value == FormatCharacters.Right_Parenthesis.value: + last_token = token + break + + if expected_var and token.type != TokenTypes.Name: + self._runtime.error(Error(ErrorCodesEnum.Unexpected, token.value)) + + if token.type == TokenTypes.Name: + if i + 1 >= tokens.count(): + self._runtime.error(Error(ErrorCodesEnum.Expected, FormatCharacters.Colon.value)) + + if i + 2 >= tokens.count(): + self._runtime.error(Error(ErrorCodesEnum.Expected, Keywords.Type.value)) + + var_ast = List(AST) + var_ast.append(AST(ASTTypesEnum.Name, token.value, self._runtime.line_count, self._runtime.line_count)) + var_ast.append(AST(ASTTypesEnum.Type, tokens[i+2].value, self._runtime.line_count, self._runtime.line_count)) + ast.append(AST(ASTTypesEnum.VariableDeclaration, var_ast, self._runtime.line_count, self._runtime.line_count)) + i += 2 + + if token.type == TokenTypes.Format_Character and token.value == FormatCharacters.Comma.value: + expected_var = True + + last_token = token + i += 1 + + return (AST(ASTTypesEnum.Arguments, ast, self._runtime.line_count, self._runtime.line_count), last_token) + def _parse_library_or_class(self, tokens: List[Token], cls=False) -> AST: """ Parses library or class declarations @@ -200,6 +260,66 @@ class ParserService(ParserABC): return AST(ASTTypesEnum.VariableDeclaration, ast, self._runtime.line_count, self._runtime.line_count) + def _parse_func(self, tokens: List[Token]) -> AST: + """[summary] + + Args: + tokens (List[Token]): [description] + + Returns: + AST: [description] + """ + end = None + ast = List(AST) + i = 0 + while i < tokens.count(): + token: Token = tokens[i] + + # if line contains } + if token.type == TokenTypes.Format_Character and token.value == FormatCharacters.Right_Brace.value: + end = self._runtime.line_count + + elif i == tokens.count()-1 and token.type == TokenTypes.Format_Character and token.value == FormatCharacters.Left_Brace.value: + break + + elif i == tokens.count()-1: + self._runtime.error(Error(ErrorCodesEnum.Expected, FormatCharacters.Left_Brace.value)) + + elif i == 0 and token.type == TokenTypes.Keyword and token.value in self._access_keywords: + ast.append(AST(ASTTypesEnum.Access, token.value, self._runtime.line_count, self._runtime.line_count)) + + elif i <= 1 and token.type == TokenTypes.Keyword and token.value == Keywords.Function.value: + ast.append(AST(ASTTypesEnum.Keyword, token.value, self._runtime.line_count, self._runtime.line_count)) + + elif i >= 1 and token.type == TokenTypes.Name: + ast.append(AST(ASTTypesEnum.Name, token.value, self._runtime.line_count, self._runtime.line_count)) + + elif i >= 2 and token.type == TokenTypes.Format_Character and token.value == FormatCharacters.Left_Parenthesis.value: + args, last_token = self._parse_args(tokens.skip(i)) + if last_token is not None: + i = tokens.index(last_token) + ast.append(args) + + elif i >= 3 and token.type == TokenTypes.Format_Character and token.value == FormatCharacters.Colon.value: + if i+1 > tokens.count(): + self._runtime.error(Error(ErrorCodesEnum.Expected, FormatCharacters.Colon.value)) + + if i+2 > tokens.count(): + self._runtime.error(Error(ErrorCodesEnum.Expected, Keywords.Type.value)) + + if i+3 > tokens.count(): + self._runtime.error(Error(ErrorCodesEnum.Expected, FormatCharacters.Left_Brace.value)) + + ast.append(AST(ASTTypesEnum.Type, tokens[i+1].value, self._runtime.line_count, self._runtime.line_count)) + i += 3 + + else: + self._runtime.error(Error(ErrorCodesEnum.Unexpected, token.value)) + + i += 1 + + return AST(ASTTypesEnum.FuncDeclaration, ast, self._runtime.line_count, end) + def _parse_use(self, tokens: List[Token]) -> AST: """ Parses use imports @@ -257,6 +377,9 @@ class ParserService(ParserABC): elif tokens.where(lambda t: t.type == TokenTypes.Keyword and t.value == Keywords.Class.value).count() > 0: self._ast.append(self._parse_library_or_class(tokens, True)) + elif tokens.where(lambda t: t.type == TokenTypes.Keyword and t.value == Keywords.Function.value).count() > 0: + self._ast.append(self._parse_func(tokens)) + elif tokens.where(lambda t: t.type == TokenTypes.Keyword and t.value == Keywords.Variable.value).count() > 0: self._ast.append(self._parse_variable(tokens))