示例#1
0
        public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
        {
            TypeReturn t = Left.CheckSemantics(scope_list, errors);

            if (!(t is ReturnInt || t is ReturnString || t is ReturnNil))//Mira si la parte izquierda es valida(solo pueden ser entera o string)
            {
                errors.Add(new Error(line, column, "La expresión izquierda de la operación relacional debe ser 'int' o 'string'"));
            }

            TypeReturn t1 = Right.CheckSemantics(scope_list, errors);

            if (!(t1 is ReturnInt || t1 is ReturnString || t1 is ReturnNil))//Mira si la parte derecha es valida(solo pueden ser entera o string)
            {
                errors.Add(new Error(line, column, "La expresión derecha de la operación relacional debe ser 'int' o 'string'"));
            }

            if (t1 == null || t == null || t1.ToString() != t.ToString())
            {
                if ((t is ReturnInt && t1 is ReturnNil) || (t is ReturnNil && t1 is ReturnInt) || (t is ReturnNil && t1 is ReturnNil))
                {
                    errors.Add(new Error(line, column, "Las expresiones comparadas son invalidas"));
                }
                else
                if (!(t is ReturnNil) && !(t1 is ReturnNil))
                {
                    errors.Add(new Error(line, column, "Ambas expresiones deben ser de tipo 'int' o de tipo 'string'"));
                }
            }
            return(new ReturnInt());
        }
示例#2
0
 public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
 {
     if (Expre.Count > 0)
     {
         bool foundBreak = false;
         for (int i = 0; i < Expre.Count; i++)
         {
             TypeReturn typeOfExp = Expre[i].CheckSemantics(scope_list, errors); //hago el chequeo semantico a la expresion de turno
             //si la expresion retorno por un break => el exp-sec no retorna valor
             if (typeOfExp is ReturnBreak)
             {
                 foundBreak = true;                           //no retorno aqui para hacerle el chequeo semantico a cada expresion del exp-sec
             }
             if (i == Expre.Count - 1)
             {
                 TypeExpSeq = foundBreak ? new ReturnBreak() : typeOfExp; //si se encontro un break retorno break para poderlo cogerlo en otro exp-sec, si no retorno el tipo de la ultima expresion
                 return(TypeExpSeq);
             }
         }
         return(null);
     }
     else
     {
         TypeExpSeq = new ReturnNotValue(); //si no hay expresiones no se retorna valor
         return(TypeExpSeq);
     }
 }
示例#3
0
        public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
        {
            Scope s = new Scope();

            foreach (var p in types)
            {
                s.Vars.Add(p.Item1, p.Item2);
            }
            scope_list.Add(s);

            TypeReturn r = Body.CheckSemantics(scope_list, errors);

            if (r != null && r is ReturnNil)//ver si el valor de retorno es distinto a lo que deberia devolver
            {
                if (Retu == "int")
                {
                    errors.Add(new Error(line, column, "No coincide el tipo de retorno con el que debería retornar"));
                }
            }
            else if (r != null && r.ToString() != Retu)
            {
                errors.Add(new Error(line, column, "No coincide el tipo de retorno con el que debería retornar"));
            }

            scope_list.RemoveAt(scope_list.Count - 1);

            return(new ReturnNotValue());
        }
示例#4
0
 public Fun_Scope(string name, List <Tuple <string, TypeReturn> > param, TypeReturn retu, bool isSystem)
 {
     Param    = param;
     Name     = name;
     Retu     = retu;
     IsSystem = isSystem;
 }
