Sugestão de roteiro para fazer este EP ...................................... Após estudar e entender o `enunciado do EP `__, baixe os `arquivos `__ para este EP9. Em seguida, depois de alterar o nome do módulo ``esqueleto_calculadora.py`` para ``calculadora.py`` copie a implementação que você fez da classe ``Calculadora`` para o EP8. Se você não fez o EP8, ainda assim você poderá fazer quase a totalidade deste EP. O EP9 consiste, essencialmente, na implementação da função ``infixa_para_posfixa()`` que está no módulo ``calculadora.py``. .. sourcecode:: python def infixa_para_posfixa(infixa): '''(list de Tokens) -> list de Tokens Recebe uma lista infixa de Tokens representando uma expressão em notação infixa e retorna uma lista de tokens representando uma expressão equivalente na notação posfixa. Essa função utiliza uma pilha que contém apenas operadores e abre parênteses. Veja as notas de aula. Pode ser útil utilizar nessa função o dicionário PREC do modulo operadores.py. Nesse dicionário as chaves são os operadores (str) e os valores (int) representam a precedência dos operadores: quanto maior o valor, maior a precedência. Exemplos: >>> >>> tokens = tokeniza("a = 2 * 31.4") >>> imprima_tokens(tokens) [V('a'), O('='), N(2), O('*'), N(31.4)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [V('a'), N(2), N(31.4), O('*'), O('=')] >>> >>> tokens = tokeniza("2+3+4") >>> imprima_tokens(tokens) [N(2), O('+'), N(3), O('+'), N(4)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(2), N(3), O('+'), N(4), O('+')] >>> >>> tokens = tokeniza("2^3^4") >>> imprima_tokens(tokens) [N(2), O('^'), N(3), O('^'), N(4)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(2), N(3), N(4), O('^'), O('^')] >>> >>> tokens = tokeniza("(2+3)*4") >>> imprima_tokens(tokens) [P('('), N(2), O('+'), N(3), P(')'), O('*'), N(4)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(2), N(3), O('+'), N(4), O('*')] >>> >>> tokens = tokeniza("22+33*4.4") >>> imprima_tokens(tokens) [N(22), O('+'), N(33), O('*'), N(4.4)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(22), N(33), N(4.4), O('*'), O('+')] >>> ''' Para implementar a função ``infixa_para_posfixa()`` você deve consultar as notas de aula ou estudar uma das duas referências a seguir: `Conversion of Infix Expressions to Prefix and Postfix `__ do capítulo `Infix, Prefix and Postfix Expressions `__ do livro `Problem Solving with Algorithms and Data Structures `__. *Outra aplicação: notação polonesa* do capítulo `Pilhas `__ do página de `Projeto de Algoritmos em C `__ do Prof. `Paulo Feofiloff `__. Depois de carregar o módulo ``calculadora.py`` execute o módulo (= ``Run -> Run Module``) e teste a função ``infixa_para_posfixa()`` no Python Shell. Os exemplos a seguir mostram o comportamento da função. .. sourcecode:: python Python 3.4.3 (default, Mar 26 2015, 22:03:40) [GCC 4.9.2] on linux Type "copyright", "credits" or "license()" for more information. >>> ================================ RESTART ================================ >>> >>> tokens = tokeniza("11") >>> imprima_tokens(tokens) [N(11)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(11)] >>> >>> tokens = tokeniza("11 2.34 aa bb cc") >>> imprima_tokens(tokens) [N(11), N(2.34), V('aa'), V('bb'), V('cc')] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(11), N(2.34), V('aa'), V('bb'), V('cc')] >>> >>> tokens = tokeniza("11 + 22") >>> imprima_tokens(tokens) [N(11), O('+'), N(22)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(11), N(22), O('+')] >>> >>> tokens = tokeniza("1 + 2 - 3") >>> imprima_tokens(tokens) [N(1), O('+'), N(2), O('-'), N(3)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(1), N(2), O('+'), N(3), O('-')] >>> >>> tokens = tokeniza("1 - 2 + 3") >>> imprima_tokens(tokens) [N(1), O('-'), N(2), O('+'), N(3)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(1), N(2), O('-'), N(3), O('+')] >>> >>> tokens = tokeniza("1 + 2 * 3") >>> imprima_tokens(tokens) [N(1), O('+'), N(2), O('*'), N(3)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(1), N(2), N(3), O('*'), O('+')] >>> >>> tokens = tokeniza("1 / 2 * 3 % 4") >>> imprima_tokens(tokens) [N(1), O('/'), N(2), O('*'), N(3), O('%'), N(4)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(1), N(2), O('/'), N(3), O('*'), N(4), O('%')] >>> >>> tokens = tokeniza("!1") >>> imprima_tokens(tokens) [O('!'), N(1)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(1), O('!')] >>> >>> tokens = tokeniza("!1 + 2") >>> imprima_tokens(tokens) [O('!'), N(1), O('+'), N(2)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(1), O('!'), N(2), O('+')] >>> >>> tokens = tokeniza("1 + !2") >>> imprima_tokens(tokens) [N(1), O('+'), O('!'), N(2)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(1), N(2), O('!'), O('+')] >>> >>> tokens = tokeniza("1 + !2 * 3") >>> imprima_tokens(tokens) [N(1), O('+'), O('!'), N(2), O('*'), N(3)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(1), N(2), O('!'), N(3), O('*'), O('+')] >>> >>> tokens = tokeniza("(1 + 2) * 3") >>> imprima_tokens(tokens) [P('('), N(1), O('+'), N(2), P(')'), O('*'), N(3)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(1), N(2), O('+'), N(3), O('*')] >>> >>> tokens = tokeniza("4 / (1 + 2 * 3) * 3") >>> imprima_tokens(tokens) [N(4), O('/'), P('('), N(1), O('+'), N(2), O('*'), N(3), P(')'), O('*'), N(3)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(4), N(1), N(2), N(3), O('*'), O('+'), O('/'), N(3), O('*')] >>> >>> tokens = tokeniza("a + (b + (c + (d + (e + f))))") >>> imprima_tokens(tokens) [V('a'), O('+'), P('('), V('b'), O('+'), P('('), V('c'), O('+'), P('('), V('d'), O('+'), P('('), V('e'), O('+'), V('f'), P(')'), P(')'), P(')'), P(')')] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [V('a'), V('b'), V('c'), V('d'), V('e'), V('f'), O('+'), O('+'), O('+'), O('+'), O('+')] >>> >>> tokens = tokeniza("a + (b * (c / (d % (e - f))))") >>> imprima_tokens(tokens) [V('a'), O('+'), P('('), V('b'), O('*'), P('('), V('c'), O('/'), P('('), V('d'), O('%'), P('('), V('e'), O('-'), V('f'), P(')'), P(')'), P(')'), P(')')] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [V('a'), V('b'), V('c'), V('d'), V('e'), V('f'), O('-'), O('%'), O('/'), O('*'), O('+')] >>> >>> tokens = tokeniza("2 ^ 3 ^ 4 ^ 5") >>> imprima_tokens(tokens) [N(2), O('^'), N(3), O('^'), N(4), O('^'), N(5)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(2), N(3), N(4), N(5), O('^'), O('^'), O('^')] >>> >>> tokens = tokeniza("!!!!2") >>> imprima_tokens(tokens) [O('!'), O('!'), O('!'), O('!'), N(2)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(2), O('!'), O('!'), O('!'), O('!')] >>> >>> tokens = tokeniza("!2 ^ !3 ^ !4 ^ !5") >>> imprima_tokens(tokens) [O('!'), N(2), O('^'), O('!'), N(3), O('^'), O('!'), N(4), O('^'), O('!'), N(5)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [N(2), N(3), N(4), N(5), O('!'), O('^'), O('!'), O('^'), O('!'), O('^'), O('!')] >>> >>> tokens = tokeniza("a = 2 + 3 * 4") >>> imprima_tokens(tokens) [V('a'), O('='), N(2), O('+'), N(3), O('*'), N(4)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [V('a'), N(2), N(3), N(4), O('*'), O('+'), O('=')] >>> >>> tokens = tokeniza("a = b = c = 0") >>> imprima_tokens(tokens) [V('a'), O('='), V('b'), O('='), V('c'), O('='), N(0)] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [V('a'), V('b'), V('c'), N(0), O('='), O('='), O('=')] >>> tokens = tokeniza("a = b = c = a + b * c") >>> imprima_tokens(tokens) [V('a'), O('='), V('b'), O('='), V('c'), O('='), V('a'), O('+'), V('b'), O('*'), V('c')] >>> posfixa = infixa_para_posfixa(tokens) >>> imprima_tokens(posfixa) [V('a'), V('b'), V('c'), V('a'), V('b'), V('c'), O('*'), O('+'), O('='), O('='), O('=')] >>> ``eval()`` .......... Se você não fez o EP8, então entregue o módulo ``calculadora.py`` apenas com a função ``infixa_para_posfixa()`` que você implementou, além do resto do esqueleto que está no módulo que você baixou. Para terminar este EP só falta agora você fazer algumas pequenas alteração no método ``eval()`` da classe ``Calculadora`` que você fez para o EP8. Abaixo está a especificação do método ``eval()`` que você implementou para o EP8. .. sourcecode:: python def eval(self, exp = ''): ''' (str) -> float ou None Recebe um string representando uma expressão em notação posfixa e retorna o valor da expressão. Se algum erro for detectado na expressão a função retorna None. ''' A seguir está a documentação do novo método ``eval()`` para o EP9. Verifique qual a difereça. .. sourcecode:: python def eval(self, exp = ''): ''' (str) -> float ou None Recebe um string representando uma expressão em NOTAÇÃO INFIXA e retorna o valor da expressão. Se algum erro for detectado na expressão a função retorna None. ''' Depois das alterações, carregue o módulo ``calculadora.py`` execute-o (= ``Run -> Run Module``). Veja abaixo alguns testes do novo método ``eval()`` .. sourcecode:: python Python 3.4.3 (default, Mar 26 2015, 22:03:40) [GCC 4.9.2] on linux Type "copyright", "credits" or "license()" for more information. >>> ================================ RESTART ================================ >>> >>> hp = Calculadora() >>> hp.eval("1 + 2") 3.0 >>> hp.eval("1+2 *3") 7.0 >>> hp.eval("(1+2) *3") 9.0 >>> hp.eval("a = 1 + 2") 3.0 >>> hp.mostre_variaveis() {'a': 3} >>> hp.eval("a = a + 2") 5.0 >>> hp.mostre_variaveis() {'a': 5} >>> hp.eval("d = a") 5.0 >>> hp.mostre_variaveis() {'d': 5, 'a': 5} >>> hp.eval("c = e = f = d = a = 1") 1.0 >>> hp.mostre_variaveis() {'c': 1, 'd': 1, 'e': 1, 'f': 1, 'a': 1} >>> hp.troca_modo_verboso() AVISO: modo verboso ativado. >>> hp.eval("1 + 2 - 3") eval(): string expr = '1 + 2 - 3' eval(): lista tokens = [N(1), O('+'), N(2), O('-'), N(3)] lista de tokens: [N(1), N(2), O('+'), N(3), O('-')] pilha de execução: [] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [N(2), O('+'), N(3), O('-')] pilha de execução: [N(1)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [O('+'), N(3), O('-')] pilha de execução: [N(1), N(2)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [N(3), O('-')] pilha de execução: [N(3)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [O('-')] pilha de execução: [N(3), N(3)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [] pilha de execução: [N(0)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado 0.0 >>> hp.eval("(1+2)*3/4") eval(): string expr = '(1+2)*3/4' eval(): lista tokens = [P('('), N(1), O('+'), N(2), P(')'), O('*'), N(3), O('/'), N(4)] lista de tokens: [N(1), N(2), O('+'), N(3), O('*'), N(4), O('/')] pilha de execução: [] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [N(2), O('+'), N(3), O('*'), N(4), O('/')] pilha de execução: [N(1)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [O('+'), N(3), O('*'), N(4), O('/')] pilha de execução: [N(1), N(2)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [N(3), O('*'), N(4), O('/')] pilha de execução: [N(3)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [O('*'), N(4), O('/')] pilha de execução: [N(3), N(3)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [N(4), O('/')] pilha de execução: [N(9)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [O('/')] pilha de execução: [N(9), N(4)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [] pilha de execução: [N(2.25)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado 2.25 >>> hp.eval("2 ^ 2 ^ 3") eval(): string expr = '2 ^ 2 ^ 3' eval(): lista tokens = [N(2), O('^'), N(2), O('^'), N(3)] lista de tokens: [N(2), N(2), N(3), O('^'), O('^')] pilha de execução: [] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [N(2), N(3), O('^'), O('^')] pilha de execução: [N(2)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [N(3), O('^'), O('^')] pilha de execução: [N(2), N(2)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [O('^'), O('^')] pilha de execução: [N(2), N(2), N(3)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [O('^')] pilha de execução: [N(2), N(8)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [] pilha de execução: [N(256)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado 256.0 >>> hp.eval("(2 ^ 2) ^ 3") eval(): string expr = '(2 ^ 2) ^ 3' eval(): lista tokens = [P('('), N(2), O('^'), N(2), P(')'), O('^'), N(3)] lista de tokens: [N(2), N(2), O('^'), N(3), O('^')] pilha de execução: [] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [N(2), O('^'), N(3), O('^')] pilha de execução: [N(2)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [O('^'), N(3), O('^')] pilha de execução: [N(2), N(2)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [N(3), O('^')] pilha de execução: [N(4)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [O('^')] pilha de execução: [N(4), N(3)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado lista de tokens: [] pilha de execução: [N(64)] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: ativado 64.0 >>> hp.mostre_variaveis() {'c': 1, 'd': 1, 'e': 1, 'f': 1, 'a': 1} >>> hp.troca_modo_verboso() AVISO: modo verboso desativado. >>> hp.eval("2 ^ 2 ^ 3") 256.0 >>> hp.eval("(2 ^ 2) ^ 3") 64.0 >>> hp.eval("3 + !3") 0.0 >>> hp.eval("3 + !!3") 6.0 >>> hp.eval("3 + !!!3") 0.0 >>> hp.eval("3 + !!!!3") # :-) 6.0 >>> print(hp) lista de tokens: [] pilha de execução: [] dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0} modo verboso: desativado >>> hp = Calculadora() >>> print(hp) lista de tokens: [] pilha de execução: [] dicionário de variáveis: {} modo verboso: desativado >>> hp.eval("a = 1") 1.0 >>> hp.eval("b = 2") 2.0 >>> hp.eval("c = 3") 3.0 >>> hp.mostre_variaveis() {'b': 2, 'c': 3, 'a': 1} >>> hp.eval("c = a = b = a + b * c") 7.0 >>> hp.mostre_variaveis() {'b': 7, 'c': 7, 'a': 7} >>> Finalmente, depois que as suas implementações acima estiverem funcionando, você pode testar a sua calculadora por completo. Para isso basta executar o módulo ``main.py``.