package procesador;

import java.util.Arrays;
import java.util.EmptyStackException;
import java.util.Stack;
import tslib.TS_Gestor.DescripcionAtributo;
import tslib.TS_Gestor.Tabla;
import tslib.TS_Gestor.TipoDatoAtributo;

public class ASem {

    public static boolean tsGlobal;
    private static boolean zonaDeclaracion;
    private static Integer despGlobal, despLocal;
    private static Integer numEtiq;

    //static Stack<ItemPila> stackP = ASint.stackP;
    static Stack<ItemPila> stackAux = ASint.stackAux;

    public static boolean debug = false;

    public static void iniciarASem() {
        tsGlobal = false;
        zonaDeclaracion = false;
        despGlobal = 0;
        despLocal = 0;
        numEtiq = 0;
        iniciarTS();
    }

    private static void iniciarTS() {
        if (debug) {
            Procesador.gestorTS.activarDebug();
        }
        Procesador.gestorTS.createAtributo("desplazamiento", DescripcionAtributo.DIR, TipoDatoAtributo.ENTERO);
        Procesador.gestorTS.createAtributo("etiqueta", DescripcionAtributo.ETIQUETA, TipoDatoAtributo.CADENA);
        Procesador.gestorTS.createAtributo("pasoParametros", DescripcionAtributo.MODO_PARAM, TipoDatoAtributo.LISTA);
        Procesador.gestorTS.createAtributo("tipoParametros", DescripcionAtributo.TIPO_PARAM, TipoDatoAtributo.LISTA);
        Procesador.gestorTS.createAtributo("tipoRetorno", DescripcionAtributo.TIPO_RET, TipoDatoAtributo.CADENA);
        Procesador.gestorTS.createAtributo("numParametro", DescripcionAtributo.NUM_PARAM, TipoDatoAtributo.ENTERO);
        Procesador.gestorTS.createAtributo("modoParametro", DescripcionAtributo.PARAM, TipoDatoAtributo.ENTERO);
    }

    private static void destroyTable(Tabla tabla) {
        Procesador.gestorTS.write(tabla);
        Procesador.gestorTS.destroy(tabla);
    }

    private static String generarEtiqueta() {
        return ("Etiqueta" + (numEtiq++));
    }

    public static void activarDebug() {
        debug = true;
    }

    public static void desactivarDebug() {
        debug = false;
    }

    public static boolean zonaDec() {
        return zonaDeclaracion;
    }

    public static void acc1_1() {
        // P -> acc1_ 1 D R acc1_2
        // Al inicio del programa

        Procesador.gestorTS.createTSGlobal();
        tsGlobal = true;
        despGlobal = 0;
        zonaDeclaracion = true;
    }

    public static void acc1_2() {
        // P -> D R
        // Despues de "D R"
        Atributos atrR = peekAuxAttributes(0); //R
        Atributos atrD = peekAuxAttributes(1); //D
        Atributos atrP = peekAuxAttributes(2); //P

        if (atrR.getProgramCount() > 1) {
            GestorError.writeError("semántico", "Solo debería haber un Programa Principal (PROGRAM)");
        } else if (atrR.getProgramCount() < 1) {
            GestorError.writeError("semántico", "Debe haber un Programa Principal (PROGRAM)");
        }
        destroyTable(Tabla.GLOBAL);
        popAuxLast(2);
    }

    public static void acc2() {
        // R -> PP R1
        Atributos atrR1 = peekAuxAttributes(0); //R1
        Atributos atrPP = peekAuxAttributes(1); //PP
        Atributos atrR = peekAuxAttributes(2); //R

        atrR.setProgramCount(atrR1.getProgramCount() + 1);

        popAuxLast(2);

    }

    public static void acc3() {
        // R -> PR R1
        Atributos atrR1 = peekAuxAttributes(0); //R1
        Atributos atrPR = peekAuxAttributes(1); //PR
        Atributos atrR = peekAuxAttributes(2); //R

        atrR.setProgramCount(atrR1.getProgramCount());

        popAuxLast(2);

    }

    public static void acc4() {
        // R -> PF R
        Atributos atrR1 = peekAuxAttributes(0); //R1
        Atributos atrPF = peekAuxAttributes(1); //PF
        Atributos atrR = peekAuxAttributes(2);//R

        atrR.setProgramCount(atrR1.getProgramCount());

        popAuxLast(2);

    }

    public static void acc5() {
        // R -> λ
        Atributos atrR = peekAuxAttributes(0); //R

        atrR.setProgramCount(0);

    }

    public static void acc6_1() {
        // PP -> program id ; D bloque ;
        // Después de "program id"

        Atributos atrId = peekAuxAttributes(0); //id
        //program
        Atributos atrPP = peekAuxAttributes(2); //PP

        int idPos = atrId.getPos();

        Procesador.gestorTS.setTipo(idPos, "procedimiento");    //dado que a la tabla no se puede añadir la palabra programa, se le llamara procedimineto y tendra etiqueta personalizada
        Procesador.gestorTS.setValorAtributoEnt(idPos, "numParametro", 0);
        Procesador.gestorTS.setValorAtributoCad(idPos, "tipoRetorno", "vacío");

        Procesador.gestorTS.setValorAtributoCad(idPos, "etiqueta", "main");
        Procesador.gestorTS.createTSLocal();
        tsGlobal = false;
        despLocal = 0;

    }

    public static void acc6_2() {
        // PP -> program id ; D bloque ;
        // Después de "D"
        zonaDeclaracion = false;

    }

    public static void acc6_3() {
        // PP -> program id ; D bloque ;
        // Después de "bloque ;"

        //;
        Atributos atrBloque = peekAuxAttributes(1); //bloque
        // D ; id program
        Atributos atrPP = peekAuxAttributes(6); //PP

        if (atrBloque.getTipo().equals("tipo_error")) {
            GestorError.writeError("semántico", "Error detectado en el desarrollo del cuerpo del Programa principal");
        }
        if (!atrBloque.getRet().equals("tipo_ok") && !atrBloque.getRet().equals("vacío")) {
            GestorError.writeError("semántico", "Programa Principal con instrucción de retorno no vacío");
        }
        if (atrBloque.getExit() > 0) {
            GestorError.writeError("semántico", "EXIT fuera de bucle detectado en Programa Principal");
        }

        destroyTable(Tabla.LOCAL);
        tsGlobal = true;
        zonaDeclaracion = true;

        popAuxLast(6);

    }

    public static void acc7_1() {
        // PR -> procedure id A ; D bloque ;
        // Después de "procedure id"

        Procesador.gestorTS.createTSLocal();
        tsGlobal = false;
        despLocal = 0;
    }

    public static void acc7_2() {
        // PR -> procedure id A ; D bloque ;
        // Después de "A ;"

        // ;
        Atributos atrA = peekAuxAttributes(1); // A
        Atributos atrId = peekAuxAttributes(2); // id 
        //procedure
        Atributos atrPR = peekAuxAttributes(4); // PR

        int idPos = atrId.getPos();
        Procesador.gestorTS.setTipo(idPos, "procedimiento");
        Procesador.gestorTS.setValorAtributoCad(idPos, "tipoRetorno", "vacío");

        if (atrA.getLong() > 0) {
            String[] tipos = atrA.getTipo().split(" ");
            String[] parametros = atrA.getReferencia().split(" ");
            Procesador.gestorTS.setValorAtributoLista(idPos, "tipoParametros", tipos);
            Procesador.gestorTS.setValorAtributoLista(idPos, "pasoParametros", parametros);
            Procesador.gestorTS.setValorAtributoEnt(idPos, "numParametro", atrA.getLong());
        } else {
            Procesador.gestorTS.setValorAtributoEnt(idPos, "numParametro", 0);
        }

        Procesador.gestorTS.setValorAtributoCad(idPos, "etiqueta", generarEtiqueta());
    }

    public static void acc7_3() {
        // PR -> procedure id A ; D bloque ;
        // Después de "D"
        zonaDeclaracion = false;
    }

