private void anadeProduccionesTerminales(
      String origen,
      String cima,
      ArrayList<String> estados,
      ArrayList<String> simbolos,
      String destino) {

    String est = new String(/*itEst.next()*/ destino);
    Iterator<String> itSimbolos = simbolos.iterator();
    while (itSimbolos.hasNext()) {
      String sim = new String(itSimbolos.next());
      Produccion p = new Produccion();
      p.anadeCadena(sim);
      String nVar = "[" + origen + cima + est + "]";
      gic.anadeVariable(nVar);
      gic.anadeProdConTerminales(nVar);
      gic.anadeProduccion(nVar, p);
    }
  }
  private void anadeProduccionConUnaLista(
      String origen,
      String destino,
      String cima,
      ArrayList<String> lista,
      ArrayList<String> simbolos,
      ArrayList<String> salidaPila) {

    int tamLista = lista.size();
    int tamListaConcreta = salidaPila.size();
    int tamSimbolos = simbolos.size();
    int nuevoTam = tamLista - 1;
    String rk = lista.get(nuevoTam) + "";
    String nVar = "[" + origen + cima + rk + "]";
    gic.anadeVariable(new String(nVar));
    Produccion p = new Produccion();

    for (int j = 0; j < tamSimbolos; j++) {
      String sim = simbolos.get(j);
      p.anadeCadena(sim);
      for (int i = 0; i < tamListaConcreta; i++) {
        String cadProd = "[";
        if (i == 0) cadProd += destino;
        else cadProd += lista.get(i - 1);
        String sigEstado = null;
        if (i + 1 == tamListaConcreta) {
          sigEstado = rk;
        } else {
          sigEstado = lista.get(i);
        }

        cadProd += salidaPila.get(i) + sigEstado + "]";
        p.anadeCadena(new String(cadProd));
      }
      gic.anadeProduccion(nVar, p);
    }
  }
  private int dimeTipo(String cadena, ArrayList<String> v) {

    if (gic.getSimbolos().contains(cadena) || lambda.equals(cadena)) return 0;
    if (v.contains(cadena)) return 1;
    else return 2;
  }
  @SuppressWarnings("unchecked")
  public void cambiaNombreVariables() {
    ArrayList<String> variables = (ArrayList<String>) gic.getVariables().clone();
    HashMap<String, ArrayList<Produccion>> produc = clonarProducciones(gic.getProducciones());

    ArrayList<String> nVariables = new ArrayList<String>();
    nVariables.add(gic.getVariableInicial());
    int tam = gic.getVariables().size();
    char ultima = comienzo;
    char nVar = comienzo;
    int ii = 1;
    boolean completo = false;
    String s = null;
    int jj = 0;
    while (ii < tam) {

      if (!completo) {
        nVar = new Character(ultima);
        ultima = (char) (nVar + 1);
        if (nVar != 'S') {
          s = nVar + "";
          nVariables.add(s);
          ii++;
        }
        if (s.equals(ultimatraduccion)) {
          completo = true;
        }
      } else {
        s = "[" + auxtraduccion + jj + "]";
        nVariables.add(s);
        jj++;
        ii++;
      }
    }

    HashMap<String, ArrayList<Produccion>> nProduc = new HashMap<String, ArrayList<Produccion>>();

    variables = (ArrayList<String>) variables.clone();
    int tamano = nVariables.size();

    for (int i = 0; i < tamano; i++) {
      String var = variables.get(i);
      String nnVar = nVariables.get(i);
      ArrayList<Produccion> nListaProd = new ArrayList<Produccion>();
      ArrayList<Produccion> listaProd = produc.get(var);
      int j = 0;
      int tamListaProd = listaProd.size();
      Produccion nProd = null;
      while (j < tamListaProd) {
        nProd = new Produccion();
        Produccion prod = listaProd.get(j);
        ArrayList<String> nConcat = nuevaContatenacion(prod, variables, nVariables);
        if (nConcat != null) nProd.setConcatenacion(nConcat);
        if (!esta(nProd, nListaProd) && ((nConcat != null))) nListaProd.add(nProd);
        j++;
      }
      nProduc.put(nnVar, nListaProd);
    }

    this.gic.setProducciones(nProduc);
    this.gic.setVariables(nVariables);

    html += "<br><h2>" + mensajero.devuelveMensaje("simplificacionGICs.genttotalsimp", 2) + "</h2>";
    html += "<br><center><table>" + gic.toHTML() + "</table></center><br>";
    xmllatex += "</ocultar>";
    xmllatex +=
        "\n<step><titulo>"
            + mensajero.devuelveMensaje("simplificacionGICs.gentradasimlatex", 2)
            + "</titulo>"
            + gic.toLat()
            + "</step>\n";
    xml +=
        "<paso><titulo>"
            + mensajero.devuelveMensaje("simplificacionGICs.genttotalsimp", 2)
            + "</titulo>"
            + gic.toXML()
            + "</paso>\n</pasos>\n";
    gic.setXML(xml);
    gic.setXMLLatex(xmllatex);
  }
  private void limpiaAConciencia(boolean simp) {

    boolean b = this.getGic().dimeSiHayProdUnitarias();
    boolean c = this.getGic().dimeSiHayProdRecursivas();
    boolean d;
    if (simp) d = this.getGic().dimeSiHayVariablesQueNoTienenProd();
    else {
      d = this.getGic().calculaAlcanzables();

      if (d) this.getGic().setVariablesSinProd(this.getGic().dameNoAlcanzables());
    }
    boolean e = this.getGic().dimeSiHayProdConProdUnitarias();

    boolean a = b || c || d || e;
    if (simp && a) {
      html += "<center>" + mensajero.devuelveMensaje("simplificacionGICs.simp", 2) + "</center>";
      xml +=
          "<paso><titulo>"
              + mensajero.devuelveMensaje("simplificacionGICs.simp", 2)
              + "</titulo></paso>\n";
      xmllatex +=
          "<oculto><titulo>"
              + mensajero.devuelveMensaje("simplificacionGICs.simplatex", 2)
              + "</titulo>"
              + gic.toLat()
              + "</oculto>\n";
    }

    boolean hecho = false;
    while (a) {

      boolean escribe = d;
      if (escribe && simp) {
        html +=
            "<br><h2>"
                + mensajero.devuelveMensaje("simplificacionGICs.quitvsimprod", 2)
                + "</h2><h3>"
                + this.getGic().getVariablesSinProd().toString()
                + "</h3>";
        xml +=
            "<paso><titulo>"
                + mensajero.devuelveMensaje("simplificacionGICs.quitvsimprod", 2)
                + this.getGic().getVariablesSinProd().toString()
                + "</titulo>";
        xmllatex +=
            "<oculto><titulo>"
                + mensajero.devuelveMensaje("simplificacionGICs.quitvsimprodlatex", 2)
                + this.getGic().getVariablesSinProd().toString()
                + "</titulo>";
      }
      if (escribe && !simp) {

        html +=
            "<br><h2>Quitamos variables no alcanzables: </h2><h3>"
                + this.getGic().dameNoAlcanzables().toString()
                + "</h3>";

        xml +=
            "<paso><titulo>"
                + mensajero.devuelveMensaje("simplificacionGICs.noalc", 2)
                + this.getGic().dameNoAlcanzables().toString()
                + "</titulo>";

        xmllatex +=
            "<oculto><titulo>"
                + mensajero.devuelveMensaje("simplificacionGICs.noalclatex", 2)
                + this.getGic().dameNoAlcanzables().toString()
                + "</titulo>";
      }

      while (d) {
        this.getGic().quitaVariablesQueNoExisten();
        d = this.getGic().dimeSiHayVariablesQueNoTienenProd();
        if (!hecho) hecho = true;
      }
      if (escribe) {
        html += "<br><center><table>" + gic.toHTML() + "</table></center><br>";
        xml += gic.toXML() + "</paso>\n";
        xmllatex += gic.toLat() + "</oculto>\n";
      }

      if (!hecho) {
        if (b) {
          html +=
              "<br><h2>"
                  + mensajero.devuelveMensaje("simplificacionGICs.unicaprod", 2)
                  + "</h2><h3>"
                  + this.getGic().getProdUnit().toString()
                  + "</h3>";
          xml +=
              "<paso><titulo>"
                  + mensajero.devuelveMensaje("simplificacionGICs.unicaprod", 2)
                  + this.getGic().getProdUnit().toString()
                  + "</titulo>";
          xmllatex +=
              "<oculto><titulo>"
                  + mensajero.devuelveMensaje("simplificacionGICs.unicaprodlatex", 2)
                  + this.getGic().getProdUnit().toString()
                  + "</titulo>";
          this.getGic().quitaProdUnitarias();
          html += "<br><center><table>" + gic.toHTML() + "</table></center><br>";
          xml += gic.toXML() + "</paso>\n";
          xmllatex += gic.toLat() + "</oculto>\n";
          if (!hecho) hecho = true;
        } else if (!hecho && c) {
          html +=
              "<br><h2>"
                  + mensajero.devuelveMensaje("simplificacionGICs.prodrec", 2)
                  + "</h2><h3>"
                  + this.getGic().getProdRecursivas().toString()
                  + "</h3>";
          xml +=
              "<paso><titulo>"
                  + mensajero.devuelveMensaje("simplificacionGICs.prodrec", 2)
                  + "</titulo>";
          xmllatex +=
              "<oculto><titulo>"
                  + mensajero.devuelveMensaje("simplificacionGICs.prodreclatex", 2)
                  + "</titulo>";

          this.getGic().quitaProdRecursivas();
          html += "<br><center><table>" + gic.toHTML() + "</table></center><br>";
          xml += gic.toXML() + "</paso>\n";
          xmllatex += gic.toLat() + "</oculto>\n";
          if (!hecho) hecho = true;
        } else if (!hecho && e) {
          if (!this.getGic().getProdConProdUnit().isEmpty()) {
            html +=
                "<br><h2>"
                    + mensajero.devuelveMensaje("simplificacionGICs.varconpunit", 2)
                    + "</h2><h3>"
                    + this.getGic().getProdConProdUnit()
                    + "</h3>";
            xml +=
                "<paso><titulo>"
                    + mensajero.devuelveMensaje("simplificacionGICs.varconpunit", 2)
                    + "</titulo>";
            xmllatex +=
                "<oculto><titulo>"
                    + mensajero.devuelveMensaje("simplificacionGICs.varconpunitlatex", 2)
                    + "</titulo>";
            this.getGic().quitaProdConProdUnitarias();
            html += "<br><center><table>" + gic.toHTML() + "</table></center><br>";
            xml += gic.toXML() + "</paso>\n";
            xmllatex += gic.toLat() + "</oculto>\n";
            if (!hecho) hecho = true;
          }
        }
      }

      if (simp) d = this.getGic().dimeSiHayVariablesQueNoTienenProd();
      else {
        d = this.getGic().calculaAlcanzables();
      }
      if (!d) {
        b = this.getGic().dimeSiHayProdUnitarias();
        c = this.getGic().dimeSiHayProdRecursivas();

        e = this.getGic().dimeSiHayProdConProdUnitarias();
      }
      a = b || c || d || e;

      hecho = false;
    }
  }
  /**
   * @return Gramatica resultado de aplicar el algoritmo para hallar una gramatica indepenediente de
   *     contexto a partir de un automata de pila dado.
   */
  @SuppressWarnings("unchecked")
  private void AP_Gramatica() {

    gic = new GramaticaIC();
    gic.setSimbolos((ArrayList<String>) automataEntrada.getAlfabeto().getListaLetras().clone());

    gic.setVariableInicial("S");

    ArrayList<String> estados = (ArrayList<String>) this.automataEntrada.getEstados().clone();
    Iterator<String> it = estados.iterator();

    gic.anadeVariable("S");
    while (it.hasNext()) {

      Produccion p = new Produccion();
      String ini = this.automataEntrada.getEstadoInicial();
      String cadena = "[" + ini + fondoPila + it.next() + "]";
      p.anadeCadena(cadena);
      gic.anadeProduccion("S", p);
      gic.anadeVariable(cadena);
    }

    ArrayList<AristaAP> arista = this.automataEntrada.getAutomataPila();
    Iterator<AristaAP> itArista = arista.iterator();

    while (itArista.hasNext()) {

      AristaAP aristaActual = itArista.next();
      ArrayList<String> salidaPila = (ArrayList<String>) aristaActual.getSalidaPila().clone();
      String destino = new String(aristaActual.getDestino());
      String origen = new String(aristaActual.getOrigen());
      ArrayList<String> simbolos = (ArrayList<String>) aristaActual.getEntradaSimbolos().clone();
      String cima = new String(aristaActual.getCimaPila());

      if (desapila(salidaPila)) {
        anadeProduccionesTerminales(origen, cima, estados, simbolos, destino);
      } else {
        int tamLista = salidaPila.size();
        ArrayList<ArrayList<String>> listaParesEstados =
            construyeListasEstados((ArrayList<String>) estados.clone(), tamLista);
        anadeProduccionesConLista(origen, destino, cima, listaParesEstados, simbolos, salidaPila);
      }
    }

    html = "";
    html +=
        "<br><h2>"
            + mensajero.devuelveMensaje("simplificacionGICs.resulap", 2)
            + "</h2><center><table>"
            + gic.toHTML()
            + "</table></center><br>";
    xml +=
        "<paso><titulo>"
            + mensajero.devuelveMensaje("simplificacionGICs.resulap", 2)
            + "</titulo>"
            + gic.toXML()
            + "</paso>\n";
    xmllatex +=
        "<ocultar>\n<oculto><titulo>"
            + mensajero.devuelveMensaje("simplificacionGICs.resulaplatex", 2)
            + "</titulo>"
            + gic.toLat()
            + "</oculto>\n";

    traduceVariables();
  }