function equate(Expressao){
// É NECESSÁRIO EXECUTAR parseVariables
var posExp = 0;
var aindaTem;
// Operador de expoente
OPERATOR = "Exp";
aindaTem = (0==0);
while ( aindaTem ){
posExp = FUNCOES[OPERATOR](textoConv);
if( posExp >= 0 ){
// Divide operandos à esquerda e à direita do operador
var OpDir = rightOperand(posExp);
var OpEsq = leftOperand(posExp);
// Concretiza a operação
Resultado = Math.pow(varValue(OpEsq),varValue(OpDir));
// Substitui o valor da variável à esquerda
VARIABLES[OpEsq] = Resultado;
// Zera a variável à direita
VARIABLES[OpDir] = 0;
// testa o fim e refaz a expressão
textoConv = updExpression(textoConv, posExp);
} else {
aindaTem = (0==1);
}
}
// Operador de multiplicação
OPERATOR = "Mul";
aindaTem = (0==0);
while ( aindaTem ){
posExp = FUNCOES[OPERATOR](textoConv);
if( posExp >= 0 ){
// Divide operandos à esquerda e à direita do operador
var OpDir = rightOperand(posExp);
var OpEsq = leftOperand(posExp);
// Concretiza a operação
Resultado = varValue(OpEsq)*varValue(OpDir);
// Substitui o valor da variável à esquerda
VARIABLES[OpEsq] = Resultado;
// Zera a variável à direita
VARIABLES[OpDir] = 0;
// testa o fim e refaz a expressão
textoConv = updExpression(textoConv, posExp);
} else {
aindaTem = (0==1);
}
}
// Operador de divisão
OPERATOR = "Div";
aindaTem = (0==0);
while ( aindaTem ){
posExp = FUNCOES[OPERATOR](textoConv);
if( posExp >= 0 ){
// Divide operandos à esquerda e à direita do operador
var OpDir = rightOperand(posExp);
var OpEsq = leftOperand(posExp);
// Concretiza a operação
Resultado = varValue(OpEsq)/varValue(OpDir);
// Substitui o valor da variável à esquerda
VARIABLES[OpEsq] = Resultado;
// Zera a variável à direita
VARIABLES[OpDir] = 0;
// testa o fim e refaz a expressão
textoConv = updExpression(textoConv, posExp);
} else {
aindaTem = (0==1);
}
}
// Operador de soma
OPERATOR = "Sum";
aindaTem = (0==0);
while ( aindaTem ){
posExp = FUNCOES[OPERATOR](textoConv);
if( posExp >= 0 ){
// Divide operandos à esquerda e à direita do operador
var OpDir = rightOperand(posExp);
var OpEsq = leftOperand(posExp);
// Concretiza a operação
Resultado = varValue(OpEsq)+varValue(OpDir);
// Substitui o valor da variável à esquerda
VARIABLES[OpEsq] = Resultado;
// Zera a variável à direita
VARIABLES[OpDir] = 0;
// testa o fim e refaz a expressão
textoConv = updExpression(textoConv, posExp);
} else {
aindaTem = (0==1);
}
}
return textoConv;
}
Esta função tem quatro partes. cada uma trata de um operador ("^", "*", "/" e "+"). E como já ressaltamos nos posts anteriores, a subtração foi transformada em soma, pois nosso parseVariables já providenciou a colocação dos sinais negativos como parte do valor do operando, dentro do array VARIABLES.
Vamos explicar a lógica de um operador, para explicar a resolução das expressões, pois ela valerá para todos. Seja o trecho que executa a multiplicação.
Iniciamos um loop while com a condição aindaTem em verdadeiro. Então chamamos a função redirecionada pelo array FUNCOES, índice "Mul" (Multiplicação). O array FUNCOES direciona esta função para findMultiplication:
// Acha uma operação de MULTIPLICAÇÃO em uma expressão
function findMultiplication(texto){
var posicao = findOperator("*", texto);
return posicao;
}
Esta função chama a função findOperator com o argumento "*" (operador de multiplicação):
// Acha um tipo de operador em um texto ou expressão
function findOperator(op,texto){
return texto.indexOf(op);
}
Que, por sua vez, utiliza a função indexOf do objeto string para achar a posição de um caracter, no caso o operador "*". Se este operador for achado, ocorrerá o tratamento da operação de multiplicação entre os dois operandos adjacentes, expressos por variáveis "Vnn".
Extração dos operandos
Uma vez achado um operador, o programa obtém o operando à sua esquerda (leftOperand) e à sua direita (rightOperand). Vamos mostrar os códigos destas funções:// Obtém a variável à esquerda DE UMA POSIÇÃO (no caso um operador aritmético)
function leftOperand(pos){
return textoConv.substr(pos-3,3);
}
// Obtém a variável à direita DE UMA POSIÇÃO (no caso um operador aritmético)
function rightOperand(pos){
return textoConv.substr(pos+1,3);
}
Ambas não tem muito mistério. Apenas utilizam o tão conhecido método substr do objeto string.
No entanto, estes são apenas os nomes dos índices das variáveis, é preciso obter o valor de cada um para calcular o Resultado:
Resultado = varValue(OpEsq)*varValue(OpDir);
Vejamos como funciona varValue:
// Obtém o valor armazenado em uma variável
function varValue(nomeVar){
return VARIABLES[nomeVar];
}
Ela se refere, através de um índice, ao array VARIABLES, e extrai seu valor. Exemplo:
VARIABLES["V01"] fornece o valor da variável V01, estabelecida pela função parseVariables.
A variável textoConv contém a última transformação da expressão em termos de variáveis, e não mais em termos de numerais.
Tratamento do Resultado
Uma vez obtido o Resultado, a variável do array indexada por OpEsq recebe este resultado, e variável do array indexada por OpDir recebe o valor 0 (zero).Atualização da expressão
Uma vez obtido o resultado e armazenado no array de variaveis, é preciso refazer a expressão na forma de de variáveis em textoConv. Isto é feito pela função updExpression, cujo código apresentamos aqui:// Faz o teste de finalização e atualiza a Expressão aritmética
function updExpression(textoConv, posExp){
if( left(textoConv,posExp) == left(right(textoConv,posExp+4),left(textoConv,posExp).length) ) {
textoConv = left(textoConv,posExp);
} else {
textoConv = left(textoConv,posExp)+right(textoConv,posExp+4);
}
return textoConv;
}
É feito um teste para verificar se o processamento da expressão, na forma de variáveis, após o ajuste da expressão, depois de uma operação aritmética. Este teste, em suma, averigua se a expressão colhida à esquerda é igual ao fragmento de mesmo comprimento na expressão da direita. Se isto for verdade, textoConv (a próxima expressão a ser interpretada) será apenas o conteúdo do lado esquerdo, senão haverá a concatenação do lado esquerdo com o direito, suprimindo o operador da última operação e o operando da direita (pois ele foi zerado, e o resultado da operação colocado no operando da esquerda).
Quando a interpretação de toda a expressão estiver terminada, a variável de índice "V01" estará armazenando o resultado final do nível corrente de parênteses..
Conclusão
Nesta fase, as operações aritméticas são efetuadas, e temos o resultado final de uma expressão pura ou extraída do interior de um nível de parênteses.No próximo post apresentaremos os detalhes da função solvExpression, que trata os níveis de parênteses.