    public static void acc7_4() {
        // PR -> procedure id A ; D bloque ;
        // Después de "bloque ;"

        // ;
        Atributos atrBloque = peekAuxAttributes(1); // bloque
        // D ; A id procedure
        Atributos atrPR = peekAuxAttributes(7); // PR

        if (atrBloque.getTipo().equals("tipo_error")) {
            GestorError.writeError("semántico", "Error detectado en el desarrollo del cuerpo del PROCEDURE");
        }
        if (!atrBloque.getRet().equals("tipo_ok") && !atrBloque.getRet().equals("vacío") && !atrBloque.getRet().equals("")) {
            GestorError.writeError("semántico", "PROCEDURE con instrucción de retorno no vacío");
        }
        if (atrBloque.getExit() > 0) {
            GestorError.writeError("semántico", "EXIT fuera de bucle detectado en PROCEDURE");
        }

        destroyTable(Tabla.LOCAL);
        tsGlobal = true;
        zonaDeclaracion = true;

        popAuxLast(7);
    }

    public static void acc8_1() {
        // PF -> function id A : T ; D bloque ;
        // Después de "function id"

        Procesador.gestorTS.createTSLocal();
        tsGlobal = false;
        despLocal = 0;
    }

    public static void acc8_2() {
        // PF -> function id A : T ; D bloque ;
        // Después de " A : T ;"

        // ;
        Atributos atrT = peekAuxAttributes(1); // T
        // :
        Atributos atrA = peekAuxAttributes(3);// A
        Atributos atrId = peekAuxAttributes(4);// id
        // function
        Atributos atrPF = peekAuxAttributes(6); // PF

        int idPos = atrId.getPos();
        Procesador.gestorTS.setTipo(idPos, "función");
        Procesador.gestorTS.setValorAtributoCad(idPos, "tipoRetorno", atrT.getTipo());

        if (atrA.getLong() > 0) {
            String[] tipos = atrA.getTipo().split(" ");
            String[] parametros = atrA.getReferencia().split(" ");
            Procesador.gestorTS.setValorAtributoLista(idPos, "tipoParametros", tipos);
            Procesador.gestorTS.setValorAtributoLista(idPos, "pasoParametros", parametros);
            Procesador.gestorTS.setValorAtributoEnt(idPos, "numParametro", atrA.getLong());
        } else {
            Procesador.gestorTS.setValorAtributoEnt(idPos, "numParametro", 0);
        }

        Procesador.gestorTS.setValorAtributoCad(idPos, "etiqueta", generarEtiqueta());
    }

    public static void acc8_3() {
        // PF -> function id A : T ; D bloque ;
        // Después de "D"
        zonaDeclaracion = false;
    }

    public static void acc8_4() {
        // PF -> function id A : T ; D bloque ;
        // después de "bloque ;"

        // ;
        Atributos atrBloque = peekAuxAttributes(1); // bloque
        // D ; 
        Atributos atrT = peekAuxAttributes(4); //T
        //  : A id function
        Atributos atrPF = peekAuxAttributes(9);// PF

        if (atrBloque.getTipo().equals("tipo_error")) {
            GestorError.writeError("semántico", "Ha sucedido un error en la función");
        }
        if (!atrBloque.getRet().equals("tipo_ok") && !atrBloque.getRet().equals(atrT.getTipo())) {
            GestorError.writeError("semántico", "Función con retorno no válido");
        }
        if (atrBloque.getExit() > 0) {
            GestorError.writeError("semántico", "EXIT no puede situarse fuera del bucle");
        }

        destroyTable(Tabla.LOCAL);
        tsGlobal = true;
        zonaDeclaracion = true;

        popAuxLast(9);
    }

    public static void acc9_1() {
        // D → var id : T ; DD
        // después de "var id : T ;"

        // ;
        Atributos atrT = peekAuxAttributes(1); // T
        // :
        Atributos atrId = peekAuxAttributes(3);// id
        // var
        Atributos atrD = peekAuxAttributes(5); // D

        int idPos = atrId.getPos();
        Procesador.gestorTS.setTipo(idPos, atrT.getTipo());

        if (tsGlobal) {
            Procesador.gestorTS.setValorAtributoEnt(idPos, "desplazamiento", despGlobal);
            despGlobal += atrT.getAncho();
        } else {
            Procesador.gestorTS.setValorAtributoEnt(idPos, "desplazamiento", despLocal);
            despLocal += atrT.getAncho();
        }
    }

    public static void acc9_2() {
        // D → var id : T ; DD
        // después de "DD"
        // (sin acción)
        popAuxLast(6);
    }

    public static void acc10() {
        // D → λ (sin acción)
    }

    public static void acc11_1() {
        // DD → id : T ; DD
        // Después de "id : T ;"

        // ;
        Atributos atrT = peekAuxAttributes(1); // T
        // :
        Atributos atrId = peekAuxAttributes(3); // id
        Atributos atrDD = peekAuxAttributes(4); // DD

        int idPos = atrId.getPos();
        Procesador.gestorTS.setTipo(idPos, atrT.getTipo());

        if (tsGlobal) {
            Procesador.gestorTS.setValorAtributoEnt(idPos, "desplazamiento", despGlobal);
            despGlobal += atrT.getAncho();
        } else {
            Procesador.gestorTS.setValorAtributoEnt(idPos, "desplazamiento", despLocal);
            despLocal += atrT.getAncho();
        }
    }

    public static void acc11_2() {
        // DD → id : T ; DD
        // Después de "DD"
        // (sin acción)

        popAuxLast(5);
    }

    public static void acc12() {
        // DD → λ (sin acción)
    }

    public static void acc13() {
        // T → boolean

        //boolean
        Atributos atrT = peekAuxAttributes(1); // T

        atrT.setTipo("lógico");
        atrT.setAncho(1);

        popAuxLast(1);
    }

    public static void acc14() {
        // T → integer

        //integer
        Atributos atrT = peekAuxAttributes(1); // T

        atrT.setTipo("entero");
        atrT.setAncho(1);

        popAuxLast(1);
    }

    public static void acc15() {
        // T → string

        //string
        Atributos atrT = peekAuxAttributes(1); // T

        atrT.setTipo("cadena");
        atrT.setAncho(64);

        popAuxLast(1);
    }

    public static void acc16_1() {
        // A → ( X id : T AA )
        // Después de "( X id : T"

        Atributos atrT = peekAuxAttributes(0); // T
        // :
        Atributos atrId = peekAuxAttributes(2);// id
        Atributos atrX = peekAuxAttributes(3);// X
        // (
        Atributos atrA = peekAuxAttributes(5);// A

        int idPos = atrId.getPos();

        Procesador.gestorTS.setTipo(idPos, atrT.getTipo());
        Procesador.gestorTS.setValorAtributoEnt(idPos, "desplazamiento", despLocal);

        if (atrX.getReferencia().equals("referencia")) {
            despLocal += 1;
            Procesador.gestorTS.setValorAtributoEnt(idPos, "modoParametro", 1);
        } else if (atrX.getReferencia().equals("valor")) {
            despLocal += atrT.getAncho();
            Procesador.gestorTS.setValorAtributoEnt(idPos, "modoParametro", 0);
        }

    }

    public static void acc16_2() {
        // A → ( X id : T AA )
        // Después de "AA )"

        // )
        Atributos atrAA = peekAuxAttributes(1); // AA
        Atributos atrT = peekAuxAttributes(2); // T
        //:
        Atributos atrID = peekAuxAttributes(4); //id
        Atributos atrX = peekAuxAttributes(5); // X
        //(
        Atributos atrA = peekAuxAttributes(7); // A

        if (atrAA.getTipo().equals("vacío")) {
            atrA.setTipo(atrT.getTipo());
            atrA.setReferencia(atrX.getReferencia());
            atrA.setLong(1);
        } else {
            atrA.setTipo(atrT.getTipo() + " " + atrAA.getTipo());
            atrA.setReferencia(atrX.getReferencia() + " " + atrAA.getReferencia());
            atrA.setLong(atrAA.getLong() + 1);
        }

        popAuxLast(7);
    }

    public static void acc17() {
        // A → λ
        Atributos atrA = peekAuxAttributes(0);// A

        atrA.setTipo("vacío");
        atrA.setLong(0);
        atrA.setReferencia("");
    }