示例#5
0
        public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
        {
            int cantCiclo = countOfClicles;

            countOfClicles = 0;

            scope_list.Add(new Scope());

            for (int i = 0; i < Decl.Count; i++)
            {
                if (Decl[i] is FunDeclarationNode)           //ver si es una declaración de funnción
                {
                    i = CheckFuntion(i, scope_list, errors); //ver si es un bloque de funciones
                }
                else
                {
                    if (Decl[i] is TypeDeclarationNode)//ver si es una declaración de tipo
                    {
                        i = CheckType(i, scope_list, errors);
                    }

                    else
                    {
                        Decl[i].CheckSemantics(scope_list, errors); //si es una declaración de variable
                    }
                }
            }

            countOfClicles = cantCiclo;

            resulLet = expSec.CheckSemantics(scope_list, errors); //hago el checksemantics del exp-sec;
            scope_list.RemoveAt(scope_list.Count - 1);

            return(resulLet);
        }
        public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
        {
            TypeReturn typeOfAsign = Asign.CheckSemantics(scope_list, errors); //hago el chequeo semantico de la asignacion

            if (typeOfAsign is ReturnNotValue)                                 //verifico que devuelva algun valor
            {
                errors.Add(new Error(line, column, "La parte derecha de la asignacion debe devolver algun valor"));
            }

            TypeReturn typeOfLvalue = LValue.CheckSemantics(scope_list, errors); //hago el chequeo semantico del Lvalue

            if (LValue is VariableNode && Utils.NoAsignVar(scope_list, ((VariableNode)LValue).Name))
            {
                errors.Add(new Error(line, column,
                                     "No se le puede asignar ningún valor a la variable '" +
                                     ((VariableNode)LValue).Name + "'"));
            }

            if (typeOfAsign is ReturnNil)      //pregunto si la parte derecha es nil
            {
                if (typeOfLvalue is ReturnInt) //un entero no permite nil (todos los demas tipos si)
                {
                    errors.Add(new Error(line, column,
                                         "No se le puede asignar un '" + typeOfAsign + "' a un '" + typeOfLvalue + "'"));
                }
            }
            else if (typeOfLvalue != null && typeOfAsign != null &&           //pregunto si no hubo problema con el chequeo de las variables
                     !typeOfLvalue.ToString().Equals(typeOfAsign.ToString())) //chequeo que los tipos sean iguales
            {
                errors.Add(new Error(line, column,
                                     "No se le puede asignar un '" + typeOfAsign + "' a un '" + typeOfLvalue + "'"));
            }

            return(new ReturnNotValue()); //la asignacion no devuelve valor
        }
        public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
        {
            Scope s = new Scope();

            foreach (var p in types)
            {
                s.Vars.Add(p.Item1, p.Item2);
            }
            scope_list.Add(s);

            TypeReturn typeOfBody = Body.CheckSemantics(scope_list, errors);

            if (typeOfBody == null) //pregunto si hubo problemas con el body del procedimiento
            {
                return(null);
            }
            if (typeOfBody.ToString() != "No valor")//ver que no retorna valor
            {
                errors.Add(new Error(line, column, "El procedimiento '" + Name + "' no debe retornar valor"));
            }

            scope_list.RemoveAt(scope_list.Count - 1);

            return(new ReturnNotValue());
        }
        public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
        {
            TypeReturn typeOfValue = Value.CheckSemantics(scope_list, errors);
            TypeReturn actual      = typeOfValue;
            bool       found;

            foreach (var access in Access_list)
            {
                found = false;
                if (access is AccessPto) //pregunto si es un acceso a un record
                {
                    AccessPto aux = access as AccessPto;
                    if (actual is ReturnRecord)
                    {
                        ReturnRecord temp = actual as ReturnRecord;
                        typesList.Add(temp); //anado el record a mi lista de record
                        //ver si el record tiene el campo .id
                        foreach (var field in temp.Fields)
                        {
                            if (field.Item1.Equals(aux.Name)) //busco el campo igual al .id
                            {
                                actual = field.Item2;         //guardo el tipo ese campo para la proxima iteracion
                                found  = true;
                                break;
                            }
                        }
                        if (!found) //si no encontro el campo
                        {
                            errors.Add(new Error(access.Line, access.Column, "El record no tiene ningun campo llamado " + aux.Name));
                        }
                    }
                    else //si el tipo al que se quiere hacer el  .   no es un record
                    {
                        errors.Add(new Error(access.Line, access.Column, "El tipo no es un record"));
                    }
                }
                else
                {
                    //es un acceso a un array
                    AccessIndex aux = access as AccessIndex;
                    if (actual is ReturnArray)
                    {
                        TypeReturn typeOfIndex = aux.Arg.CheckSemantics(scope_list, errors); //hago el chequeo semantico a [exp]
                        if (!(typeOfIndex is ReturnInt))                                     //pregunto si es entera
                        {
                            errors.Add(new Error(access.Line, access.Column, "La expresion de indexer debe devolver un entero"));
                        }
                        ReturnArray temp = actual as ReturnArray;
                        typesList.Add(temp);
                        actual = temp.Type_Of_Elements; //el tipo del acceso es el mismo para todo los elementos del array
                    }
                    else
                    {
                        errors.Add(new Error(access.Line, access.Column, "El tipo que se desea indexar no es un array"));
                    }
                }
            }
            return(actual);
        }
示例#9
0
        /// <summary>
        /// Chequea que la expresion de la condicion devuelva un entero
        /// </summary>
        /// <param name="scope_list">Lista de scope de la expresion de la condicion</param>
        /// <param name="errors">Lista de errores</param>
        protected void CheckCondition(List <Scope> scope_list, List <Error> errors)
        {
            TypeReturn typeOfCond = Cond.CheckSemantics(scope_list, errors);

            if (!(typeOfCond is ReturnInt))  //La expresion de la condicional del if tiene que devolver un entero
            {
                errors.Add(new Error(line, column, "La condicion del if debe retornar un entero"));
            }
        }
示例#10
0
        public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
        {
            countOfClicles++;
            bool problem = false; //para no meter una variable que esta mal en el Scope

            //hay que ver que no exista una variable ni una funcion con el mismo nombre que la del for
            foreach (Scope scope in scope_list)
            {
                if (scope.Vars.Any(s => s.Key.Equals(this.Name))) //pregunto por las variables
                {
                    errors.Add(new Error(line, column, "Ya existe una variable con el nombre: " + Name));
                    problem = true;                                     //no puedo anadirla porque ya existe
                }
                else if (scope.Funcs.Any(s => s.Key.Equals(this.Name))) //pregunto por las funciones
                {
                    errors.Add(new Error(line, column, "Ya existe una funcion con el nombre: " + Name));
                    problem = true; //no puedo anadirla porque ya existe
                }
            }

            TypeReturn typeOfAsign = Asig.CheckSemantics(scope_list, errors);

            if (!(typeOfAsign is ReturnInt))
            {
                errors.Add(new Error(line, column, "La expresion de asignacion debe retonar un entero"));
                problem = true; //no puedo anadirla porque la variable no es un entero
            }

            TypeReturn typeOfTo = To.CheckSemantics(scope_list, errors);

            if (!(typeOfTo is ReturnInt))
            {
                errors.Add(new Error(line, column, "La expresion del To debe retornar un entero"));
            }

            if (!problem) //si no preguntara esto podria estar anadiendo una variable con problemas al Scope (en el Scope no hay nada con errores!)
            {
                varFor = new Var_Scope(Name, typeOfAsign, true);
                Dictionary <string, Var_Scope> param = new Dictionary <string, Var_Scope>();
                param.Add(Name, varFor);
                Scope scopeBodyFor = new Scope(param, new Dictionary <string, TypeReturn>(), new Dictionary <string, Fun_Scope>()); //el scope para la variable del for

                scope_list.Add(scopeBodyFor);                                                                                       //agrego la variable del for a la lista de scope para que el body del for pueda verla

                //if(Body!=null)
                TypeReturn typeOfBody = Body.CheckSemantics(scope_list, errors);
                if (!(typeOfBody is ReturnNotValue))
                {
                    errors.Add(new Error(line, column, "La expresion del body del for no debe devolver nada"));
                }
                scope_list.Remove(scopeBodyFor); //remuevo la variable del for
            }

            countOfClicles--;
            return(new ReturnNotValue());
        }
