Exemplo n.º 1
0
        private void add(ParseNode raiz, string ambito, string tipo_dato, Nodo resultado)
        {
            Simbolo nuevo;

            foreach (ParseNode hijo in raiz.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_global.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>"));
                }
            }
        }
Exemplo n.º 2
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
        }
Exemplo n.º 3
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
        }
Exemplo n.º 4
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"));
        }
Exemplo n.º 5
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);
        }
Exemplo n.º 6
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);
        }