    public static void acc18_1() {
        // AA → ; X id : T AA1
        // Después de "; X id : T"

        Atributos atrT = peekAuxAttributes(0); // T
        // :
        Atributos atrId = peekAuxAttributes(2); // id
        Atributos atrX = peekAuxAttributes(3); // X
        // ;
        Atributos atrAA = peekAuxAttributes(5); // AA

        int idPos = atrId.getPos();
        Procesador.gestorTS.setTipo(idPos, atrT.getTipo());
        Procesador.gestorTS.setValorAtributoEnt(idPos, "desplazamiento", despLocal);

        if (atrX.getReferencia().equals("referencia")) {
            despLocal += 1;
            Procesador.gestorTS.setValorAtributoEnt(idPos, "modoParametro", 1);
        } else if (atrX.getReferencia().equals("valor")) {
            despLocal += atrT.getAncho();
            Procesador.gestorTS.setValorAtributoEnt(idPos, "modoParametro", 0);
        }
    }

    public static void acc18_2() {
        // AA -> ; X id : T AA1
        // Después de "AA1"
        Atributos atrAA1 = peekAuxAttributes(0); // AA1
        Atributos atrT = peekAuxAttributes(1); // T
        //:
        Atributos atrID = peekAuxAttributes(3); // id
        Atributos atrX = peekAuxAttributes(4); // X
        // ;
        Atributos atrAA = peekAuxAttributes(6); // AA

        if (atrAA1.getTipo().equals("vacío")) {
            atrAA.setTipo(atrT.getTipo());
            atrAA.setReferencia(atrX.getReferencia());
            atrAA.setLong(1);
        } else {
            atrAA.setTipo(atrT.getTipo() + " " + atrAA1.getTipo());
            atrAA.setReferencia(atrX.getReferencia() + " " + atrAA1.getReferencia());
            atrAA.setLong(atrAA1.getLong() + 1);
        }

        popAuxLast(6);
    }

    public static void acc19() {
        // AA → λ
        Atributos atrAA = peekAuxAttributes(0); // AA

        atrAA.setTipo("vacío");
        atrAA.setLong(0);
        atrAA.setReferencia("");
    }

    public static void acc20() {
        // X → var
        Atributos atrX = peekAuxAttributes(1); // X

        atrX.setReferencia("referencia");

        popAuxLast(1);
    }

    public static void acc21() {
        // X → λ
        Atributos atrX = peekAuxAttributes(0);// X

        atrX.setReferencia("valor");
    }

    public static void acc22() {
        // C → B C1
        Atributos atrC1 = peekAuxAttributes(0); // C1
        Atributos atrB = peekAuxAttributes(1); // B
        Atributos atrC = peekAuxAttributes(2); // C

        if (atrB.getTipo().equals("tipo_ok")) {
            atrC.setTipo(atrC1.getTipo());
        } else {
            atrC.setTipo("tipo_error");
        }

        atrC.setExit(atrB.getExit() + atrC1.getExit());

        if (atrB.getRet().equals(atrC1.getRet())) {
            atrC.setRet(atrB.getRet());
        } else if (atrB.getRet().equals("tipo_ok")) {
            atrC.setRet(atrC1.getRet());
        } else if (atrC1.getRet().equals("tipo_ok")) {
            atrC.setRet(atrB.getRet());
        } else {
            atrC.setRet("tipo_error");
        }

        popAuxLast(2);
    }

    public static void acc23() {
        // C → λ
        Atributos atrC = peekAuxAttributes(0);// C

        atrC.setTipo("tipo_ok");
        atrC.setExit(0);
        atrC.setRet("tipo_ok");
    }

    public static void acc24() {
        // Bloque → begin C end

        //end
        Atributos atrC = peekAuxAttributes(1); // C
        //begin
        Atributos atrBloque = peekAuxAttributes(3); // Bloque

        atrBloque.setTipo(atrC.getTipo());
        atrBloque.setExit(atrC.getExit());
        atrBloque.setRet(atrC.getRet());

        popAuxLast(3);
    }

    public static void acc25() {
        // B → S
        Atributos atrS = peekAuxAttributes(0);// S
        Atributos atrB = peekAuxAttributes(1); // B

        atrB.setTipo(atrS.getTipo());
        atrB.setExit(atrS.getExit());
        atrB.setRet(atrS.getRet());

        popAuxLast(1);
    }

    public static void acc26() {
        // B → if E then Bcola

        Atributos atrBcola = peekAuxAttributes(0); // Bcola
        //then
        Atributos atrE = peekAuxAttributes(2); // E
        //if
        Atributos atrB = peekAuxAttributes(4); // B

        if (atrE.getTipo().equals("lógico")) {
            atrB.setTipo(atrBcola.getTipo());
        } else {
            atrB.setTipo("tipo_error");
        }

        atrB.setExit(atrBcola.getExit());
        atrB.setRet(atrBcola.getRet());

        popAuxLast(4);
    }

    public static void acc27() {
        // Bcola → S
        Atributos atrS = peekAuxAttributes(0); // S
        Atributos atrBcola = peekAuxAttributes(1); // Bcola

        atrBcola.setTipo(atrS.getTipo());
        atrBcola.setExit(atrS.getExit());
        atrBcola.setRet(atrS.getRet());

        popAuxLast(1);
    }

    public static void acc28() {
        // Bcola → Bloque ; BlqElse
        Atributos atrBlqElse = peekAuxAttributes(0); // BlqElse
        // ;
        Atributos atrBloque = peekAuxAttributes(2); // Bloque
        Atributos atrBcola = peekAuxAttributes(3); // Bcola

        if (atrBloque.getTipo().equals("tipo_ok")) {
            atrBcola.setTipo(atrBlqElse.getTipo());
        } else {
            atrBcola.setTipo("tipo_error");
        }

        atrBcola.setExit(atrBloque.getExit() + atrBlqElse.getExit());

        if (atrBloque.getRet().equals(atrBlqElse.getRet())) {
            atrBcola.setRet(atrBloque.getRet());
        } else if (atrBloque.getRet().equals("tipo_ok")) {
            atrBcola.setRet(atrBlqElse.getRet());
        } else if (atrBlqElse.getRet().equals("tipo_ok")) {
            atrBcola.setRet(atrBloque.getRet());
        } else {
            atrBcola.setRet("tipo_error");
        }

        popAuxLast(3);
    }

    public static void acc29() {
        // BlqElse → else Bloque ;

        // ;
        Atributos atrBloque = peekAuxAttributes(1); // Bloque
        //else
        Atributos atrBlqElse = peekAuxAttributes(3); // BlqElse

        atrBlqElse.setTipo(atrBloque.getTipo());
        atrBlqElse.setExit(atrBloque.getExit());
        atrBlqElse.setRet(atrBloque.getRet());

        popAuxLast(3);
    }

    public static void acc30() {
        // BlqElse → λ
        Atributos atrBlqElse = peekAuxAttributes(0);// BlqElse
        atrBlqElse.setTipo("tipo_ok");
        atrBlqElse.setExit(0);
        atrBlqElse.setRet("tipo_ok");
    }

    public static void acc31() {
        // B → while E do Bloque ;

        //;
        Atributos atrBloque = peekAuxAttributes(1);// Bloque
        // do
        Atributos atrE = peekAuxAttributes(3); // E
        //while
        Atributos atrB = peekAuxAttributes(5); // B

        if (atrE.getTipo().equals("lógico")) {
            atrB.setTipo(atrBloque.getTipo());
        } else {
            atrB.setTipo("tipo_error");
        }

        atrB.setExit(atrBloque.getExit());
        atrB.setRet(atrBloque.getRet());

        popAuxLast(5);
    }

    public static void acc32() {
        // B → repeat C until E ;

        //;
        Atributos atrE = peekAuxAttributes(1); // E
        //until
        Atributos atrC = peekAuxAttributes(3); // C
        //repeat
        Atributos atrB = peekAuxAttributes(5); // B

        if (atrE.getTipo().equals("lógico")) {
            atrB.setTipo(atrC.getTipo());
        } else {
            atrB.setTipo("tipo_error");
        }

        atrB.setExit(atrC.getExit());
        atrB.setRet(atrC.getRet());

        popAuxLast(5);
    }