示例#11
0
        public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
        {
            TypeReturn t = Value.CheckSemantics(scope_list, errors);

            if (!(t is ReturnInt))//Mira a ver si el Value es entero
            {
                errors.Add(new Error(line, column, "La expresión debe ser entera"));
            }

            return(new ReturnInt());
        }
示例#12
0
        public override bool CheckHeader(List <Scope> scope_list, List <Error> errors)
        {
            int cant = errors.Count();//ver los errores que hay hasta el momento

            if (Utils.IsStandardFunction(scope_list[0], Name))
            {
                errors.Add(new Error(line, column, "Hay una funcion en la libreria estandar con el nombre '" + Name + "'"));
            }

            else if (scope_list[scope_list.Count - 1].Vars.ContainsKey(Name) ||
                     scope_list[scope_list.Count - 1].Funcs.ContainsKey(Name))                                //ver si no hay una funcion o variable con ese nombre
            {
                errors.Add(new Error(line, column, "El nombre de la función '" + Name + "' ya esta en uso")); //añado el error
            }
            resul = Utils.FindType(scope_list, Retu);
            if (resul == null)                                                                                    //ver si el "tipo" existe
            {
                errors.Add(new Error(line, column, "El tipo de retorno de la función '" + Name + "' no existe")); //añado el error
            }
            Dictionary <string, string> e = new Dictionary <string, string>();                                    //para saber cuales son los parámetros y no repetir
            TypeReturn temp = null;

            foreach (var p in Param)
            {
                temp = Utils.FindType(scope_list, p.Item2);
                if (temp == null)                                                                                           //ver si el "tipo" existe
                {
                    errors.Add(new Error(line, column, "El tipo del parámetro '" + p.Item1 + "' de la función no existe")); //añado el error
                }
                else
                {
                    types.Add(new Tuple <string, Var_Scope>(p.Item1, new Var_Scope(p.Item1, temp)));
                }

                if (Param.Where(x => x.Item1 == p.Item1).Count() > 1 && !e.ContainsKey(p.Item1))                    //hay mas de uno con el mismo nombre y si no lo he visto
                {
                    errors.Add(new Error(line, column, "Existe más de un parámetro con el nombre '" + Name + "'")); //añado el error
                    e.Add(p.Item1, p.Item1);                                                                        //añado el nombre del parámetro al diccionario
                }
            }

            if (cant == errors.Count)//ver si no hubo error
            {
                f = new Fun_Scope(Name, types.Select(x => new Tuple <string, TypeReturn>(x.Item1, x.Item2.Var_type)).ToList(), resul);
                scope_list[scope_list.Count - 1].Funcs.Add(Name, f);//añadir la función al scope
                return(false);
            }
            return(true);
        }
        public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
        {
            //chequeamos si el tipo del array ya se definio anteriormente
            TypeReturn typeOfArray = Utils.FindType(scope_list, Name);

            if (typeOfArray == null)
            {
                errors.Add(new Error(line, column, "El tipo " + this.Name + "no se ha delcarado todavia"));
            }

            //verificamos que la expresion de inicializacion devuelva algun valor(puede ser nil)
            TypeReturn typeOfInitial = Initial.CheckSemantics(scope_list, errors);

            if (typeOfInitial is ReturnNotValue || typeOfInitial == null) //pregunto por null porque si hubo un error devuelvo null
            {
                errors.Add(new Error(line, column, "La expresion de la inicializacion del array debe devolver algun valor"));
            }

            if (!(typeOfArray is ReturnArray)) //el tipo no es un array
            {
                errors.Add(new Error(line, column, "El tipo " + "'" + this.Name + "'" + " no es de tipo array"));
            }

            else
            {
                if (typeOfInitial is ReturnNil) //si es nil no pueden ser int los valores del array
                {
                    if ((typeOfArray as ReturnArray).Type_Of_Elements is ReturnInt)
                    {
                        errors.Add(new Error(line, column, "El array no permite 'nil' porque los valores del array son 'int'"));
                    }
                }
                else if (((ReturnArray)typeOfArray).Type_Of_Elements.ToString() != typeOfInitial.ToString())
                {
                    errors.Add(new Error(line, column, "Los elementos del array son de tipo '" + ((ReturnArray)typeOfArray).Type_Of_Elements.ToString() + "' y no de tipo '" + typeOfInitial.ToString() + "'"));
                }
            }

            //verificamos que el size es un entero
            TypeReturn typeOfSize = Size.CheckSemantics(scope_list, errors);

            if (!(typeOfSize is ReturnInt))
            {
                errors.Add(new Error(line, column, "La expresion del tamaño del array no devuelve un entero"));
            }
            Array = typeOfArray as ReturnArray;                                                      //para usarlo en la generacion de codigo
            return((typeOfArray != null) ? typeOfArray : new ReturnArray(this.Name, typeOfInitial)); //retorno el array
        }
