Exemple #1
0
        private void declaracion(TablaSimbolo tabla, ParseNode raiz, string ambito)
        {
            pila_ambito.Push(ambito);//nuevo
            string tipo_dato;

            tipo_dato = raiz.childNodes[0].ToString();
            Nodo resultado = null;

            if (raiz.childNodes.Count > 2)//de la forma <tipodato><id><asignacion>
            {
                //asignacion es de la forma <condicion> solo tiene un hijo
                resultado = calculo(raiz.childNodes[2].izq()); //<declaracion>-><asignacion>-><condicion>
                if ("<error>".Equals(resultado.Tipo))          //si hay un error semantico en el calculo
                {
                    resultado = null;                          //calculo ya se encarga de agregar el error
                }
            }
            //revisamos los ids para agregarlos
            ParseNode ids = raiz.childNodes[1];
            Simbolo   nuevo;

            foreach (ParseNode hijo in ids.childNodes)
            {
                nuevo = new Simbolo(tipo_dato, hijo.ToString(), ambito, hijo.Fila, hijo.Columna); //genero un nuevo simbolo
                addError(nuevo.asignar(resultado));                                               //si tuviese un error en la asignacion, lo agrega, si no hay no hace nada la funcion adderror
                if (!tabla.add(nuevo))                                                            //si no se logra agregar(por eso el !)
                {
                    addError(new ParseNode(nuevo.Fila, nuevo.Columna, "La variable:" + hijo.ToString() + " ya fue declarada", "<error>"));
                }
            }
        }
Exemple #2
0
 private void dibujarTS(string ambito, TablaSimbolo tabla)
 {
     //1.-Guardamos el dot
     Archivo.guardar(tabla.graficaTabla(ambito), ruta + "TS_" + ambito + ".dot");//obviamos que devuelve, asumimos que todo funciona
     //2.-Llamamos el comando para generar la imagen
     Archivo.generarGrafica(ruta, "TS_" + ambito + ".dot");
 }
Exemple #3
0
 public void cambiarAmbito(TablaSimbolo general /*List<Error> errores*/)
 {
     foreach (Simbolo simbolo in general.simbolos)
     {
         simbolos.Add(simbolo);
     }
 }
Exemple #4
0
 private void inicializarListas()
 {
     lista_errores  = new List <Error_>();
     lista_metodos  = new List <Metodo>();
     pila_ambito    = new Stack <string>();
     tabla_global   = new TablaSimbolo();
     tabla_local    = new TablaSimbolo();
     pila_subambito = new Stack <string>();//nuevo
 }
Exemple #5
0
        private Nodo si(ParseNode raiz)
        {
            Nodo retorno = null;

            //los hijos de if son de la forma: Si <condicion> <sentencia> <else>, sentencia y else son opcionales
            if (raiz.childNodes.Count <= 2)
            {
                pila_subambito.Pop(); //nuevo
                return(null);         //no hago nada, no tiene ni sentencia ni else
            }
            ParseNode si   = null;
            ParseNode sino = null;

            foreach (ParseNode hijo_ in raiz.childNodes)//recupero las sentencias si,sino
            {
                if ("<SENTENCIAW>".Equals(hijo_.ToString()))
                {
                    si = hijo_;
                }
                else if ("<ELSE>".Equals(hijo_.ToString()))
                {
                    sino = hijo_;
                }
            }
            Nodo resultado = calculo(raiz.childNodes[1]);//calculo el valor de la condicion

            if ("<error>".Equals(resultado.Tipo))
            {
                pila_subambito.Pop(); //nuevo
                return(null);         //dejo de revisar el if
            }
            if (!"Bool".Equals(resultado.Tipo))
            {
                pila_subambito.Pop();//nuevo
                addError(new Nodo(raiz.Fila, raiz.Columna, "La condicion del mientras no retorna un booleano", "<error>"));
                return(null);
            }
            TablaSimbolo aux = tabla_local;   //se guarda la tabla actual

            tabla_local = new TablaSimbolo(); //pasamos a una tabla para if
            tabla_local.cambiarAmbito(aux);   //pasamos los valores de aux a local
            if (MyMath.toBool(resultado.ToString()))
            {
                retorno = ejecutar(si);//si es null no hace nada
            }
            else
            {
                //los hijos de <else> tienen la forma: sino <sentencia>
                if (sino != null)
                {
                    retorno = ejecutar(sino.der());
                }
            }
            tabla_local = aux;    //recuperamos la tabla local
            pila_subambito.Pop(); //nuevo
            return(retorno);
        }
