package Portugol.Language.Calcular;
import Portugol.Language.Analisador.Simbolo;
import Portugol.Language.Utilitario.Parentesis;
import Portugol.Language.Utilitario.IteratorExpression;
import Portugol.Language.Utilitario.IteratorString;
import java.util.Stack;
import java.util.Vector;
public class Calculador {
public static String VERSION = "Versão:2.0 \t(c)Augusto Bilabila e David Silva Barrera";
/**
* Creates a new instance of Calculador
*/
Vector inFix;
Vector posFix;
private static CalculusElement calculator = new CalculusElement();
// constroi um calculador com uma expressao na forma infixa
public Calculador(Vector exp) {
inFix = exp;
try {
posFix = this.CalulatePosFix(inFix);
} catch (Exception e) {
//posFix = e.getMessage();
}
}
// verifica se a string é um elemento de cálculo válido
public static boolean IsCalculus(Object str) {
CalculusElement calculator = new CalculusElement();
return calculator.IsCalculus(str);
}
// retorna a expressao infixa normalizada
public Vector GetInfix() {
return inFix;
}
// retorna a Expressao posfixa
public Vector GetPosfix() {
return posFix;
}
// faz o calculo da expressao
// public Object GetResult() throws Exception {
// return CalulateValue(inFix);
// }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/**
* metodo estatico que converte infixa em posfixa
*/
public static Vector CalulatePosFix(Vector infix) throws Exception {
if (!Parentesis.Verify(infix)) {
throw new Exception(Parentesis.GetError(infix));
}
Stack s = new Stack();
Vector strPosFix = new Vector();
for (int i = 0; i < infix.size(); i++) {//David
Object elem = infix.get(i);
// parametros das funcoes
if (elem instanceof String && ((String) elem).equals(",")) {
//retirar todos elementos ate ao parentesis
while (!s.empty() && !((String) s.peek()).equals("(")) {
elem = (String) s.pop();
strPosFix.add(elem);
}
continue;
}
// introduzir directamente na pilha
if (elem instanceof String && ((String) elem).equalsIgnoreCase("(")) {
s.push(elem);
} //retirar da pilha todos operadores ate encontrar o (
else if (elem instanceof String && ((String) elem).equalsIgnoreCase(")")) {
while (!s.empty()) {
elem = (String) s.pop();
if (elem instanceof String && ((String) elem).equalsIgnoreCase("(")) {
break;
}
strPosFix.add(elem);;
}
} // se for um operador
else if (calculator.IsCalculus(elem)) {
int prio = calculator.GetPriority(elem);
//retirar todos operadores com maior prioridade
while (!s.empty() && calculator.GetPriority((String) s.peek()) >= prio) {
strPosFix.add(s.pop());
}
s.push(elem);
} else {
strPosFix.add(elem);;
}
}// fim do iterador
while (!s.empty()) {
strPosFix.add(s.pop());
}
return strPosFix;
}
//------------------------------------------------------------------------------
// Executa o calculo
public static Object CalulateValue(Vector expr) throws Exception {
Vector exprPostFix = CalulatePosFix(expr);
// se a expressao for vazia
// if( str.length() == 0) return expr;
//IteratorString it = new IteratorString(str);
Stack result = new Stack();
Vector params = new Vector();
Object elem;
for (int i = 0; i < exprPostFix.size(); i++) {
// se for um calculo
elem = exprPostFix.get(i);
if (calculator.IsCalculus(elem)) {
// retirar os parametros do calculo
params.clear();
for (int index = 0; index < calculator.GetNumParameters(elem); index++) {
//verificar se existem parametros
if (result.empty()) {
throw new Exception(" ERRO 011:\nNO NÚMERO DE PARÁMETROS NO SÍMBOLO :" + elem);
}
//adicionar no inicio
params.add(0, result.pop());
}
//adicionar o resultado
result.push(calculator.Calculate(elem, params));
} else // se for um valor
{
result.push(elem);
}
}
if (result.size() == 1) {
return result.pop();
} else {
throw new Exception("A EXPRESSÃO ESTÁ MAL CONSTRUÍDA");
//throw new Exception(" ERRO 011:\nA EXPRESSÃO [" + expr + "] ESTÁ MAL CONSTRUÍDA");
}
}
}