示例#14
0
        public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
        {
            TypeReturn typeOfFun = Utils.FindFunction(scope_list, Name, out fun, ref NumLevelUp); //chequear que la funcion este definida en el scope

            if (typeOfFun == null)
            {
                errors.Add(new Error(line, column, "La funcion '" + Name + "' no esta declarada en este ambito"));
                return(null); //no se encontro la funcion en el scope
            }

            //para no irme de rango en el for y no tener que estar preguntando cual es menor o mayor
            int min = Math.Min(Param.Count, fun.Param.Count); //me quedo con el minimo de la cantidad de parametros entre la functioncall y la declarada

            //voy comparando los parametros y viendo que devuelvan lo mismo
            for (int i = 0; i < min; i++)
            {
                TypeReturn type = Param[i].CheckSemantics(scope_list, errors); //le hago el chequeo semantico a cada parametro (tienen que devolver algun valor)
                if (type == null)
                {
                    continue;
                }

                if (type is ReturnNil)
                {
                    if (fun.Param[i].Item2 is ReturnInt)
                    {
                        errors.Add(new Error(line, column, "No se le puede asignar un '" + type + "' a un '" + fun.Param[i].Item2 + "'")); //añado el error
                    }
                }
                else if (!type.ToString().Equals(fun.Param[i].Item2.ToString())) //pregunto si el parametro i-esimo de la functioncall es del mismo tipo que del declarado
                {
                    errors.Add(new Error(line, column, "El parametro '" + fun.Param[i].Item1 + "' no es de tipo '" + fun.Param[i].Item2 + "'"));
                }

                if (type is ReturnNotValue) //pregunto si el i-esimo parametro devuelve algun valor (tienen que hacerlo)
                {
                    errors.Add(new Error(line, column, "La expresion del parametro " + i + "-esimo no devuelve valor"));
                }
            }

            if (fun.Param.Count != Param.Count) //para saber si tienen la misma cantidad de parametros la funcioncall que la declarada
            {
                errors.Add(new Error(line, column, "La funcion '" + Name + "' no tiene " + Param.Count + " parametros"));
            }

            return(typeOfFun); //es null si la funcion no se encontro en el Scope
        }
        public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
        {
            this.CheckCondition(scope_list, errors); //chequea que la expresion de la condicion sea un entero

            //hago el chequeo semantico del then y del else
            TypeReturn typeOfBody     = Body.CheckSemantics(scope_list, errors);
            TypeReturn typeOfBodyElse = Body_else.CheckSemantics(scope_list, errors);

            if (typeOfBody == null || typeOfBodyElse == null) //pregunto si hubo problemas en el then y en el else
            {
                return(null);
            }
            //chequeamos que los tipos devueltos por el then y el else sean iguales (puede ser nil uno de las exp mientras la otra no sea int)
            if (typeOfBody is ReturnNil)
            {
                if (typeOfBodyElse is ReturnInt)
                {
                    errors.Add(new Error(line, column, "Los tipos retornados por las expresiones del then y del else tienen que ser iguales"));
                }
                else
                {
                    return(typeOfBodyElse);
                }
            }
            else
            {
                if (typeOfBodyElse is ReturnNil)
                {
                    if (typeOfBody is ReturnInt)
                    {
                        errors.Add(new Error(line, column, "Los tipos retornados por las expresiones del then y del else tienen que ser iguales"));
                    }
                    else
                    {
                        return(typeOfBody);
                    }
                }

                else if (!typeOfBody.ToString().Equals(typeOfBodyElse.ToString())) //el tipo del then y el del else tienen que ser iguales
                {
                    errors.Add(new Error(line, column, "Los tipos retornados por las expresiones del then y del else tienen que ser iguales"));
                }
            }
            //tanto la exp del then como la del else retornan el mismo tipo => retorno el tipo de cualquiera de las dos
            return(typeOfBody); //VER AQUI CUANDO LOS TIPOS SEAN != SI DEVUELVO NULL
        }
        public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
        {
            TypeReturn t = Left.CheckSemantics(scope_list, errors);

            if (!(t is ReturnInt))//Mira si la parte izquierda no es Entera
            {
                errors.Add(new Error(line, column, "La expresión izquierda de la operación lógica debe ser entera"));
            }

            t = Right.CheckSemantics(scope_list, errors);
            if (!(t is ReturnInt))//Mira si la parte derecha no es Entera
            {
                errors.Add(new Error(line, column, "La expresión derecha de la operación lógica debe ser entera"));
            }

            return(new ReturnInt());
        }