Exemple #6
0
        public Nodo asignarValor(string identificador, Nodo valor, TablaSimbolo global)
        {
            Simbolo aux = getSimbolo(identificador);    //busca en esta tabla

            if (aux == null)                            //si el simbolo no esta en esta tabla
            {
                aux = global.getSimbolo(identificador); //busca en la tabla global
            }
            if (aux == null)
            {
                return(new Nodo(0, 0, "La variable:" + identificador + " no existe", "<error>"));
            }
            return(aux.asignar(valor));//se retorna null si todo salio bien
        }
Exemple #7
0
        public Nodo getValor(string identificador, TablaSimbolo global) //tomado como base el ejemplo
        {
            Simbolo aux = getSimbolo(identificador);                    //busca en esta tabla

            if (aux == null)                                            //si el simbolo no esta en esta tabla
            {
                aux = global.getSimbolo(identificador);                 //busca en la tabla global
            }
            if (aux == null)                                            //si aun asi no lo encuentra
            {
                return(null);                                           //<error> la variable no existe
            }
            return(aux.Valor);                                          //si el simbolo no tuviese un valor asignado, el se encarga de mandarme un ParseNode con mensaje de error
        }
Exemple #8
0
        private void asignar(TablaSimbolo tabla, ParseNode raiz, string ambito)
        {
            pila_ambito.Push(ambito);//nuevo
            //los hijos del nodo asignar son de la forma: id <asignacion>
            string id = raiz.izq().ToString();
            //el nodo <asignacion> solo tiene al hijo <condicion>
            ParseNode asignacion = raiz.der();
            Nodo      resultado  = calculo(asignacion.izq()); //reitero, calculo ya se encarga de guardar errores

            if ("<error>".Equals(resultado.Tipo))             //si es error no asigno nada
            {
                return;
            }
            addError(tabla.asignarValor(id, resultado, tabla_global));//si no hay error solo asigna el valor
        }
Exemple #9
0
        public void mas_menos(string identificador, TablaSimbolo global, bool mas)
        {
            Simbolo aux = getSimbolo(identificador);    //busca en esta tabla

            if (aux == null)                            //si el simbolo no esta en esta tabla
            {
                aux = global.getSimbolo(identificador); //busca en la tabla global
            }
            if (aux == null)
            {
                return;
            }
            double valor = double.Parse(aux.Valor.ToString());

            if (mas)
            {
                valor++;
            }
            else
            {
                valor--;
            }
            aux.asignar(new Nodo(0, 0, valor.ToString(), "Double"));
        }
Exemple #10
0
        private Nodo mientras_o_Hasta(ParseNode raiz, bool mientras = true)
        {
            Nodo retorno = null;

            //los hijos de while son de la forma: mientras <condicion> <sentencia>, sentencia es opcional
            if (raiz.childNodes.Count <= 2) //si no hay sentencia, el while podria ser infinito
            {
                pila_subambito.Pop();       //nuevo
                addError(new Nodo(raiz.Fila, raiz.Columna, "La funcion mientras no tiene forma de salir", "<error>"));
                return(null);
            }
            Nodo resultado = calculo(raiz.der());

            if ("<error>".Equals(resultado.Tipo))
            {
                pila_subambito.Pop(); //nuevo
                return(null);         //dejo de revisar
            }
            if (!"Bool".Equals(resultado.Tipo))
            {
                pila_subambito.Pop();//nuevo
                addError(new Nodo(raiz.Fila, raiz.Columna, "La condicion del mientras no retorna un booleano", "<error>"));
                return(null);
            }
            TablaSimbolo aux = tabla_local;   //se guarda la tabla actual

            tabla_local = new TablaSimbolo(); //pasamos a una tabla para if
            tabla_local.cambiarAmbito(aux);   //pasamos los valores de aux a local
            if (mientras)
            {
                while (MyMath.toBool(resultado.ToString()))
                {
                    retorno = ejecutar(raiz.childNodes[2]);
                    //Verificamos si no hay un continue/break/etc
                    if (retorno != null)
                    {
                        if ("<DETENER>".Equals(retorno.Tipo))
                        {
                            break;//detengo el while
                        }
                        if ("<CONTINUAR>".Equals(retorno.Tipo))
                        {
                            retorno = null;//ya adentro se encarga de saltar el resto de sentencias asi que solo regreso retorno a ser null
                        }
                        if ("<RETORNO>".Equals(retorno.Tipo))
                        {
                            break;
                        }
                    }
                    resultado = calculo(raiz.der());
                }
            }
            else
            {
                while (!MyMath.toBool(resultado.ToString()))
                {
                    retorno   = ejecutar(raiz.childNodes[2]);
                    resultado = calculo(raiz.der());
                }
            }
            tabla_local = aux;//recuperamos la tabla local
            if (retorno != null && "<DETENER>".Equals(retorno.Tipo))
            {
                retorno = null;   //limpio el detener, si no se podria propagar a otras cosas
            }
            pila_subambito.Pop(); //nuevo
            return(retorno);
        }