    public static void acc33() {
        // B → loop C end ;

        //;
        //end
        Atributos atrC = peekAuxAttributes(1); // C
        //loop
        Atributos atrB = peekAuxAttributes(3); // B

        if (atrC.getExit() > 1) {
            GestorError.writeError("semántico", "Dentro de un LOOP no debe haber más de un EXIT");
        } else if (atrC.getExit() < 1) {
            GestorError.writeError("semántico", "Dentro de un LOOP debe haber un EXIT");
        }

        atrB.setTipo(atrC.getTipo());
        atrB.setExit(0);
        atrB.setRet(atrC.getRet());

        popAuxLast(4);
    }

    public static void acc34() {
        // B → for id := E1 to E2 do Bloque ;

        //;
        Atributos atrBloque = peekAuxAttributes(1); // Bloque
        //do
        Atributos atrE2 = peekAuxAttributes(3); // E2
        //to
        Atributos atrE1 = peekAuxAttributes(5); // E1
        //:=
        Atributos atrId = peekAuxAttributes(7); // id
        //for
        Atributos atrB = peekAuxAttributes(9); // B

        int idPos = atrId.getPos();

        if (atrE1.getTipo().equals("entero") && atrE2.getTipo().equals("entero")
                && Procesador.gestorTS.getTipo(idPos).equals("entero")) {
            atrB.setTipo(atrBloque.getTipo());
        } else {
            atrB.setTipo("tipo_error");
        }

        atrB.setExit(atrBloque.getExit());
        atrB.setRet(atrBloque.getRet());

        popAuxLast(9);
    }

    public static void acc35() {
        // B → case E of N O end ;

        //; 
        //end
        Atributos atrO = peekAuxAttributes(2); // O
        Atributos atrN = peekAuxAttributes(3); // N
        //of
        Atributos atrE = peekAuxAttributes(5); // E
        //case
        Atributos atrB = peekAuxAttributes(7); // B

        if (atrE.getTipo().equals("entero") && atrN.getTipo().equals("tipo_ok")
                && atrO.getTipo().equals("tipo_ok")) {
            atrB.setTipo("tipo_ok");
        } else {
            atrB.setTipo("tipo_error");
        }

        atrB.setExit(atrN.getExit() + atrO.getExit());

        if (atrN.getRet().equals(atrO.getRet())) {
            atrB.setRet(atrN.getRet());
        } else if (atrN.getRet().equals("tipo_ok")) {
            atrB.setRet(atrO.getRet());
        } else if (atrO.getRet().equals("tipo_ok")) {
            atrB.setRet(atrN.getRet());
        } else {
            atrB.setRet("tipo_error");
        }

        popAuxLast(7);
    }

    public static void acc36() {
        // N → entero : Bloque ; N1

        Atributos atrN1 = peekAuxAttributes(0); // N1
        //;
        Atributos atrBloque = peekAuxAttributes(2); // Bloque
        //:
        //entero
        Atributos atrN = peekAuxAttributes(5); // N

        if (atrN1.getTipo().equals("tipo_ok")) {
            atrN.setTipo(atrBloque.getTipo());
        } else {
            atrN.setTipo("tipo_error");
        }

        atrN.setExit(atrBloque.getExit() + atrN1.getExit());

        if (atrBloque.getRet().equals(atrN1.getRet())) {
            atrN.setRet(atrBloque.getRet());
        } else if (atrBloque.getRet().equals("tipo_ok")) {
            atrN.setRet(atrN1.getRet());
        } else if (atrN1.getRet().equals("tipo_ok")) {
            atrN.setRet(atrBloque.getRet());
        } else {
            atrN.setRet("tipo_error");
        }

        popAuxLast(5);
    }

    public static void acc37() {
        // N → λ

        Atributos atrN = peekAuxAttributes(0); // N

        atrN.setTipo("tipo_ok");
        atrN.setExit(0);
        atrN.setRet("tipo_ok");
    }

    public static void acc38() {
        // O → otherwise : Bloque ;

        //;
        Atributos atrBloque = peekAuxAttributes(1); // Bloque
        //:
        //otherwise
        Atributos atrO = peekAuxAttributes(3); // O

        atrO.setTipo(atrBloque.getTipo());
        atrO.setExit(atrBloque.getExit());
        atrO.setRet(atrBloque.getRet());

        popAuxLast(4);
    }

    public static void acc39() {
        // O → λ

        Atributos atrO = peekAuxAttributes(0); // O

        atrO.setTipo("tipo_ok");
        atrO.setExit(0);
        atrO.setRet("tipo_ok");
    }

    public static void acc40() {
        // S → write LL ;

        //;
        Atributos atrLL = peekAuxAttributes(1);  // LL
        //write
        Atributos atrS = peekAuxAttributes(3); // S

        atrS.setTipo("tipo_ok");
        atrS.setExit(0);
        atrS.setRet("tipo_ok");

        if (!atrLL.getTipo().equals("vacío")) {
            String[] lista = atrLL.getTipo().split(" ");
            for (String item : lista) {
                if (!item.equals("entero") && !item.equals("cadena")) {
                    atrS.setTipo("tipo_error");
                    GestorError.writeError("semántico", "Error en los argumentos de WRITE");
                }
            }
        }

        popAuxLast(3);
    }

    public static void acc41() {
        // S → writeln LL ;

        //;
        Atributos atrLL = peekAuxAttributes(1);  // LL
        //writeln
        Atributos atrS = peekAuxAttributes(3); // S

        atrS.setTipo("tipo_ok");
        atrS.setExit(0);
        atrS.setRet("tipo_ok");

        if (!atrLL.getTipo().equals("vacío")) {
            String[] lista = atrLL.getTipo().split(" ");
            for (String item : lista) {
                if (!item.equals("entero") && !item.equals("cadena")) {
                    atrS.setTipo("tipo_error");
                    GestorError.writeError("semántico", "Error en los argumentos de WRITELN");
                    throw new RuntimeException();
                }
            }
        }

        popAuxLast(3);
    }

    public static void acc42() {
        // S → read ( V ) ;

        //;
        //)
        Atributos atrV = peekAuxAttributes(2);  // V
        //(
        //read
        Atributos atrS = peekAuxAttributes(5); // S

        atrS.setTipo("tipo_ok");
        atrS.setExit(0);
        atrS.setRet("tipo_ok");

        if (!atrV.getTipo().equals("vacío")) {
            String[] lista = atrV.getTipo().split(" ");
            for (String item : lista) {
                if (!item.equals("entero") && !item.equals("cadena")) {
                    atrS.setTipo("tipo_error");
                    GestorError.writeError("semántico", "Error en los argumentos de READ");
                }
            }
        }

        popAuxLast(5);
    }

