martes, 15 de noviembre de 2016

Parseador Java

/*********************************************************************************
 *Clase que Evalua una expresión matemática.                                         *
 *Para Evaluar  se debe crear un objeto (Obj) de tipo Parseador.                     *
 *Para Evaluar una expresion  se escribe Obj.evaluar (Expr).                         *
 *La función devuelve un String con Expr en notación postfija, además                *
 *el programa también guarda de manera automática la última expresión evaluada.      *
 *Para evaluar el número x en la expresión se utilizar Obj.f(x) para evaluar         *
 *en la última expresión o se puede pasar una expresión en notación postfija         *
 *escribiendo Obj.f(exprEnPostfija, x).                                                 *
 ********************************************************************************/

//By Psehgaft

import java.util.*;

public class Evaluador{

    private String ultimaParseada;

    public Evaluador(){
        ultimaParseada="0";
    }
    public String evaluar(String expresion) throws SintaxException{
        Stack PilaNumeros=new Stack();
        Stack PilaOperadores= new Stack();
        String expr=quitaEspacios(expresion.toLowerCase());
        String fragmento;
        int pos=0, tamano=0;
        byte cont=1;

        final String funciones[]={"1 2 3 4 5 6 7 8 9 0 ( ) x e + - * / ^ %",
                            "pi",
                            "ln(",
                            "log( abs( sen( sin( cos( tan( sec( csc( cot( sgn(",
                            "rnd() asen( asin( acos( atan( asec( acsc( acot( senh( sinh( cosh( tanh( sech( csch( coth( sqrt(",
                            "round( asenh( acosh( atanh( asech( acsch( acoth("};

        final String parentesis="( ln log abs sen sin cos tan sec csc cot sgn asen asin acos atan asec acsc acot senh sinh cosh tanh sech csch coth sqrt round asenh asinh acosh atanh asech acsch acoth";
uir cualquier cosa menos (+ * / ^ %)

        byte anterior=0;

        try{
            while(pos<expr.length>
                tamano=0;
                cont=1;
                while (tamano==0 && cont
                    if(pos+cont
                        tamano=cont;
                    }
                    cont++;
                }

                if (tamano==0){
                    ultimaParseada="0";
                    throw new SintaxException("Error en la expresión");
                }else if(tamano==1){
                                    if(isNum(expr.substring(pos,pos+tamano))){
                        if(anterior==1 || anterior==4){
                            sacaOperadores(PilaNumeros, PilaOperadores, "*");
                        }
                        fragmento="";
                                            do{
                            fragmento=fragmento+expr.charAt(pos);
                            pos++;
                        }while(pos<expr.length expr.charat="">
                        try{
                            Double.valueOf(fragmento);
                        }catch(NumberFormatException e){
                            ultimaParseada="0";
                            throw new SintaxException("Número mal digitado");
                        }
                        PilaNumeros.push(new String(fragmento));
                        anterior=1;
                        pos--;
                    }else if (expr.charAt(pos)=='x' || expr.charAt(pos)=='e'){
                        if(anterior==1 || anterior==4){
                            sacaOperadores(PilaNumeros, PilaOperadores, "*");
                        }
                        PilaNumeros.push(expr.substring(pos,pos+tamano));
                        anterior=1;
                    }else if (expr.charAt(pos)=='+' || expr.charAt(pos)=='*' || expr.charAt(pos)=='/' || expr.charAt(pos)=='%'){
                        if (anterior==0 || anterior==2 || anterior==3)
                            throw new SintaxException("Error en la expresión");

                        sacaOperadores(PilaNumeros, PilaOperadores, expr.substring(pos,pos+tamano));
                        anterior=2;
                    }else if (expr.charAt(pos)=='^'){
                        if (anterior==0 || anterior==2 || anterior==3)
                            throw new SintaxException("Error en la expresión");

                        PilaOperadores.push(new String("^"));
                        anterior=2;
                    }else if (expr.charAt(pos)=='-'){
                        if(anterior==0 || anterior==2 || anterior==3){
                            PilaNumeros.push(new String("-1"));
                            sacaOperadores(PilaNumeros, PilaOperadores, "*");
                        }else{
                            sacaOperadores(PilaNumeros, PilaOperadores, "-");
                        }
                        anterior=2;
                    }else if (expr.charAt(pos)=='('){
                        if (anterior==1 || anterior == 4){
                            sacaOperadores(PilaNumeros, PilaOperadores, "*");
                        }
                        PilaOperadores.push(new String("("));
                        anterior=3;
                    }else if (expr.charAt(pos)==')'){
                        if(anterior!=1 && anterior !=4)
                            throw new SintaxException("Error en la expresión");

                        while(!PilaOperadores.empty() && parentesis.indexOf(((String)PilaOperadores.peek()))==-1){
                            sacaOperador(PilaNumeros, PilaOperadores);
                        }
                        if(!((String)PilaOperadores.peek()).equals("(")){
                            PilaNumeros.push(new String(((String)PilaNumeros.pop()) + " " + ((String)PilaOperadores.pop())));
                        }else{
                            PilaOperadores.pop();
                        }
                        anterior=4;
                    }
                }else if(tamano>=2){
                    fragmento=expr.substring(pos,pos+tamano);
                    if(fragmento.equals("pi")){
                        if(anterior==1 || anterior==4){
                            sacaOperadores(PilaNumeros, PilaOperadores, "*");
                        }
                        PilaNumeros.push(fragmento);
                        anterior=1;
                    }else if(fragmento.equals("rnd()")){
                        if(anterior==1 || anterior==4){
                            sacaOperadores(PilaNumeros, PilaOperadores, "*");
                        }
                        PilaNumeros.push("rnd");
                        anterior=1;
                    }else{
                        if (anterior==1 || anterior == 4){
                            sacaOperadores(PilaNumeros, PilaOperadores, "*");
                        }
                        PilaOperadores.push(fragmento.substring(0,fragmento.length()-1));
                        anterior=3;
                    }
                }
                pos+=tamano;
            }
            while(!PilaOperadores.empty()){
                if(parentesis.indexOf((String)PilaOperadores.peek())!=-1)
                    throw new SintaxException("Hay un paréntesis de más");
                sacaOperador(PilaNumeros, PilaOperadores);
            }
            }catch(EmptyStackException e){
            ultimaParseada="0";
            throw new SintaxException("Expresión mal digitada");
        }

        ultimaParseada=((String)PilaNumeros.pop());

        if(!PilaNumeros.empty()){
            ultimaParseada="0";
            throw new SintaxException("Error en la expresión");
        }

        return ultimaParseada;

    public double f(String expresionParseada, double x) throws ArithmeticException{
        Stack pilaEvaluar = new Stack();
        double a, b;
        StringTokenizer tokens=new StringTokenizer(expresionParseada);
        String tokenActual;

        try{
            while(tokens.hasMoreTokens()){
                tokenActual=tokens.nextToken();

                if(tokenActual.equals("+")){//suma
                    b=((Double)pilaEvaluar.pop()).doubleValue();
                    a=((Double)pilaEvaluar.pop()).doubleValue();
                    pilaEvaluar.push(new Double(a+b));
                }else if(tokenActual.equals("-")){//resta
                    b=((Double)pilaEvaluar.pop()).doubleValue();
                    a=((Double)pilaEvaluar.pop()).doubleValue();
                    pilaEvaluar.push(new Double(a-b));
                }else if(tokenActual.equals("*")){//Multiplicación
                    b=((Double)pilaEvaluar.pop()).doubleValue();
                    a=((Double)pilaEvaluar.pop()).doubleValue();
                    pilaEvaluar.push(new Double(a*b));
                }else if(tokenActual.equals("/")){//División
                    b=((Double)pilaEvaluar.pop()).doubleValue();
                    a=((Double)pilaEvaluar.pop()).doubleValue();
                    pilaEvaluar.push(new Double(a/b));
                    pilaEvaluar.push(new Double(Long.toString(Math.round(a))));
                }else{//si es otra cosa tiene que ser un número, simplemente se mete en la pila
                    pilaEvaluar.push(Double.valueOf(tokenActual));
                }
            }
        }catch(EmptyStackException e){
            throw new ArithmeticException("Expresión mal parseada");
        }catch(NumberFormatException e){
            throw new ArithmeticException("Expresión mal digitada");
        }catch(ArithmeticException e){
            throw new ArithmeticException("Valor no real en la expresión");
        }

        a=((Double)pilaEvaluar.pop()).doubleValue();

        if(!pilaEvaluar.empty())
            throw new ArithmeticException("Expresión mal digitada");  
        return a;
    }


    public double f(double x) throws ArithmeticException{
        try{
            return f(ultimaParseada,x);
        }catch(ArithmeticException e){
            throw e;
        }
    }
    private void sacaOperador(Stack Numeros, Stack operadores) throws EmptyStackException{
        String operador, a, b;
        final String operadoresBinarios="+ - * / ^ %";

        try{
            operador=(String)operadores.pop();

            if(operadoresBinarios.indexOf(operador)!=-1){
                b=(String)Numeros.pop();
                a=(String)Numeros.pop();
                Numeros.push(new String(a+" "+b+" "+operador));
            }else{
                a=(String)Numeros.pop();
                Numeros.push(new String(a+" "+operador));
            }
        }catch(EmptyStackException e){
            throw e;
        }
    }

    private void sacaOperadores(Stack PilaNumeros, Stack PilaOperadores, String operador){
        final String parentesis="( ln log abs sen sin cos tan sec csc cot sgn asen asin acos atan asec acsc acot senh sinh cosh tanh sech csch coth sqrt round asenh asinh acosh atanh asech acsch acoth";


        while(!PilaOperadores.empty() && parentesis.indexOf((String)PilaOperadores.peek())==-1 && ((String)PilaOperadores.peek()).length()==1 && prioridad(((String)PilaOperadores.peek()).charAt(0))>=prioridad(operador.charAt(0))){
            sacaOperador(PilaNumeros, PilaOperadores);
        }
        PilaOperadores.push(operador);
    }

    private int prioridad(char s) {
        if (s=='+' || s=='-') //Si es una suma o una resta devuelve cero
            return 0;
        else if (s=='*' || s=='/' || s=='%') //Si es multiplicación, división o resto de división devuelve uno
            return 1;
        else if (s=='^')//Si es potencia devuelve dos
            return 2;

        return -1; //Si no fue nada de lo anterior devuelve -1
    }

    private boolean isNum(String s) {
        if (s.compareTo("0")>=0 && s.compareTo("9")
            return true;
        else
            return false;
    }

    private String quitaEspacios(String polinomio){
        String unspacedString = "";  

        for(int i = 0; i < polinomio.length(); i++){  
            if(polinomio.charAt(i) != ' ') .
                unspacedString += polinomio.charAt(i);
        }

        return unspacedString;
    }

    private double sgn(double a){
        if(a<0)
            return -1;
        else if(a>0)
            return 1;
        else
            return 0;
    }

    private class SintaxException extends ArithmeticException{
        public SintaxException(){
            super("Error de sintaxis en el polinomio");
        }

        public SintaxException(String e){
            super(e);
        }
    }

</expr.length>

</expr.length>

No hay comentarios:

Publicar un comentario