示例#17
0
        public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
        {
            CheckCondition(scope_list, errors); //chequeo que la expresion de la condicion devuelva un entero

            TypeReturn typeOfBody = Body.CheckSemantics(scope_list, errors);

            if (!(typeOfBody is ReturnNotValue)) //La expresion del body no puede retornar ningun valor
            {
                errors.Add(new Error(line, column, "La expresion del cuerpo del if no puede devolver ningun valor"));
            }

            if (typeOfBody is ReturnBreak) //pregunto si el body del if es un break para saberlo por si estoy dentro de un exp-sec
            {
                return(new ReturnBreak());
            }

            return(new ReturnNotValue()); //si no retorno ningun valor
        }
示例#18
0
        protected TypeReturn CheckSemanticsForEqualAndDistinct(List <Scope> scope_list, List <Error> errors)
        {
            TypeReturn tLeft  = Left.CheckSemantics(scope_list, errors);
            TypeReturn tRight = Right.CheckSemantics(scope_list, errors);

            if (tLeft == null || tRight == null) //si alguna de las dos variables tuvo problemas no se hace la comparacion
            {
                return(new ReturnInt());
            }

            if (tLeft is ReturnNotValue || tRight is ReturnNotValue)
            {
                errors.Add(new Error(line, column, "De las expresiones comparadas hay al menos una que no tiene valor"));
            }

            if (tLeft is ReturnInt && !(tRight is ReturnInt))
            {
                errors.Add(new Error(line, column, "Las expresiones comparadas no son del mismo tipo,no se puede comparar una expresion del Tipo 'int' con una del tipo '" + tRight.ToString() + "'"));
            }

            if (tLeft is ReturnString && !(tRight is ReturnString || tRight is ReturnNil))
            {
                errors.Add(new Error(line, column, "Las expresiones comparadas no son del mismo tipo,no se puede comparar una expresion del Tipo 'string' con una del tipo '" + tRight.ToString() + "'"));
            }

            if (tLeft is ReturnArray && !(tRight is ReturnNil || tLeft.Equals(tRight)))
            {
                errors.Add(new Error(line, column, "Las expresiones comparadas no son del mismo tipo,no se puede comparar una expresion del Tipo '" + tLeft.ToString() + "' con una del tipo '" + tRight.ToString() + "'"));
            }

            if (tLeft is ReturnRecord && !(tRight is ReturnNil || tLeft.Equals(tRight)))
            {
                errors.Add(new Error(line, column, "Las expresiones comparadas no son del mismo tipo,no se puede comparar una expresion del Tipo '" + tLeft.ToString() + "' con una del tipo '" + tRight.ToString() + "'"));
            }

            if (tLeft is ReturnNil && ((tRight is ReturnInt) || (tRight is ReturnNil)))
            {
                errors.Add(new Error(line, column, "Las expresiones comparadas no son del mismo tipo,no se puede comparar una expresion del Tipo Nil con una del tipo " + tRight.ToString() + "'"));
            }

            return(new ReturnInt());
        }
示例#19
0
        public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
        {
            countOfClicles++;
            TypeReturn typeOfCondi = Condi.CheckSemantics(scope_list, errors);

            if (!(typeOfCondi is ReturnInt))  //La expresion de la condicional del if tiene que devolver un entero
            {
                errors.Add(new Error(line, column, "La condicion del while debe retornar un entero"));
            }

            TypeReturn typeOfBody = Body.CheckSemantics(scope_list, errors);

            if (!(typeOfBody is ReturnNotValue))
            {
                errors.Add(new Error(line, column, "La expresion del body del while no debe retornar ningun valor"));
            }

            countOfClicles--;
            return(new ReturnNotValue());
        }
