public override bool Equals(object obj) { if (obj == null) { return(false); } Metodo transformado = obj as Metodo; if (transformado == null) { return(false); } return(Equals(transformado)); }
private void agregarFuncion(ParseNode raiz, string ambito)//espera { Metodo nuevo = new Metodo(raiz, ambito); int fila = raiz.childNodes[1].Fila; //fila del id int columna = raiz.childNodes[1].Columna; //columna del id if (!existeMetodo(nuevo)) //si no existe { lista_metodos.Add(nuevo); } else { addError(new Nodo(fila, columna, "El metodo:" + nuevo.Nombre + " ya fue declarado", "<error>")); } }
private bool Equals(Metodo otro) { return(ToString().Equals(otro.ToString())); }
private bool existeMetodo(Metodo nuevo) { return(lista_metodos.Contains(nuevo)); }
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); }