Exemple #11
0
        private Nodo para(ParseNode raiz, string ambito)
        {
            if (raiz.childNodes.Count < 7) //no tiene sentencia
            {
                pila_subambito.Pop();      //nuevo
                return(null);
            }
            Nodo retorno = null;
            //los hijos de for son de la forma: para Double id E <condicion> <op> <sentenciaw>, sentencia es opcional
            string  nombre  = raiz.childNodes[2].ToString();                                                              //el nombre de la variable para la condicion
            Simbolo i       = new Simbolo("Double", nombre, ambito, raiz.childNodes[2].Fila, raiz.childNodes[2].Columna); //genero un nuevo simbolo
            Nodo    valor_i = calculo(raiz.childNodes[3]);

            if ("<error>".Equals(valor_i.Tipo) || "String".Equals(valor_i.Tipo))
            {
                pila_subambito.Pop();         //nuevo
                return(null);                 //si hay error dejo de revisar el for
            }
            i.asignar(valor_i);               //no deberia haber problema con el type casting
            TablaSimbolo aux = tabla_local;   //se guarda la tabla actual

            tabla_local = new TablaSimbolo(); //pasamos a una tabla para if
            tabla_local.cambiarAmbito(aux);   //pasamos los valores de aux a local
            if (!tabla_local.add(i))          //si la variable de reconocimiento ya existe
            {
                pila_subambito.Pop();         //nuevo
                addError(new Nodo(i.Fila, i.Columna, "La variable:" + i.Identificador + " ya fue definida en este ambito", "<error>"));
                return(null);
            }
            Nodo resultado = calculo(raiz.childNodes[4]); //calculo la condicion

            if ("<error>".Equals(resultado.Tipo))         //verifico que la condicion si sea un booleano
            {
                pila_subambito.Pop();                     //nuevo
                return(null);                             //dejo de revisar
            }
            if (!"Bool".Equals(resultado.Tipo))
            {
                pila_subambito.Pop();//nuevo
                addError(new Nodo(raiz.Fila, raiz.Columna, "La condicion del mientras no retorna un booleano", "<error>"));
                return(null);
            }
            while (MyMath.toBool(resultado.ToString()))
            {
                retorno = ejecutar(raiz.childNodes[6]);
                if (retorno != null)
                {
                    if ("<DETENER>".Equals(retorno.Tipo))
                    {
                        break;//detengo el while
                    }
                    if ("<CONTINUAR>".Equals(retorno.Tipo))
                    {
                        retorno = null;//ya adentro se encarga de saltar el resto de sentencias asi que solo regreso retorno a ser null
                    }
                    if ("<RETORNO>".Equals(retorno.Tipo))
                    {
                        break;
                    }
                }
                if ("+".Equals(raiz.childNodes[5].izq().ToString()))   //++
                {
                    tabla_local.mas_menos(nombre, tabla_global, true); //funcion extra que hice para facilitar el ++/--
                }
                else//--
                {
                    tabla_local.mas_menos(nombre, tabla_global, false);
                }
                resultado = calculo(raiz.childNodes[4]); //recalculamos la condicion
            }
            tabla_local = aux;                           //recuperamos la tabla local
            if (retorno != null && "<DETENER>".Equals(retorno.Tipo))
            {
                retorno = null;
            }
            pila_subambito.Pop();//nuevo
            return(retorno);
        }