示例#20
0
        //---------------------chequea el bloque de tipos
        int CheckType(int first, List <Scope> scope_list, List <Error> errors)
        {
            int last = first;
            Dictionary <string, string> tem = new Dictionary <string, string>();                             //guardo todos los nombres de los tipos
            List <TypeDeclarationNode>  no_recursive_types = new List <TypeDeclarationNode>();               //guardo solo los alias y los arrays que no pueden caer en un ciclo
            Dictionary <string, TypeDeclarationNode> typ   = new Dictionary <string, TypeDeclarationNode>(); //guardo los que no son alias

            for (int i = first; i < Decl.Count; i++)
            {
                last = i;
                if (Decl[i] is TypeDeclarationNode)
                {
                    string name = ((TypeDeclarationNode)Decl[i]).Id;//cojo el nombre del type

                    if (Utils.IsSystemType(name))
                    {
                        errors.Add(new Error(Decl[i].line, Decl[i].column, "No se puede crear un tipo con el nombre de 'int' o de 'string'"));
                    }
                    else if (scope_list[scope_list.Count - 1].Types.ContainsKey(name) || tem.ContainsKey(name)) //ver si hay un tipo con ese nombre.
                    {
                        errors.Add(new Error(Decl[i].line, Decl[i].column, "Existe un tipo con el nombre " + "'" + name + "'"));
                    }
                    else
                    {
                        if (Decl[i] is AliasDecNode || Decl[i] is ArrayDecNode)
                        {
                            no_recursive_types.Add((TypeDeclarationNode)Decl[i]);                                                    //Añado el alias o array en su lista
                        }
                        else
                        {
                            typ.Add(name, (TypeDeclarationNode)Decl[i]); //Añado el TypeDeclarationNode en su diccionario
                        }
                        tem.Add(name, name);                             //añado el nombre de cada tipo
                    }
                }
                else
                {
                    last = i - 1;
                    break;
                }
            }

            //--------chequeo los ciclos en los alias o arrays
            int cant = 0;

            while (cant != no_recursive_types.Count())//verificar que los alias esten correctos
            {
                cant = no_recursive_types.Count();
                for (int i = 0; i < no_recursive_types.Count; i++)
                {
                    if (no_recursive_types[i] is AliasDecNode)
                    {
                        var t = Utils.FindType(scope_list, ((AliasDecNode)no_recursive_types[i]).Value_redef);//me dice si el tipo existe y me lo dá
                        if (t != null)
                        {
                            scope_list[scope_list.Count() - 1].Types.Add(no_recursive_types[i].Id, t);
                            no_recursive_types.Remove(no_recursive_types[i]);//lo quito de la lista de alias
                            i = i - 1;
                        }
                        else
                        {
                            if (typ.ContainsKey(((AliasDecNode)no_recursive_types[i]).Value_redef))
                            {
                                typ.Add(no_recursive_types[i].Id, typ[((AliasDecNode)no_recursive_types[i]).Value_redef]);
                                no_recursive_types.Remove(no_recursive_types[i]);
                                i = i - 1;
                            }
                        }
                    }
                    else if (no_recursive_types[i] is ArrayDecNode)
                    {
                        var t = Utils.FindType(scope_list, ((ArrayDecNode)no_recursive_types[i]).Value);//me dice si el tipo existe y me lo dá
                        if (t != null)
                        {
                            scope_list[scope_list.Count() - 1].Types.Add(no_recursive_types[i].Id, new ReturnArray(no_recursive_types[i].Id, t));
                            no_recursive_types.Remove(no_recursive_types[i]);//lo quito de la lista de alias
                            i = i - 1;
                        }
                        else
                        {
                            if (typ.ContainsKey(((ArrayDecNode)no_recursive_types[i]).Value))
                            {
                                typ.Add(no_recursive_types[i].Id, no_recursive_types[i]);
                                no_recursive_types.Remove(no_recursive_types[i]);
                                i = i - 1;
                            }
                        }
                    }
                }
            }

            if (no_recursive_types.Count() > 0)//hay ciclo o error
            {
                for (int i = 0; i < no_recursive_types.Count(); i++)
                {
                    if (no_recursive_types[i] is ArrayDecNode)
                    {
                        errors.Add(new Error(no_recursive_types[i].line, no_recursive_types[i].column, "El array '" + no_recursive_types[i].Id + "' es recursivo , es mutuamente recursivo o su tipo es invalido"));
                    }
                    else
                    {
                        errors.Add(new Error(no_recursive_types[i].line, no_recursive_types[i].column, "Error en el alias el tipo no pasa a traves de ningún record o array"));
                    }
                }
            }

            //---ver si estan bien
            cant = 0;
            while (cant != typ.Count())
            {
                cant = typ.Count();
                foreach (var t in typ)
                {
                    if (t.Key != t.Value.Id)//es un alias
                    {
                        var temp = (scope_list[scope_list.Count - 1].Types.ContainsKey(t.Value.Id)) ? scope_list[scope_list.Count - 1].Types[t.Value.Id] : null;
                        if (temp != null)// era un alias al que ya resolvi su tipo
                        {
                            scope_list[scope_list.Count - 1].Types.Add(t.Key, temp);
                            typ.Remove(t.Key);//lo quito de la lista del diccionario typ
                            break;
                        }
                        else if (!typ.ContainsKey(t.Value.Id))//Es imposible resolver el alias pues el tipo al que hace referencia dio error al resolverse
                        {
                            errors.Add(new Error(t.Value.line, t.Value.column, "No se pudo resolver el alias '" + t.Key + "'"));
                            typ.Remove(t.Key);//lo quito de la lista del diccionario typ
                            break;
                        }
                        continue;
                    }
                    if (t.Value is ArrayDecNode)//si es una declaración de Array
                    {
                        var v = Utils.FindType(scope_list, ((ArrayDecNode)t.Value).Value);
                        if (v != null)
                        {
                            scope_list[scope_list.Count() - 1].Types.Add(t.Key, new ReturnArray(t.Value.Id, v));
                            typ.Remove(t.Key);//lo quito de la lista del diccionario typ
                            break;
                        }
                        else
                        {
                            if (!typ.ContainsKey(((ArrayDecNode)t.Value).Value))
                            {
                                errors.Add(new Error(t.Value.line, t.Value.column, "No existe el tipo con el nombre " + "'" + ((ArrayDecNode)t.Value).Value + "'"));
                                typ.Remove(t.Key);//lo quito de la lista de typ
                                break;
                            }
                        }
                    }
                    if (t.Value is RecordDecNode)//si es una declaración de Record
                    {
                        int entro         = 0;
                        var params_record = new List <Tuple <string, TypeReturn> >();            //guardo los campos de los record

                        foreach (var par in ((RecordDecNode)t.Value).Value)                      //recorro los campos de los record
                        {
                            var v = Utils.FindType(scope_list, par.Item2);                       //veo el tipo de cada record

                            if (v != null)                                                       //si existe el tipo
                            {
                                params_record.Add(new Tuple <string, TypeReturn>(par.Item1, v)); //añado el campo con su tipo
                                continue;
                            }
                            else
                            {
                                entro = 1;
                                if (!typ.ContainsKey(par.Item2))
                                {
                                    errors.Add(new Error(t.Value.line, t.Value.column, "No existe el tipo con el nombre " + "'" + par.Item2 + "'"));
                                    typ.Remove(t.Key);//lo quito de la lista de typ
                                    entro = 2;
                                    break;
                                }
                            }
                        }

                        if (entro == 0)//No hay ningún conflicto con los tipos, todos estan en el scope
                        {
                            var aux = new ReturnRecord(t.Value.Id, params_record);
                            scope_list[scope_list.Count() - 1].Types.Add(t.Key, aux); //Añado al Scope
                            (t.Value as RecordDecNode).record = aux;                  //lo guardo para usarlo en la generacion de codigo
                            typ.Remove(t.Key);                                        //lo quito de la lista de alias
                            break;
                        }
                        if (entro == 2)
                        {
                            break;            //es porque modifique y estoy haciendo un foreach
                        }
                    }
                }
            }

            List <Tuple <string, string> > toRemove = new List <Tuple <string, string> >(); //borrar los alias que estan bien antes de llenar los tipo recursivos por ultima vez

            foreach (var t in typ)                                                          //recorro los que quedan en typ y lleno al diccionario "type_scope"
            {
                if (t.Key != t.Value.Id)                                                    //Es un alias
                {
                    toRemove.Add(new Tuple <string, string>(t.Key, t.Value.Id));
                    continue;
                }
                if (t.Value is RecordDecNode)
                {
                    ReturnRecord aux = new ReturnRecord(t.Value.Id, new List <Tuple <string, TypeReturn> >());
                    scope_list[scope_list.Count - 1].Types.Add(t.Key, aux); //la lista de los campos esta vacia
                    (t.Value as RecordDecNode).record = aux;                //lo guardo para usarlo en la generacion de codigo
                }
                if (t.Value is ArrayDecNode)
                {
                    scope_list[scope_list.Count - 1].Types.Add(t.Key, new ReturnArray(t.Value.Id, null));//el tipo del array no se conoce
                }
            }

            while (toRemove.Count > 0)//quito los alias los meto en el scope con el type return del tipo a que hacen referencia.
            {
                var temp = toRemove[toRemove.Count - 1];
                scope_list[scope_list.Count - 1].Types.Add(temp.Item1, scope_list[scope_list.Count - 1].Types[temp.Item2]);
                toRemove.Remove(temp);
                typ.Remove(temp.Item1);
            }

            foreach (var t in typ)//llenamos lo que esta en "type_scope" que no se conoce
            {
                if (t.Value is RecordDecNode)
                {
                    foreach (var elem in ((RecordDecNode)t.Value).Value)       //recorro para llenar los campos del record
                    {
                        TypeReturn x = Utils.FindType(scope_list, elem.Item2); //pido su tipo
                        ((ReturnRecord)scope_list[scope_list.Count - 1].Types[t.Key]).Fields.Add(new Tuple <string, TypeReturn>(elem.Item1, x));
                    }
                }
                if (t.Value is ArrayDecNode)
                {
                    ((ReturnArray)scope_list[scope_list.Count - 1].Types[t.Key]).Type_Of_Elements =
                        scope_list[scope_list.Count - 1].Types[((ArrayDecNode)t.Value).Value];//lleno el tipo del array
                }
            }
            return(last);
        }
