"""
Um componente adicionando as funcionalidades de sqrt(), sin() e cos() em 
chamadas do eval() padrão no Python.
"""

import math

def avaliar_expressao(expressao):
    i = 0
    while i < len(expressao):
        # método maluco de busca na string (procure um por um até achar)
        if expressao[i:i+4] == "sqrt":
            open_paren = expressao.find("(", i)
            if open_paren == -1:
                raise ValueError("Parêntese de abertura faltando para sqrt")
            close_paren = encontrar_parentese_fechando(expressao, open_paren)
            if close_paren == -1:
                raise ValueError("Parêntese de fechamento faltando para sqrt")
            # recursividade
            arg_sqrt = avaliar_expressao(expressao[open_paren+1:close_paren])
            result = math.sqrt(arg_sqrt)
            # substituição na string
            expressao = expressao[:i] + str(result) + expressao[close_paren+1:]
        elif expressao[i:i+3] == "sin":
            open_paren = expressao.find("(", i)
            if open_paren == -1:
                raise ValueError("Parêntese de abertura faltando para sin")
            close_paren = encontrar_parentese_fechando(expressao, open_paren)
            if close_paren == -1:
                raise ValueError("Parêntese de fechamento faltando para sin")
            arg_sin = avaliar_expressao(expressao[open_paren+1:close_paren])
            result = math.sin(arg_sin)
            expressao = expressao[:i] + str(result) + expressao[close_paren+1:]
        elif expressao[i:i+3] == "cos":
            open_paren = expressao.find("(", i)
            if open_paren == -1:
                raise ValueError("Parêntese de abertura faltando para cos")
            close_paren = encontrar_parentese_fechando(expressao, open_paren)
            if close_paren == -1:
                raise ValueError("Parêntese de fechamento faltando para cos")
            arg_cos = avaliar_expressao(expressao[open_paren+1:close_paren])
            result = math.cos(arg_cos)
            expressao = expressao[:i] + str(result) + expressao[close_paren+1:]
        i += 1
    return eval(expressao)

def encontrar_parentese_fechando(expressao, open_paren):
    count = 1
    i = open_paren + 1
    while i < len(expressao):
        if expressao[i] == "(":
            count += 1
        elif expressao[i] == ")":
            count -= 1
            if count == 0:
                return i
        i += 1
    return -1

expression = "4+sin(2)+sqrt(5)+sin(sin(5+2))"
result = avaliar_expressao(expression)
print(result)