def p_args(p):
    """ args    : arg_tuple ',' args
                | arg_tuple """
    args = []

    args.append((tree.NameVal(p[1][0]), tree.TypeVal(p[1][1])))
    if "," in p[1:]:
        for argument in p[3].get_arguments():
            args.append(argument)

    p[0] = tree.Args(args)
def p_expression_call_no_args(p):
    " expression : NAME '(' ')' "
    p[0] = tree.Call(tree.NameVal(p[1]), None)
def p_expression_call(p):
    " expression : NAME '(' args_val ')' "
    p[0] = tree.Call(tree.NameVal(p[1]), p[3])
def p_statement_no_args_function(p):
    " statement : FUNCTION NAME '(' ')' '=' '{' block '}'"
    p[0] = tree.Function(tree.NameVal(p[2]), None, p[7])
def p_statement_function(p):
    " statement : FUNCTION NAME '(' args ')' '=' '{' block '}'"
    p[0] = tree.Function(tree.NameVal(p[2]), p[4], p[8])
def p_statement_type_value_assignment(p):
    "statement : NAME TVASSIGNMENT statement"
    p[0] = tree.AssignWithType(tree.NameVal(p[1]), p[3])
def p_statement_type_declaration(p):
    "statement : arg_tuple"
    p[0] = tree.TypeDeclare(tree.NameVal(p[1][0]), tree.TypeVal(p[1][1]))
def p_statement_assignment(p):
    "statement : NAME '=' statement "
    p[0] = tree.Assign(tree.NameVal(p[1]), p[3])