Exemple #12
0
        private Nodo llamada(ParseNode raiz)
        {
            //los hijos de llamada tienen la forma: nombre_funcion <VALORES>
            //1.-recuperamos el nombre del metodo
            string id_metodo = raiz.izq().ToString();

            //2.-Verificamos si existe el metodo, en este punto todavia no vemos si el no. de parametros es correcto
            if (!existeMetodo(id_metodo))
            {
                return(null);
            }
            //3.-Una vez que revisamos que existe el metodo revisamos si hay valores para recuperar el metodo
            Metodo funcion = null;
            Nodo   retorno = null;

            if (raiz.der() == null)//no hay valores
            {
                funcion = getMetodo(id_metodo);
                //4.-Si no encontramos un metodo sin parametros, es error
                if (funcion == null)
                {
                    addError(new Nodo(raiz.Fila, raiz.Columna, "El metodo:" + id_metodo + " no existe", "<error>"));
                    return(new Nodo(raiz.Fila, raiz.Columna, "1", "Int"));//retornamos un entero por si acaso, para continuar con la ejecucion
                }
                //5.-Si no es null entonces ejecutamos el metodo sin parametros
                TablaSimbolo aux = tabla_local;        //se guarda la tabla actual
                tabla_local = new TablaSimbolo();      //pasamos a una tabla para if
                tabla_local.cambiarAmbito(aux);        //pasamos los valores de aux a local
                pila_ambito.Push(id_metodo);           //agregamos el nuevo ambito
                retorno = ejecutar(funcion.Sentencia); //llamamos la raiz de las sentencias de funcion y las mandamos a ejecutar
                //6.-Solo aqui sabemos el tipo de la funcion y el tipo de retorno, asi que revisamos y lanzamos un error de ser necesario

                tabla_local = aux;//recuperamos la tabla local
            }
            else//si hay valores
            {
                //4.-calculamos los valores y los metemos en una lista
                List <Nodo> valores   = new List <Nodo>();
                Nodo        resultado = null;
                foreach (ParseNode valor in raiz.der().childNodes) //llamada->valores
                {
                    resultado = calculo(valor);                    //calculo agrega cualquier error, no retorna null en ningun caso
                    valores.Add(resultado);
                }
                //5.-Teniendo los valores generamos el id extra
                string id_extra = "";
                foreach (Nodo val in valores)
                {
                    id_extra += val.Tipo;
                }
                //6.-Con el id extra buscamos otra vez a funcion pero con id_metodo+id_extra
                funcion = getMetodo(id_metodo + id_extra);
                //7.-Si no encontramos un metodo con esos parametros, es error, no se puede hacer typecasting para parametros, eso se haria con templates y no lo maneja nuestra gramatica
                if (funcion == null)
                {
                    addError(new Nodo(raiz.Fila, raiz.Columna, "El metodo:" + id_metodo + "con parametros:" + id_extra + " no existe", "<error>"));
                    pila_ambito.Pop();                                     //nuevo
                    return(new Nodo(raiz.Fila, raiz.Columna, "1", "Int")); //retornamos un entero por si acaso, para continuar con la ejecucion
                }
                //8.-Si no es null ejecutamos el metodo, pero antes agregamos a su tabla, simbolos que corresponden a sus parametros
                //esta forma de agregar es distinda, pues si el metodo es recursivo y declara una variable, en lugar de intentar declararla otra vez, cambiamos su valor
                TablaSimbolo aux = tabla_local;   //se guarda la tabla actual
                tabla_local = new TablaSimbolo(); //pasamos a una tabla para if
                tabla_local.cambiarAmbito(aux);   //pasamos los valores de aux a local
                pila_ambito.Push(id_metodo);      //agregamos el nuevo ambito
                //8.1.-Aqui agregamos los parametros como simbolo
                int     limite       = valores.Count;
                Simbolo actual       = null;
                Nodo    valor_actual = null;
                for (int i = 0; i < limite; i++)
                {
                    actual       = funcion.parametros[i];
                    valor_actual = valores[i];
                    actual.asignar(valor_actual);
                    tabla_local.replace(actual);//esta es la funcion que agrega o reemplaza cuando es requerido
                }
                //9.-ejecutamos
                retorno     = ejecutar(funcion.Sentencia); //llamamos la raiz de las sentencias de funcion y las mandamos a ejecutar
                tabla_local = aux;                         //recuperamos la tabla local
            }
            if ("<RETORNO>".Equals(retorno.Tipo))
            {
                retorno.Tipo = retorno.Sub_tipo;
            }
            pila_ambito.Pop();
            return(retorno);
        }