示例#21
0
 public Var_Scope(string name, TypeReturn type, bool noAsign)
 {
     Name     = name;
     Var_type = type;
     NoAsign  = noAsign;
 }
 void FindTipoVariable(List <Scope> scope_list, string s)
 {
     TipoVariable = Utils.FindType(scope_list, s);
 }
        public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
        {
            int cant = errors.Count;//me da la cant de errores que hay hasta el momento

            TypeReturn typeOfAsign = Asig.CheckSemantics(scope_list, errors);
            TypeReturn typeVar;

            if (typeOfAsign == null) //cuando no existe la asignación
            {
                return(new ReturnNotValue());
            }

            if (VarType == null)                                                   //no tiene tipo la variable
            {
                if ((typeOfAsign is ReturnNil) || (typeOfAsign is ReturnNotValue)) //si es nil o no retorna valor no se puede inferir el tipo
                {
                    errors.Add(new Error(line, column, "No se puede inferir el tipo"));
                    return(new ReturnNotValue());
                }
                //Var_type = typeOfAsign.ToString(); //se infiere el tipo
                typeVar = typeOfAsign;
            }

            //tiene tipo la variable (VarType!=null)
            else
            {
                typeVar = Utils.FindType(scope_list, VarType); //busco el tipo de la variable
                if (typeVar == null)
                {
                    errors.Add(new Error(line, column, "El tipo de la variable '" + Name + "' no existe"));
                    //añado el error
                    return(null);
                }
                // el tipo de la variable existe
                if (typeOfAsign is ReturnNil) //pregunto si la asignacion es nil y el Lvalue permite nil
                {
                    if (typeVar is ReturnInt)
                    {
                        errors.Add(new Error(line, column,
                                             "No se le puede asignar un '" + typeOfAsign.ToString() + "' a un '" +
                                             typeVar + "'")); //añado el error
                    }
                }
                else if (!typeVar.Equals(typeOfAsign))
                {
                    errors.Add(new Error(line, column,
                                         "No se le puede asignar un '" + typeOfAsign.ToString() + "' a un '" +
                                         typeVar + "'")); //añado el error
                }
            }

            if (scope_list[scope_list.Count - 1].Vars.ContainsKey(Name) || scope_list[scope_list.Count - 1].Funcs.ContainsKey(Name)) //ver si hay una funcion o una variable con ese nombre
            {
                errors.Add(new Error(line, column, "El nombre de la variable '" + Name + "' ya esta en uso"));                       //añado el error
            }
            if (cant == errors.Count)                                                                                                //si no hubo errores
            {
                v = new Var_Scope(Name, typeVar);
                scope_list[scope_list.Count - 1].Vars.Add(Name, v); //añado la variable al scope
            }
            return(new ReturnNotValue());
        }
