Improved parser to handle variables

This commit is contained in:
Sven Heidemann 2021-10-28 15:11:13 +02:00
parent b11ec9003e
commit e6895992c2
6 changed files with 70 additions and 16 deletions

View File

@ -1,5 +1,3 @@
public lib Preview.Variables { public lib Preview.Variables {
public var str: string = "Hello World"; public var str: string = "Hello World";
public var test: bool = false; public var test: bool = false;

View File

@ -17,8 +17,8 @@ public lib Main {
} }
private func testForEach(): void { private func testForEach(): void {
var list = []; var loopList = [];
list.forEach(e => { loopList.forEach(e => {
output(e); output(e);
}); });
} }

View File

@ -34,7 +34,8 @@ class LanguageDefinition:
Keywords.Public.value, Keywords.Public.value,
Keywords.Private.value, Keywords.Private.value,
Keywords.Static.value, Keywords.Static.value,
Keywords.This.value Keywords.This.value,
Keywords.Type.value
] ]
datatypes = [ datatypes = [
Datatypes.Empty.value, Datatypes.Empty.value,

View File

@ -36,6 +36,7 @@ class Keywords(Enum):
Private = 'private' Private = 'private'
Static = 'static' Static = 'static'
This = 'this' This = 'this'
Type = 'type'
class Booleans(Enum): class Booleans(Enum):

View File

@ -6,9 +6,10 @@ class ASTTypesEnum(Enum):
Access = 'access' Access = 'access'
Keyword = 'keyword' Keyword = 'keyword'
Name = 'name' Name = 'name'
Type = 'type'
LibraryDeclaration = 'library_declaration' LibraryDeclaration = 'library_declaration'
ClassDeclaration = 'class_declaration' ClassDeclaration = 'class_declaration'
FuncDeclaration = 'func_declaration' FuncDeclaration = 'func_declaration'
VariableDeclaration = 'variable_declaration' VariableDeclaration = 'variable_declaration'
VariableValue = 'variable_value'

View File

@ -3,7 +3,7 @@ from parser.abc.ast import AST
from parser.abc.parser_abc import ParserABC from parser.abc.parser_abc import ParserABC
from parser.model.ast_types_enum import ASTTypesEnum from parser.model.ast_types_enum import ASTTypesEnum
from cc_lang.model.language_definition_classes import FormatCharacters, Keywords from cc_lang.model.language_definition_classes import ExpressionCharacters, FormatCharacters, Keywords
from cpl_core.console.console import Console from cpl_core.console.console import Console
from cpl_query.extension.list import List from cpl_query.extension.list import List
from lexer.model.token import Token from lexer.model.token import Token
@ -40,7 +40,7 @@ class ParserService(ParserABC):
<name> <.> <name> <name> <.> <name>
Returns: Returns:
AST: Name AST Tuple[AST, Token]: Name as AST and last Token of Name
""" """
name = '' name = ''
last_token: Optional[Token] = None last_token: Optional[Token] = None
@ -55,13 +55,10 @@ class ParserService(ParserABC):
else: else:
break break
last_token = token last_token = token
return (AST(ASTTypesEnum.Name, name, self._runtime.line_count, self._runtime.line_count), last_token) return (AST(ASTTypesEnum.Name, name, self._runtime.line_count, self._runtime.line_count), last_token)
def _parse_library_or_class(self, tokens: List[Token], cls=False) -> AST: def _parse_library_or_class(self, tokens: List[Token], cls=False) -> AST:
""" Parses library or class declarations """ Parses library or class declarations
@ -108,9 +105,9 @@ class ParserService(ParserABC):
elif i >= 1 and token.type == TokenTypes.Name: elif i >= 1 and token.type == TokenTypes.Name:
name, last_token = self._parse_name(tokens.skip(i)) name, last_token = self._parse_name(tokens.skip(i))
if last_token is not None:
i = tokens.index(last_token) i = tokens.index(last_token)
ast.append(name) ast.append(name)
ast.append(AST(ASTTypesEnum.Name, token.value, self._runtime.line_count, self._runtime.line_count))
else: else:
self._runtime.error(Error(ErrorCodesEnum.Unexpected, token.value)) self._runtime.error(Error(ErrorCodesEnum.Unexpected, token.value))
@ -128,6 +125,8 @@ class ParserService(ParserABC):
AST: AST:
var test: number; var test: number;
<var> <name> <type> <end> <var> <name> <type> <end>
var test = 0;
<var> <name> <value | int, str, bool> <end>
var test: number = 0; var test: number = 0;
<var> <name> <type> <value | int, str, bool> <end> <var> <name> <type> <value | int, str, bool> <end>
var test: number = test; var test: number = test;
@ -142,10 +141,64 @@ class ParserService(ParserABC):
""" """
end = None end = None
ast = List(AST) ast = List(AST)
for i in range(0, tokens.count()): i = 0
# for i in range(0, tokens.count()):
while i < tokens.count():
token: Token = tokens[i] token: Token = tokens[i]
return AST(ASTTypesEnum.VariableDeclaration, ast) if i == tokens.count()-1 and token.type == TokenTypes.Format_Character and token.value == FormatCharacters.Semicolon.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 >= 0 and token.type == TokenTypes.Keyword and Keywords.Variable.value:
ast.append(AST(ASTTypesEnum.Keyword, token.value, self._runtime.line_count, self._runtime.line_count))
elif i >= 1 and token.type == TokenTypes.Name:
name, last_token = self._parse_name(tokens.skip(i))
i = tokens.index(last_token)
ast.append(name)
elif i >= 2 and token.type == TokenTypes.Format_Character and token.value == FormatCharacters.Colon.value:
if i+1 < tokens.count():
next_token = tokens[i+1]
ast.append(AST(ASTTypesEnum.Type, next_token.value, self._runtime.line_count, self._runtime.line_count))
i += 1
else:
self._runtime.error(Error(ErrorCodesEnum.Expected, ASTTypesEnum.Type.value))
elif i >= 2 and token.type == TokenTypes.Expression_Character and token.value == ExpressionCharacters.Equal.value:
if i+1 < tokens.count():
end = tokens.where(lambda t: t.type == TokenTypes.Format_Character and t.value == FormatCharacters.Semicolon.value).first_or_default()
value = ''
if end is not None:
for t in tokens[i+1:]:
t: Token = t
if t == end:
break
value += t.value
ast.append(AST(ASTTypesEnum.VariableValue, value, self._runtime.line_count, self._runtime.line_count))
i = tokens.index(end)
else:
self._runtime.error(Error(ErrorCodesEnum.Expected, ASTTypesEnum.Type.value))
elif i == tokens.count()-1 and token.type != TokenTypes.Format_Character and token.value != FormatCharacters.Semicolon.value:
self._runtime.error(Error(ErrorCodesEnum.Expected, FormatCharacters.Semicolon.value))
else:
if i == 1 or i == 2 and token.type == TokenTypes.Type:
self._runtime.error(Error(ErrorCodesEnum.Unexpected, f'{token.type.name.lower()}: {token.value}'))
else:
self._runtime.error(Error(ErrorCodesEnum.Unexpected, {token.value}))
i += 1
return AST(ASTTypesEnum.VariableDeclaration, ast, self._runtime.line_count, self._runtime.line_count)
def create_ast(self, tokens: List[Token]) -> List[AST]: def create_ast(self, tokens: List[Token]) -> List[AST]:
self._ast = List(AST) self._ast = List(AST)