    public static void acc43() {
        // S → id Scola

        Atributos atrScola = peekAuxAttributes(0); // Scola
        Atributos atrId = peekAuxAttributes(1); // id
        Atributos atrS = peekAuxAttributes(2); // S

        int idPos = atrId.getPos();

        atrId.setTipo(Procesador.gestorTS.getTipo(idPos));

        String idEtiq = "";
        if (atrId.getTipo().equals("procedimiento")) {
            idEtiq = Procesador.gestorTS.getValorAtributoCad(idPos, "etiqueta");
        }

        if (atrId.getTipo().equals(atrScola.getTipo()) && atrScola.getAsig() && !atrId.getTipo().equals("procedimiento")) {    //es asignacion y son iguales int-int
            atrS.setTipo("tipo_ok");
        } else if (atrId.getTipo().equals("procedimiento") && !atrScola.getAsig() && !idEtiq.equals("main")) {    //es llamada a procedimiento y no es MAIN 
            int numParam = Procesador.gestorTS.getValorAtributoEnt(idPos, "numParametro");
            if (numParam > 0) {
                String[] sColaAtributos = atrScola.getTipo().split(" ");
                String[] idAtbAtributos = Procesador.gestorTS.getValorAtributoLista(idPos, "tipoParametros");
                if (sColaAtributos.length == idAtbAtributos.length && Arrays.compare(sColaAtributos, idAtbAtributos) == 0) {
                    atrS.setTipo("tipo_ok");
                } else {
                    GestorError.writeError("semántico", "Los parámetros del PROCEDURE no coinciden" + "\n \t Se ha recibido: "
                            + Arrays.toString(sColaAtributos) + "\n \t y se esperaba: " + Arrays.toString(idAtbAtributos));
                    atrS.setTipo("tipo_error");
                }
            } else if (numParam == 0 && !atrScola.getAsig()) {
                String[] sColaAtributos = atrScola.getTipo().split(" ");

                GestorError.writeError("semántico", "Los parámetros del PROCEDURE no coinciden" + "\n \t Se ha recibido: "
                        + Arrays.toString(sColaAtributos) + "\n \t pero el PROCEDURE no tiene parámetros");
                atrS.setTipo("tipo_error");
            } else {
                atrS.setTipo("tipo_ok");
            }
        } else if (idEtiq.equals("main")) {      // llamada a programa principal
            GestorError.writeError("semántico", "No se puede realizar una llamada al programa principal");
            atrS.setTipo("tipo_error");
        } else if (atrId.getTipo().equals("procedimiento") && atrScola.getAsig()) {
            GestorError.writeError("semántico", "Se está realizando una asignación a un PROCEDURE");
            atrS.setTipo("tipo_error");
        } else if (Procesador.gestorTS.getTipo(idPos).equals("función")) {     //llamada a una funcion
            atrS.setTipo("tipo_error");
            GestorError.writeError("semántico", "Una funcíon no puede ser usada como sentencia");
        } else {
            atrS.setTipo("tipo_error");
            if (atrScola.getAsig()) {
                GestorError.writeError("semántico", "Tipos incompatibles en asignación");
            } else {
                GestorError.writeError("semántico", "Error en llamada a procedimiento");
            }
        }

        atrS.setExit(0);
        atrS.setRet("tipo_ok");

        popAuxLast(2);
    }

    public static void acc44() {
        // Scola → := E ;

        //;
        Atributos atrE = peekAuxAttributes(1);  // E
        //:=
        Atributos atrScola = peekAuxAttributes(3);  // Scola

        atrScola.setTipo(atrE.getTipo());
        atrScola.setAsig(true);

        popAuxLast(3);
    }

    public static void acc45() {
        // Scola → LL ;

        //;
        Atributos atrLL = peekAuxAttributes(1);  // LL
        Atributos atrScola = peekAuxAttributes(2);  // Scola

        atrScola.setTipo(atrLL.getTipo());
        atrScola.setLong(atrLL.getLong());
        atrScola.setAsig(false);

        popAuxLast(2);
    }

    public static void acc46() {
        // S → return Y ;

        //;
        Atributos atrY = peekAuxAttributes(1);  // Y
        //return
        Atributos atrS = peekAuxAttributes(3);  // S
        if (!atrY.getTipo().equals("tipo_error")) {
            atrS.setTipo("tipo_ok");
        } else {
            atrS.setTipo("tipo_error");
        }

        atrS.setExit(0);
        atrS.setRet(atrY.getTipo());

        popAuxLast(3);
    }

    public static void acc47() {
        // S → exit when E ;
        //;
        Atributos atrE = peekAuxAttributes(1);  // E
        //when
        //exit
        Atributos atrS = peekAuxAttributes(4);  // S

        if (atrE.getTipo().equals("lógico")) {
            atrS.setTipo("tipo_ok");
        } else {
            atrS.setTipo("tipo_error");
        }

        atrS.setExit(1);
        atrS.setRet("tipo_ok");

        popAuxLast(4);
    }

    public static void acc48() {
        // LL → ( L )

        //)
        Atributos atrL = peekAuxAttributes(1);  // L
        //(
        Atributos atrLL = peekAuxAttributes(3);  // LL

        atrLL.setTipo(atrL.getTipo());
        atrLL.setLong(atrL.getLong());

        popAuxLast(3);
    }

    public static void acc49() {
        // LL → λ
        Atributos atrLL = peekAuxAttributes(0);  // LL
        atrLL.setTipo("vacío");
        atrLL.setLong(0);
    }

    public static void acc50() {
        // L → E Q
        Atributos atrQ = peekAuxAttributes(0);  // Q
        Atributos atrE = peekAuxAttributes(1);  // E
        Atributos atrL = peekAuxAttributes(2);  // L

        if (atrQ.getTipo().equals("vacío")) {
            atrL.setTipo(atrE.getTipo());
        } else {
            atrL.setTipo(atrE.getTipo() + " " + atrQ.getTipo());
        }

        atrL.setLong(atrQ.getLong() + 1);

        popAuxLast(2);
    }

    public static void acc51() {
        // Q → , E Q1
        Atributos atrQ1 = peekAuxAttributes(0);  // Q1
        Atributos atrE = peekAuxAttributes(1);  // E
        //,
        Atributos atrQ = peekAuxAttributes(3);; // Q

        if (atrQ1.getTipo().equals("vacío")) {
            atrQ.setTipo(atrE.getTipo());
        } else {
            atrQ.setTipo(atrE.getTipo() + " " + atrQ1.getTipo());
        }

        atrQ.setLong(atrQ1.getLong() + 1);

        popAuxLast(3);
    }

    public static void acc52() {
        // Q → λ
        Atributos atrQ = peekAuxAttributes(0);  // Q
        atrQ.setTipo("vacío");
        atrQ.setLong(0);
    }

    public static void acc53() {
        // V → id W
        Atributos atrW = peekAuxAttributes(0);  // W
        Atributos atrId = peekAuxAttributes(1);  // id
        Atributos atrV = peekAuxAttributes(2); // V

        int idPos = atrId.getPos();

        if (atrW.getTipo().equals("vacío")) {
            atrV.setTipo(Procesador.gestorTS.getTipo(idPos));
        } else {
            atrV.setTipo(Procesador.gestorTS.getTipo(idPos) + " " + atrW.getTipo());
        }

        atrV.setLong(1 + atrW.getLong());

        popAuxLast(2);
    }

    public static void acc54() {
        // W → , id W1
        Atributos atrW1 = peekAuxAttributes(0);  // W1
        Atributos atrId = peekAuxAttributes(1); // id
        // ,
        Atributos atrW = peekAuxAttributes(3);  // W

        int idPos = atrId.getPos();

        if (atrW1.getTipo().equals("vacío")) {
            atrW.setTipo(Procesador.gestorTS.getTipo(idPos));
        } else {
            atrW.setTipo(Procesador.gestorTS.getTipo(idPos) + " " + atrW1.getTipo());
        }

        atrW.setLong(atrW1.getLong() + 1);

        popAuxLast(3);
    }

    public static void acc55() {
        // W → λ
        Atributos atrW = peekAuxAttributes(0);  // W
        atrW.setTipo("vacío");
        atrW.setLong(0);
    }

    public static void acc56() {
        // Y → E
        Atributos atrE = peekAuxAttributes(0);  // E
        Atributos atrY = peekAuxAttributes(1);  // Y

        atrY.setTipo(atrE.getTipo());

        popAuxLast(1);
    }

    public static void acc57() {
        // Y → λ
        Atributos atrY = peekAuxAttributes(0);  // Y
        atrY.setTipo("vacío");
    }

    public static void acc58() {
        // E → F Eprima
        Atributos atrEprima = peekAuxAttributes(0);  // Eprima
        Atributos atrF = peekAuxAttributes(1);  // F
        Atributos atrE = peekAuxAttributes(2);  // E

        if (atrEprima.getTipo().equals("vacío")) {
            atrE.setTipo(atrF.getTipo());
        } else if (atrF.getTipo().equals("lógico") && atrEprima.getTipo().equals("lógico")) {
            atrE.setTipo("lógico");
        } else {
            atrE.setTipo("tipo_error");
            GestorError.writeError("semántico", "Error dentro de la expresión");
        }

        popAuxLast(2);
    }

