From c96a938727ef0f7864bf99d767ed1ae2f5e7040c Mon Sep 17 00:00:00 2001 From: Daniel Weipert Date: Mon, 8 Jul 2024 11:23:56 +0200 Subject: functions --- henshin | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++------ test/test.test | 9 ++++ 2 files changed, 134 insertions(+), 13 deletions(-) diff --git a/henshin b/henshin index 9958da3..c780b17 100755 --- a/henshin +++ b/henshin @@ -72,6 +72,9 @@ tokens = [ "BRACKET_RIGHT", + "AND", + "OR", + "BIT_AND", "BIT_OR", @@ -102,12 +105,15 @@ t_OPERATOR_PIPE_REPLACEMENT = r'\$' t_PARENTHESIS_LEFT = r'\(' t_PARENTHESIS_RIGHT = r'\)' -t_BRACE_LEFT = r'\[' -t_BRACE_RIGHT = r'\]' -t_BRACKET_LEFT = r'{' -t_BRACKET_RIGHT = r'}' +t_BRACKET_LEFT = r'\[' +t_BRACKET_RIGHT = r'\]' +t_BRACE_LEFT = r'{' +t_BRACE_RIGHT = r'}' +t_AND = r'\&\&' +t_OR = r'\|\|' +t_BIT_AND = r'\&' t_BIT_OR = r'\|' @@ -189,7 +195,7 @@ class AstNodeVariableDeclarationStatement(AstNode): class AstNodeVariableReassignmentStatement(AstNode): def __init__(self, name, value): - self.type = type + self.name = name self.value = value class AstNodeExpression(AstNode): @@ -203,6 +209,32 @@ class AstNodeOperatorExpression(AstNode): self.left = left self.right = right +class AstNodeFunctionDeclaration(AstNode): + def __init__(self, name, parameters, return_type, body): + self.name = name + self.parameters = parameters + self.return_type = return_type + self.body = body + +class AstNodeFunctionDeclarationParameter(AstNode): + def __init__(self, name, type): + self.name = name + self.type = type + +class AstNodeReturnStatement(AstNode): + def __init__(self, expression): + self.expression = expression + +class AstNodeFunctionCall(AstNode): + def __init__(self, name, parameters): + self.name = name + self.parameters = parameters + +class AstNodeFunctionCallParameter(AstNode): + def __init__(self, name, value): + self.name = name + self.value = value + precedence = ( ('left', 'OPERATOR_PLUS', 'OPERATOR_MINUS'), @@ -217,9 +249,20 @@ def p_statements(p): def resolve_nodes(node, level): node_dict = node.__dict__ for property in node_dict: - if isinstance(node_dict[property], AstNode): - print('> '*level, property, node_dict[property].__class__.__name__) - resolve_nodes(node_dict[property], level+1) + node_value = node_dict[property] + + if isinstance(node_value, AstNode): + print('> '*level, property, node_value.__class__.__name__) + resolve_nodes(node_value, level+1) + elif isinstance(node_value, list): + list_length = len(node_value) + print('> '*level, property + '[' + str(list_length) + ']:') + + for idx in range(list_length): + item = node_value[idx] + + print('> '*(level+1), str(idx+1)+'.', item.__class__.__name__) + resolve_nodes(item, level+2) else: print('> '*level, property, node_dict[property]) @@ -227,15 +270,67 @@ def p_statements(p): print(p[1].__class__.__name__) resolve_nodes(p[1], 0) + statements = [p[1]] + if len(p) > 2: + statements.extend(p[2]) + p[0] = statements + def p_statement(p): '''statement : variable_declaration_statement - | variable_reassignment_statement''' + | variable_reassignment_statement + | function_declaration + | return_statement''' p[0] = p[1] -# def p_function(p): -# '''function : FUNCTION IDENTIFIER PARENTHESIS_LEFT function_parameters PARENTHESIS_RIGHT COLON return_type BRACKET_LEFT statements BRACKET_RIGHT''' -# pass + +def p_function_declaration(p): + '''function_declaration : FUNCTION IDENTIFIER PARENTHESIS_LEFT function_declaration_parameters PARENTHESIS_RIGHT COLON return_type BRACE_LEFT statements BRACE_RIGHT''' + + p[0] = AstNodeFunctionDeclaration(p[2], p[4], p[7], p[9]) + +def p_function_declaration_parameters(p): + '''function_declaration_parameters : function_declaration_parameter COMMA function_declaration_parameters + | function_declaration_parameter + |''' + + parameters = [p[1]] + if len(p) > 2: + parameters.append(p[3]) + + p[0] = parameters + +def p_function_declaration_parameter(p): + '''function_declaration_parameter : IDENTIFIER COLON variable_type''' + + p[0] = AstNodeFunctionDeclarationParameter(p[1], p[3]) + + +def p_function_call(p): + '''function_call : IDENTIFIER PARENTHESIS_LEFT function_call_parameters PARENTHESIS_RIGHT SEMICOLON''' + + p[0] = AstNodeFunctionCall(p[1], p[3]) + +def p_function_call_parameters(p): + '''function_call_parameters : function_call_parameter COMMA function_call_parameters + | function_call_parameter + |''' + + parameters = [p[1]] + if len(p) > 2: + parameters.append(p[3]) + + p[0] = parameters + +def p_function_call_parameter(p): + '''function_call_parameter : IDENTIFIER ASSIGN expression + | expression''' + + if len(p) > 2: + p[0] = AstNodeFunctionCallParameter(p[1], p[3]) + else: + p[0] = AstNodeFunctionCallParameter("", p[1]) + def p_variable_declaration_statement(p): '''variable_declaration_statement : variable_declarator IDENTIFIER COLON variable_type ASSIGN expression SEMICOLON''' @@ -244,7 +339,8 @@ def p_variable_declaration_statement(p): def p_variable_reassignment_statement(p): '''variable_reassignment_statement : IDENTIFIER ASSIGN expression SEMICOLON''' - pass + + p[0] = AstNodeVariableReassignmentStatement(p[1], p[3]) def p_variable_declarator(p): '''variable_declarator : CONST @@ -256,6 +352,18 @@ def p_variable_type(p): | TYPE_STRING''' p[0] = p[1] + +def p_return_statement(p): + '''return_statement : RETURN expression SEMICOLON''' + + p[0] = AstNodeReturnStatement(p[2]) + +def p_return_type(p): + '''return_type : variable_type + | TYPE_VOID''' + p[0] = p[1] + + def p_identifier(p): '''identifier : IDENTIFIER''' @@ -275,6 +383,7 @@ def p_expression(p): '''expression : identifier | number | string + | function_call | expression OPERATOR_PLUS expression | expression OPERATOR_MINUS expression | expression OPERATOR_MULTIPLY expression @@ -293,3 +402,6 @@ def p_error(p): parser = yacc.yacc(debug=True, debuglog=log) result = parser.parse(input) # print(result) + +# if __name__ == "__main__": +# lex.runmain() diff --git a/test/test.test b/test/test.test index 5e3f420..2ffe743 100644 --- a/test/test.test +++ b/test/test.test @@ -6,3 +6,12 @@ ply = "way cooler!!"; const new: integer = henshin * 5 + 10; const test: integer = 1 + 1; + +function main(input: string): void { + const hello: string = "world!"; + const bye: string = "bye!"; + + return hello; +} + +main(test); -- cgit v1.2.3