示例#24
0
 public Fun_Scope(string name, List <Tuple <string, TypeReturn> > param, TypeReturn retu)
 {
     Param = param;
     Name  = name;
     Retu  = retu;
 }
        public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors)
        {
            ReturnRecord recordDeclared = null;
            //chequear si el tipo del record ya existe en el scope
            KeyValuePair <string, TypeReturn> pair = default(KeyValuePair <string, TypeReturn>);

            for (int i = 0; i < scope_list.Count; i++)
            {
                Scope scope = scope_list[i];
                pair = scope.Types.FirstOrDefault(s => s.Key.Equals(this.Name)); //busco el tipo (nombre) del record en el scope

                if (!pair.Equals(default(KeyValuePair <string, TypeReturn>)))    //pregunto si existe el nombre del tipo en este ambito
                {
                    //chequeo si el tipo es un record
                    if (pair.Value is ReturnRecord)
                    {
                        recordDeclared = pair.Value as ReturnRecord;
                    }
                    else
                    {
                        errors.Add(new Error(line, column, "El tipo '" + Name + "' no es de tipo record"));
                    }
                    break;
                }
            }

            if (pair.Equals(default(KeyValuePair <string, TypeReturn>))) //pregunto si se encontro el el tipo del record en el scope
            {
                errors.Add(new Error(line, column, "El tipo '" + Name + "' no existe en este ambito"));
                return(null); //el record no esta declarado en este scope
            }

            //el menor de la cantidad de campos entre el instanciado y el declarado para no irme de rango en el for
            int min = Math.Min(recordDeclared.Fields.Count, Dict.Count);

            //chequear que concuerden los nombres de los campos y sus tipos de retorno (entre el record declarado y el instanciado)
            for (int i = 0; i < min; i++) //por cada campo
            {
                //chequeo que los nombres sean los mismos
                string keyRecordInstanced = Dict.ElementAt(i).Item1;                  //cojo el nombre del campo i-esimo del record instanciado
                string keyRecordDeclared  = recordDeclared.Fields.ElementAt(i).Item1; //el nombre del campo i-esimo del record declarado
                if (!keyRecordInstanced.Equals(keyRecordDeclared))                    //pregunto si los nombres de los campos son distintos
                {
                    errors.Add(new Error(line, column, "El " + i + "-esimo campo no se llama " + keyRecordDeclared + " sino " + keyRecordInstanced));
                }

                //chequeo que los tipos de los campos sean los mismos
                TypeReturn typeOfParameterDeclared = recordDeclared.Fields.ElementAt(i).Item2; //el tipo del campo i-esimo del record declarado
                if (typeOfParameterDeclared == null)                                           //si es null es porque no se encontro el tipo en este ambito
                {
                    errors.Add(new Error(line, column, "El tipo '" + recordDeclared.Fields.ElementAt(i).Item2 + "' no se encuentra declarado en este ambito"));
                }


                TypeReturn typeOfParameterInstanced = Dict.ElementAt(i).Item2.CheckSemantics(scope_list, errors); //el tipo del campo i-esimo cuando se instancio el record

                if (typeOfParameterInstanced is ReturnNil)                                                        //chequeo si el campo del record instanciado es nil
                {
                    //hay que chequear que el tipo del parametro no sea ni int ni string
                    if (typeOfParameterDeclared is ReturnInt)
                    {
                        errors.Add(new Error(line, column, "Solo se puede asignar nil a un tipo record, array o string"));
                    }
                }
                //pregunto si los TypeReturn de los campos son != de null para que no me de NullException al pedirle el GetType()
                else if (typeOfParameterDeclared != null && typeOfParameterInstanced != null && !typeOfParameterDeclared.GetType().Equals(typeOfParameterInstanced.GetType()))  //pregunto si los tipos de retorno son iguales
                {
                    errors.Add(new Error(line, column, "El record '" + recordDeclared.Record_name + "'. El tipo del campo '" + keyRecordDeclared + "' es '" + typeOfParameterDeclared.ToString() + "' y no '" + typeOfParameterInstanced.ToString() + "'"));
                }
            }

            if (Dict.Count != recordDeclared.Fields.Count) //para saber si los records tienen la misma cantidad de campos
            {
                errors.Add(new Error(line, column, "El record '" + Name + "' no tiene " + Dict.Count + " campos"));
            }

            record = recordDeclared;
            return(recordDeclared); //retorno el mismo record que estaba en el scope
        }
示例#26
0
 public Var_Scope(string name, TypeReturn type)
 {
     Name     = name;
     Var_type = type;
     NoAsign  = false;
 }
        }                                                 //contiene el tipo de retorno de los elementos del array

        public ReturnArray(string array_name, TypeReturn type_of_elements)
        {
            this.Array_name       = array_name;
            this.Type_Of_Elements = type_of_elements;
        }