    public static void acc59() {
        // Eprima → or F Eprima
        Atributos atrEprima1 = peekAuxAttributes(0);  // Eprima1
        Atributos atrF = peekAuxAttributes(1);  // F
        //or
        Atributos atrEprima = peekAuxAttributes(3);  // Eprima

        if (atrEprima1.getTipo().equals("vacío")) {
            if (atrF.getTipo().equals("lógico")) {
                atrEprima.setTipo("lógico");
            } else {
                atrEprima.setTipo("tipo_error");
            }
        } else if (atrF.getTipo().equals("lógico") && atrEprima1.getTipo().equals("lógico")) {
            atrEprima.setTipo("lógico");
        } else {
            atrEprima.setTipo("tipo_error");
        }

        popAuxLast(3);
    }

    public static void acc60() {
        // Eprima → xor F Eprima
        Atributos atrEprima1 = peekAuxAttributes(0);  // Eprima1
        Atributos atrF = peekAuxAttributes(1);  // F
        //xor
        Atributos atrEprima = peekAuxAttributes(3);  // Eprima

        if (atrEprima1.getTipo().equals("vacío")) {
            if (atrF.getTipo().equals("lógico")) {
                atrEprima.setTipo("lógico");
            } else {
                atrEprima.setTipo("tipo_error");
            }
        } else if (atrF.getTipo().equals("lógico") && atrEprima1.getTipo().equals("lógico")) {
            atrEprima.setTipo("lógico");
        } else {
            atrEprima.setTipo("tipo_error");
        }

        popAuxLast(3);
    }

    public static void acc61() {
        // Eprima → λ
        Atributos atrEprima = peekAuxAttributes(0);  // Eprima
        atrEprima.setTipo("vacío");
    }

    public static void acc62() {
        // F → G Fprima
        Atributos atrFprima = peekAuxAttributes(0); // Fprima
        Atributos atrG = peekAuxAttributes(1);  // G
        Atributos atrF = peekAuxAttributes(2);  // F

        if (atrFprima.getTipo().equals("vacío")) {
            atrF.setTipo(atrG.getTipo());
        } else if (atrG.getTipo().equals("lógico") && atrFprima.getTipo().equals("lógico")) {
            atrF.setTipo("lógico");
        } else {
            atrF.setTipo("tipo_error");
        }

        popAuxLast(2);
    }

    public static void acc63() {
        // Fprima → and G Fprima
        Atributos atrFprima1 = peekAuxAttributes(0);  // Fprima1
        Atributos atrG = peekAuxAttributes(1);  // G
        //and
        Atributos atrFprima = peekAuxAttributes(3); // Fprima

        if (atrFprima1.getTipo().equals("vacío")) {
            if (atrG.getTipo().equals("lógico")) {
                atrFprima.setTipo("lógico");
            } else {
                atrFprima.setTipo("tipo_error");
            }
        } else if (atrFprima1.getTipo().equals("vacío") && atrG.getTipo().equals("lógico")) {
            atrFprima.setTipo("lógico");
        } else {
            atrFprima.setTipo("tipo_error");
        }

        popAuxLast(3);
    }

    public static void acc64() {
        // Fprima → λ
        Atributos atrFprima = peekAuxAttributes(0);  // Fprima
        atrFprima.setTipo("vacío");
    }

    public static void acc65() {
        // G → H Gprima
        Atributos atrGprima = peekAuxAttributes(0);  // Gprima
        Atributos atrH = peekAuxAttributes(1);  // H
        Atributos atrG = peekAuxAttributes(2);  // G

        if (atrGprima.getTipo().equals("vacío")) {
            atrG.setTipo(atrH.getTipo());
        } else if (atrH.getTipo().equals("entero") && atrGprima.getTipo().equals("lógico")) {
            atrG.setTipo("lógico");
        } else {
            atrG.setTipo("tipo_error");
        }

        popAuxLast(2);
    }

    public static void acc66() {
        // Gprima → = H Gprima
        Atributos atrGprima1 = peekAuxAttributes(0);  // Gprima1
        Atributos atrH = peekAuxAttributes(1);  // H
        //=
        Atributos atrGprima = peekAuxAttributes(3);  // Gprima

        if (atrGprima1.getTipo().equals("vacío")) {
            if (atrH.getTipo().equals("entero")) {
                atrGprima.setTipo("lógico");
            } else {
                atrGprima.setTipo("tipo_error");
            }
        } else if (atrGprima1.getTipo().equals("lógico") && atrH.getTipo().equals("entero")) {
            atrGprima.setTipo("lógico");
        } else {
            atrGprima.setTipo("tipo_error");
        }

        popAuxLast(3);
    }

    public static void acc67() {
        // Gprima → <> H Gprima
        Atributos atrGprima1 = peekAuxAttributes(0);  // Gprima1
        Atributos atrH = peekAuxAttributes(1);  // H
        //<>
        Atributos atrGprima = peekAuxAttributes(3);  // Gprima

        if (atrGprima1.getTipo().equals("vacío")) {
            if (atrH.getTipo().equals("entero")) {
                atrGprima.setTipo("lógico");
            } else {
                atrGprima.setTipo("tipo_error");
            }
        } else if (atrGprima1.getTipo().equals("lógico") && atrH.getTipo().equals("entero")) {
            atrGprima.setTipo("lógico");
        } else {
            atrGprima.setTipo("tipo_error");
        }

        popAuxLast(3);
    }

    public static void acc68() {
        // Gprima → > H Gprima
        Atributos atrGprima1 = peekAuxAttributes(0);  // Gprima1
        Atributos atrH = peekAuxAttributes(1);  // H
        //>
        Atributos atrGprima = peekAuxAttributes(3);  // Gprima

        if (atrGprima1.getTipo().equals("vacío")) {
            if (atrH.getTipo().equals("entero")) {
                atrGprima.setTipo("lógico");
            } else {
                atrGprima.setTipo("tipo_error");
            }
        } else if (atrGprima1.getTipo().equals("lógico") && atrH.getTipo().equals("entero")) {
            atrGprima.setTipo("lógico");
        } else {
            atrGprima.setTipo("tipo_error");
        }

        popAuxLast(3);
    }

    public static void acc69() {
        // Gprima → >= H Gprima
        Atributos atrGprima1 = peekAuxAttributes(0);  // Gprima1
        Atributos atrH = peekAuxAttributes(1);  // H
        //>=
        Atributos atrGprima = peekAuxAttributes(3);  // Gprima

        if (atrGprima1.getTipo().equals("vacío")) {
            if (atrH.getTipo().equals("entero")) {
                atrGprima.setTipo("lógico");
            } else {
                atrGprima.setTipo("tipo_error");
            }
        } else if (atrGprima1.getTipo().equals("lógico") && atrH.getTipo().equals("entero")) {
            atrGprima.setTipo("lógico");
        } else {
            atrGprima.setTipo("tipo_error");
        }

        popAuxLast(3);
    }

    public static void acc70() {
        // Gprima → < H Gprima
        Atributos atrGprima1 = peekAuxAttributes(0);  // Gprima1
        Atributos atrH = peekAuxAttributes(1);  // H
        //<
        Atributos atrGprima = peekAuxAttributes(3);  // Gprima

        if (atrGprima1.getTipo().equals("vacío")) {
            if (atrH.getTipo().equals("entero")) {
                atrGprima.setTipo("lógico");
            } else {
                atrGprima.setTipo("tipo_error");
            }
        } else if (atrGprima1.getTipo().equals("lógico") && atrH.getTipo().equals("entero")) {
            atrGprima.setTipo("lógico");
        } else {
            atrGprima.setTipo("tipo_error");
        }

        popAuxLast(3);
    }

    public static void acc71() {
        // Gprima → <= H Gprima

        Atributos atrGprima1 = peekAuxAttributes(0);  // Gprima1
        Atributos atrH = peekAuxAttributes(1);  // H
        //<=
        Atributos atrGprima = peekAuxAttributes(3);  // Gprima

        if (atrGprima1.getTipo().equals("vacío")) {
            if (atrH.getTipo().equals("entero")) {
                atrGprima.setTipo("lógico");
            } else {
                atrGprima.setTipo("tipo_error");
            }
        } else if (atrGprima1.getTipo().equals("lógico") && atrH.getTipo().equals("entero")) {
            atrGprima.setTipo("lógico");
        } else {
            atrGprima.setTipo("tipo_error");
        }

        popAuxLast(3);
    }

    public static void acc72() {
        // Gprima → λ

        Atributos atrGprima = peekAuxAttributes(0);  // Gprima

        atrGprima.setTipo("vacío");
    }

    public static void acc73() {
        // H → I Hprima
        Atributos atrHprima = peekAuxAttributes(0); // Hprima
        Atributos atrI = peekAuxAttributes(1); // I
        Atributos atrH = peekAuxAttributes(2); // H

        if (atrHprima.getTipo().equals("vacío")) {
            atrH.setTipo(atrI.getTipo());
        } else if (atrI.getTipo().equals("cadena") && atrHprima.getTipo().equals("cadena")) {
            atrH.setTipo("cadena");
        } else if (atrI.getTipo().equals("entero") && atrHprima.getTipo().equals("entero")) {
            atrH.setTipo("entero");
        } else {
            atrH.setTipo("tipo_error");
        }

        popAuxLast(2);
    }

    public static void acc74() {
        // Hprima → + I Hprima
        Atributos atrHprima1 = peekAuxAttributes(0);  // Hprima1
        Atributos atrI = peekAuxAttributes(1);  // I
        //+
        Atributos atrHprima = peekAuxAttributes(3);  // Hprima

        if (atrHprima1.getTipo().equals("vacío")) {
            if (atrI.getTipo().equals("cadena") || atrI.getTipo().equals("entero")) {
                atrHprima.setTipo(atrI.getTipo());
            } else {
                atrHprima.setTipo("tipo_error");
            }
        } else if (atrHprima1.getTipo().equals(atrI.getTipo()) && (atrI.getTipo().equals("entero") || atrI.getTipo().equals("cadena"))) {
            atrHprima.setTipo(atrI.getTipo());
        } else {
            atrHprima.setTipo("tipo_error");
        }

        popAuxLast(3);
    }

    public static void acc75() {
        // Hprima → - I Hprima
        Atributos atrHprima1 = peekAuxAttributes(0);  // Hprima1
        Atributos atrI = peekAuxAttributes(1);  // I
        //-
        Atributos atrHprima = peekAuxAttributes(3);  // Hprima

        if (atrHprima1.getTipo().equals("vacío")) {
            if (atrI.getTipo().equals("entero")) {
                atrHprima.setTipo("entero");
            } else {
                atrHprima.setTipo("tipo_error");
            }
        } else if (atrHprima1.getTipo().equals("entero") && atrI.getTipo().equals("entero")) {
            atrHprima.setTipo("entero");
        } else {
            atrHprima.setTipo("tipo_error");
        }

        popAuxLast(3);
    }

    public static void acc76() {
        // Hprima → λ
        Atributos atrHprima = peekAuxAttributes(0);  // Hprima
        atrHprima.setTipo("vacío");
    }

    public static void acc77() {
        // I → J Iprima
        Atributos atrIprima = peekAuxAttributes(0); // Iprima
        Atributos atrJ = peekAuxAttributes(1);  // J
        Atributos atrI = peekAuxAttributes(2);  // I

        if (atrIprima.getTipo().equals("vacío")) {
            atrI.setTipo(atrJ.getTipo());
        } else if (atrJ.getTipo().equals("entero") && atrIprima.getTipo().equals("entero")) {
            atrI.setTipo("entero");
        } else {
            atrI.setTipo("tipo_error");
        }

        popAuxLast(2);
    }

    public static void acc78() {
        // Iprima → * J Iprima
        Atributos atrIprima1 = peekAuxAttributes(0); // Iprima1
        Atributos atrJ = peekAuxAttributes(1);  // J
        //*
        Atributos atrIprima = peekAuxAttributes(3);  // Iprima

        if (atrIprima1.getTipo().equals("vacío")) {
            if (atrJ.getTipo().equals("entero")) {
                atrIprima.setTipo("entero");
            } else {
                atrIprima.setTipo("tipo_error");
            }
        } else if (atrIprima1.getTipo().equals("entero") && atrJ.getTipo().equals("entero")) {
            atrIprima.setTipo("entero");
        } else {
            atrIprima.setTipo("vacío");
        }

        popAuxLast(3);
    }

    public static void acc79() {
        // Iprima → / J Iprima
        Atributos atrIprima1 = peekAuxAttributes(0);  // Iprima1
        Atributos atrJ = peekAuxAttributes(1);  // J
        // /
        Atributos atrIprima = peekAuxAttributes(3);  // Iprima

        if (atrIprima1.getTipo().equals("vacío")) {
            if (atrJ.getTipo().equals("entero")) {
                atrIprima.setTipo("entero");
            } else {
                atrIprima.setTipo("tipo_error");
            }
        } else if (atrIprima1.getTipo().equals("entero") && atrJ.getTipo().equals("entero")) {
            atrIprima.setTipo("entero");
        } else {
            atrIprima.setTipo("vacío");
        }

        popAuxLast(3);
    }

    public static void acc80() {
        // Iprima → mod J Iprima
        Atributos atrIprima1 = peekAuxAttributes(0); // Iprima1
        Atributos atrJ = peekAuxAttributes(1); // J
        //mod
        Atributos atrIprima = peekAuxAttributes(3);  // Iprima

        if (atrIprima1.getTipo().equals("vacío")) {
            if (atrJ.getTipo().equals("entero")) {
                atrIprima.setTipo("entero");
            } else {
                atrIprima.setTipo("tipo_error");
            }
        } else if (atrIprima1.getTipo().equals("entero") && atrJ.getTipo().equals("entero")) {
            atrIprima.setTipo("entero");
        } else {
            atrIprima.setTipo("vacío");
        }

        popAuxLast(3);
    }

    public static void acc81() {
        // Iprima → λ
        Atributos atrIprima = peekAuxAttributes(0);  // Iprima
        atrIprima.setTipo("vacío");
    }

    public static void acc82() {
        // J → K Jprima

        Atributos atrJprima = peekAuxAttributes(0);   // Jprima
        Atributos atrK = peekAuxAttributes(1);  // K
        Atributos atrJ = peekAuxAttributes(2);  // J

        if (atrJprima.getTipo().equals("vacío")) {
            atrJ.setTipo(atrK.getTipo());
        } else if (atrK.getTipo().equals("entero") && atrJprima.getTipo().equals("entero")) {
            atrJ.setTipo("entero");
        } else {
            atrJ.setTipo("tipo_error");
        }

        popAuxLast(2);
    }

    public static void acc83() {
        // Jprima → ^ K Jprima

        Atributos atrJprima1 = peekAuxAttributes(0);  // Jprima1
        Atributos atrK = peekAuxAttributes(1);  // K
        // ^
        Atributos atrJprima = peekAuxAttributes(3); // Jprima

        if (atrJprima1.getTipo().equals("entero") || atrJprima1.getTipo().equals("vacío")) {
            if (atrK.getTipo().equals("entero")) {
                atrJprima.setTipo("entero");
            } else {
                atrJprima.setTipo("tipo_error");
            }
        } else {
            atrJprima.setTipo("tipo_error");
        }

        popAuxLast(3);
    }

    public static void acc84() {
        // Jprima → λ
        Atributos atrJprima = peekAuxAttributes(0); // Jprima
        atrJprima.setTipo("vacío");
    }

    public static void acc85() {
        // K → not K
        Atributos atrK1 = peekAuxAttributes(0);  // K1
        //not
        Atributos atrK = peekAuxAttributes(2); // K

        if (atrK1.getTipo().equals("lógico")) {
            atrK.setTipo("lógico");
        } else {
            atrK.setTipo("tipo_error");
        }

        popAuxLast(2);
    }

    public static void acc86() {
        // K → + K
        Atributos atrK1 = peekAuxAttributes(0);  // K1
        //+
        Atributos atrK = peekAuxAttributes(2); // K

        if (atrK1.getTipo().equals("entero")) {
            atrK.setTipo("entero");
        } else {
            atrK.setTipo("tipo_error");
        }

        popAuxLast(2);
    }

    public static void acc87() {
        // K → - K
        Atributos atrK1 = peekAuxAttributes(0);  // K1
        //-
        Atributos atrK = peekAuxAttributes(2); // K

        if (atrK1.getTipo().equals("entero")) {
            atrK.setTipo("entero");
        } else {
            atrK.setTipo("tipo_error");
        }

        popAuxLast(2);

    }

    public static void acc88() {
        // K → Z

        Atributos atrZ = peekAuxAttributes(0);  // Z
        Atributos atrK = peekAuxAttributes(1); // K

        atrK.setTipo(atrZ.getTipo());

        popAuxLast(1);
    }

    public static void acc89() {
        // Z → ENTERO Zprima

        Atributos atrZprima = peekAuxAttributes(0);  // Zprima
        //entero
        Atributos atrZ = peekAuxAttributes(2);  // Z

        if (atrZprima.getTipo().equals("vacío")) {
            atrZ.setTipo("entero");
        } else if (atrZprima.getTipo().equals("entero")) {
            atrZ.setTipo("lógico");
        } else {
            atrZ.setTipo("tipo_error");
        }

        popAuxLast(2);
    }

    public static void acc90() {
        // Z → CADENA

        //cadena
        Atributos atrZ = peekAuxAttributes(1); // Z

        atrZ.setTipo("cadena");

        popAuxLast(1);
    }

    public static void acc91() {
        // Z → TRUE

        //true
        Atributos atrZ = peekAuxAttributes(1); // Z

        atrZ.setTipo("lógico");

        popAuxLast(1);

    }

    public static void acc92() {
        // Z → FALSE

        //false
        Atributos atrZ = peekAuxAttributes(1);  // Z

        atrZ.setTipo("lógico");

        popAuxLast(1);
    }

    public static void acc93() {
        // Z → ID LL Zprima
        Atributos atrZprima = peekAuxAttributes(0);  // Zprima
        Atributos atrLL = peekAuxAttributes(1);  // LL
        Atributos atrId = peekAuxAttributes(2);  // ID
        Atributos atrZ = peekAuxAttributes(3);  // Z

        int idPos = atrId.getPos();
        atrId.setTipo(Procesador.gestorTS.getTipo(idPos));

        if (atrId.getTipo().equals("procedimiento") && Procesador.gestorTS.getValorAtributoCad(idPos, "etiqueta").equals("main")) {
            GestorError.writeError("semántico", "Llamada ilegal al programa principal");
            atrZ.setTipo("tipo_error");
        } else if (atrId.getTipo().equals("procedure")) {
            GestorError.writeError("semántico", "No se puede realizar una llamada a un PROCEDURE aquí");
            atrZ.setTipo("tipo_error");
        } else if (atrId.getTipo().equals("función")) {
            String tipoRet = Procesador.gestorTS.getValorAtributoCad(idPos, "tipoRetorno");
            int numParam = Procesador.gestorTS.getValorAtributoEnt(idPos, "numParametro");

            if (numParam > 0) {
                String[] llAtributos = atrLL.getTipo().split(" ");
                String[] idAtbAtributos = Procesador.gestorTS.getValorAtributoLista(idPos, "tipoParametros");
                if (llAtributos.length == idAtbAtributos.length && Arrays.compare(llAtributos, idAtbAtributos) == 0) {
                    atrZ.setTipo(tipoRet);
                } else {
                    GestorError.writeError("semántico", "Los parámetros de la función no coinciden.\n \t Se ha recibido: "
                            + Arrays.toString(llAtributos) + "\n \t pero la función espera: " + Arrays.toString(idAtbAtributos));
                    atrZ.setTipo("tipo_error");
                }
            } else if (numParam == 0 && atrLL.getLong() != 0) {
                String[] llAtributos = atrLL.getTipo().split(" ");

                GestorError.writeError("semántico", "Los parámetros de la función no coinciden.\n \t Se ha recibido: "
                        + Arrays.toString(llAtributos) + "\n \t pero no tiene ningún parámetro");
                atrZ.setTipo("tipo_error");
            } else {
                atrZ.setTipo(tipoRet);
            }
        } else if (atrId.getTipo().equals("entero") || atrId.getTipo().equals("cadena") || atrId.getTipo().equals("lógico")) {
            atrZ.setTipo(atrId.getTipo());
        }

        if (atrZprima.getTipo().equals("vacío")) {
            // atrZ.tipo se queda igual
        } else if (atrZprima.getTipo().equals("entero") && atrZ.getTipo().equals("entero")) {
            atrZ.setTipo("lógico");
        } else {
            atrZ.setTipo("tipo_error");
        }

        popAuxLast(3);
    }

    public static void acc94() {
        // Z → ( E ) Zprima

        Atributos atrZprima = peekAuxAttributes(0); // Zprima
        // )
        Atributos atrE = peekAuxAttributes(2);  // E
        // (
        Atributos atrZ = peekAuxAttributes(4); // Z

        if (atrZprima.getTipo().equals("vacío")) {
            atrZ.setTipo(atrE.getTipo());
        } else if (atrZprima.getTipo().equals("entero") && atrE.getTipo().equals("entero")) {
            atrZ.setTipo("lógico");
        } else {
            atrZ.setTipo("tipo_error");
        }

        popAuxLast(4);
    }

    public static void acc95() {
        // Z → MAX ( L )
        //)
        Atributos atrL = peekAuxAttributes(1); // L
        //( MAX
        Atributos atrZ = peekAuxAttributes(4);// Z

        atrZ.setTipo("entero");

        if (!atrL.getTipo().equals("vacío")) {
            String[] lista = atrL.getTipo().split(" ");
            for (String item : lista) {
                if (!item.equals("entero")) {
                    atrZ.setTipo("tipo_error");
                }
            }
        }

        popAuxLast(4);
    }

    public static void acc96() {
        // Z → MIN ( L )

        //)
        Atributos atrL = peekAuxAttributes(1); // L
        //( MIN
        Atributos atrZ = peekAuxAttributes(4);// Z

        atrZ.setTipo("entero");

        if (!atrL.getTipo().equals("vacío")) {
            String[] lista = atrL.getTipo().split(" ");
            for (String item : lista) {
                if (!item.equals("entero")) {
                    atrZ.setTipo("tipo_error");
                }
            }
        }
    }

    public static void acc97() {
        // Zprima → in ( L )

        // (
        Atributos atrL = peekAuxAttributes(1); // L
        // ) in
        Atributos atrZprima = peekAuxAttributes(4); // Zprima

        atrZprima.setTipo("entero");

        if (!atrL.getTipo().equals("vacío")) {
            String[] lista = atrL.getTipo().split(" ");
            for (String item : lista) {
                if (!item.equals("entero")) {
                    atrZprima.setTipo("tipo_error");
                }
            }
        }

        popAuxLast(4);
    }

    public static void acc98() {
        // Zprima → λ
        Atributos atrZprima = peekAuxAttributes(0); // Zprima
        atrZprima.setTipo("vacío");
    }

    // Función auxiliar para obtener el n-ésimo elemento desde el tope de la pila auxiliar
    private static ItemPila peekAux(int n) {
        int index = stackAux.size() - 1 - n;
        if (index < 0 || index >= stackAux.size()) {
            throw new EmptyStackException();
        }
        return stackAux.get(index);
    }

    // Función auxiliar para obtener los atributos del n-ésimo elemento desde el tope de la pila auxiliar
    private static Atributos peekAuxAttributes(int nBuscar) {
        ItemPila item = peekAux(nBuscar);

        if (item.getTipo() == ItemPila.Tipo.NOTERMINAL) {
            if (debug) {
                System.out.println("PEEK AUX: " + ((NoTerminal) item).debug());
            }
            return ((NoTerminal) item).getAtributos();
        } else {
            if (debug) {
                System.out.println("PEEK AUX: " + ((Terminal) item).debug());
            }
            return ((Terminal) item).getAtributos();
        }
    }

    // Función auxiliar para eliminar los n elementos desde el tope de la pila auxiliar
    private static void popAuxLast(int nBorrar) {
        for (int i = 0; i < nBorrar && !stackAux.isEmpty(); i++) {
            stackAux.pop();
        }
    }

}
