public override void CheckSemantic(Scope scope, List<Error> errors)
        {
            SizeExp.CheckSemantic(scope, errors);
            if (!SizeExp.ReturnType.MatchWith(IntType.IntInstance))
            {
                errors.Add(new Error(SizeExp,"La expresión para definir la longitud de un array debe ser de tipo 'int' y se encontró una expresión de tipo '{0}'", SizeExp.ReturnType));
                HasError = true;
            }
            InitialValueExp.CheckSemantic(scope, errors);
            TigerType myTypeDec = scope.GetType(TypeName);
            if (myTypeDec == null)
            {
                errors.Add(new Error(GetChild(0),"El tipo '{0}' no existe en el ámbito actual", TypeName));
                HasError = true;
                ReturnType = UndefinedType.UndefinedInstance;
            }
            else if (!(myTypeDec is ArrayType))
            {
                errors.Add(new Error(GetChild(0), "El tipo de una expresión de creación de 'array' debe ser de un tipo definido como 'array' y se encontró '{0}'", TypeName));
                HasError = true;
                ReturnType = UndefinedType.UndefinedInstance;
            }
            else if (!InitialValueExp.ReturnType.MatchWith(((ArrayType)myTypeDec).ElementsType))
            {

                errors.Add(new Error(InitialValueExp, "En una expresión de instanciación de un array, el tipo de los elementos del 'array' debe coincidir con la expresión de inicialización y se encontraron expresiones con los tipos '{0}' y '{1}'", ((ArrayType)myTypeDec).ElementsType, InitialValueExp.ReturnType));
                HasError = true;
                ReturnType = UndefinedType.UndefinedInstance;
            }
            else
                ReturnType = myTypeDec;
        }
        public override void CheckSemantic(Scope scope, List<Error> errors)
        {
            if (BuiltInFunctions.Functions.Contains(NameFunction))//marcar la funcion builtin para añadirla al ensamblado
                BuiltInFunctions.UsedFunctions.Add(NameFunction);

            foreach (ExpressionNode realParam in Arguments)
                realParam.CheckSemantic(scope, errors);

            DeclarationNode funDeclaration = scope.GetFunVar(NameFunction);
            if (funDeclaration == null || !(funDeclaration is FunctionDecNode))
            {
                errors.Add(new Error(GetChild(0), "La función '{0}' no está definida en el ámbito actual", NameFunction));
                HasError = true;
                ReturnType = UndefinedType.UndefinedInstance;
            }
            else
            {
                FunDeclaration = (FunctionDecNode)funDeclaration;
                if (FunDeclaration.Arguments.Count == Arguments.Count)
                {
                    for (int i = 0; i < Arguments.Count; i++)
                        if (!FunDeclaration.Arguments[i].RelatedType.MatchWith(Arguments[i].ReturnType))
                        {
                            errors.Add(new Error(Arguments[i], "En el llamado a '{0}' el tipo del parámetro real no. {1} no coincide con el tipo del parámetro formal '{2}'", FunDeclaration.Name, (i + 1), FunDeclaration.Arguments[i].VariableName));
                            HasError = true;
                        }
                }
                else
                {
                    errors.Add(new Error(GetChild(0),"En el llamado a '{0}' la cantidad de parámetros reales no coincide con la de parámetros formales",FunDeclaration.Name));
                    HasError = true;
                }
                ReturnType = funDeclaration.RelatedType;
            }
        }
        public override void CheckSemantic(Scope scope, List<Error> errors)
        {
            Record.CheckSemantic(scope, errors);
            if (Record.ReturnType == UndefinedType.UndefinedInstance)
                ReturnType = UndefinedType.UndefinedInstance;
            else if (!(Record.ReturnType is RecordType))
            {
                errors.Add(new Error(Record,"El operador '.' sólo se puede aplicar a expresiones de un tipo definido como 'record' y se encontró una expresión de tipo '{0}'", Record.ReturnType));
                HasError = true;
                ReturnType = UndefinedType.UndefinedInstance;
            }
            else
            {
                RecordVariableDecNode fieldDec = ((RecordType)Record.ReturnType).GetField(FieldName);
                if (fieldDec == null)
                {

                    errors.Add(new Error(GetChild(0), "El tipo definido como 'record' '{0}' no contiene el miembro '{1}'", Record.ReturnType, FieldName));
                    HasError = true;
                    ReturnType = UndefinedType.UndefinedInstance;
                }
                else
                    ReturnType = fieldDec.RelatedType;
            }
        }
Example #4
0
        public override void CheckSemantic(Scope scope, List<Error> errors)
        {
            LeftValue.CheckSemantic(scope, errors);
            RightExp.CheckSemantic(scope, errors);

            if (LeftValue is VariableNode)
            {
                ForVariableDecNode controlDecl = ((VariableNode)LeftValue).VarDeclaration as ForVariableDecNode;
                if (controlDecl != null)
                {
                    errors.Add(new Error(LeftValue,"La variable de control de una expresión 'for' es de sólo lectura y se está intentando modificar a la variable '{0}'", controlDecl.VariableName));
                    HasError = true;
                }
            }

            if (RightExp.ReturnType == VoidType.VoidInstance)
            {
                errors.Add(new Error(RightExp,"La parte derecha de una expresión de asignación debe retornar un valor y se encontró una expresión de tipo 'void'"));
                HasError = true;
            }
            else if (!LeftValue.ReturnType.MatchWith(RightExp.ReturnType))
            {
                HasError = true;
                errors.Add(new Error(this, "La parte derecha y la parte izquierda de una expresón de asignación deben ser del mismo tipo y se encontraron expresiones con tipos '{0}' y '{1}'", LeftValue.ReturnType, RightExp.ReturnType));
            }

            ReturnType = VoidType.VoidInstance;
        }
Example #5
0
        public override void CheckSemantic(Scope scope, List<Error> errors)
        {
            foreach (ExpressionNode expression in Expressions)
                expression.CheckSemantic(scope, errors);

            if (ReturnType == VoidType.VoidInstance)
                return;
            ReturnType = Expressions.Count == 0 ? VoidType.VoidInstance : Expressions[Expressions.Count - 1].ReturnType;
        }
Example #6
0
 public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     Value = EscapeText(Text);
     if (Value == null)
     {
         errors.Add(new Error(this,"La cadena contiene una secuencia de escape incorrecta"));
         HasError = true;
     }
     ReturnType = StringType.StringInstance;
 }
Example #7
0
        public override void CheckSemantic(Scope scope, List<Error> errors)
        {
            Scope current = new Scope(scope);

            foreach (DeclarationsSequence dec in Declarations)
                dec.CheckSemantic(current, errors);

            Expressions.CheckSemantic(current, errors);
            ReturnType = Expressions.ReturnType;
        }
Example #8
0
 public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     Operand.CheckSemantic(scope, errors);
     if (!Operand.ReturnType.MatchWith(IntType.IntInstance))
     {
         errors.Add(new Error(Operand, "El operando del operador unario '-' debe ser de tipo 'int' y se encontró una expresión de tipo '{0}'", Operand.ReturnType));
         HasError = true;
     }
     ReturnType = IntType.IntInstance;
 }
 public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     InitialExp.CheckSemantic(scope.Parent, errors);
     if (!InitialExp.ReturnType.MatchWith(IntType.IntInstance))
     {
         errors.Add(new Error(InitialExp, "En una expresión 'for' la expresión de inicialización debe ser de tipo 'int' y se encontró una expresión de tipo '{0}'",InitialExp.ReturnType));
         HasError = true;
     }
     RelatedType = IntType.IntInstance;
     scope.AddFunVar(VariableName, this);
 }
Example #10
0
 public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     ReturnType = IntType.IntInstance;
     int value;
     if (!int.TryParse(Text, out value))
     {
         errors.Add(new Error(this, "El número '{0}' es demasiado grande para ser convertido a 'int'", Text));
         HasError = true;
     }
     Value = value;
 }
 public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     LeftOperand.CheckSemantic(scope, errors);
     RightOperand.CheckSemantic(scope, errors);
     if (!LeftOperand.ReturnType.MatchWith(RightOperand.ReturnType))
     {
         errors.Add(new Error(this,"Los operandos del operador binario '{0}' deben ser del mismo tipo y se encontraron expresiones con los tipos '{1}' y '{2}'",Text, LeftOperand.ReturnType, RightOperand.ReturnType));
         HasError = true;
     }
     ReturnType = IntType.IntInstance;
 }
        public override void CheckSemantic(Scope scope, List<Error> errors)
        {
            //la comprobacion de si hay algun campo repetido se hace en el RecordDecNode

            RelatedType = scope.GetType(TypeName);
            if (RelatedType == null)
            {
                errors.Add(new Error(GetChild(1),"El tipo '{0}' no está definido en el ámbito actual", TypeName));
                HasError = true;
                RelatedType = UndefinedType.UndefinedInstance;
            }
        }
 public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     DeclarationNode funDeclaration = scope.GetFunVar(VariableName, false);
     //El tipo del parametro se determino en el chequeo de semantica de la secuencia de declaraciones de funciones
     if (funDeclaration != null)
     {
         errors.Add(new Error(this, "Se han definido dos o más parámetros con el nombre '{0}' dentro de la función", VariableName));
         HasError = true;
     }
     else
         scope.AddFunVar(VariableName, this);
 }
 public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     LeftOperand.CheckSemantic(scope, errors);
     RightOperand.CheckSemantic(scope, errors);
     //si no se cumple que los dos son int o los dos son string => error
     if ( !((LeftOperand.ReturnType.MatchWith(IntType.IntInstance) && RightOperand.ReturnType.MatchWith(IntType.IntInstance)) ||
            (LeftOperand.ReturnType.MatchWith(StringType.StringInstance) && RightOperand.ReturnType.MatchWith(StringType.StringInstance))))
     {
         errors.Add(new Error(this, "Los dos operandos del operador binario '{0}' deben ser del mismo tipo y este ha de ser 'int' o 'string', y se econtraron expresiones con los tipos '{1}' y '{2}'",Text, LeftOperand.ReturnType, RightOperand.ReturnType));
         HasError = true;
     }
     ReturnType = IntType.IntInstance;
 }
Example #15
0
 public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     //es añadido al scope en el CheckSemantic del TypeDeclarationSecuence si no esta redefinido incorrectamente
     TigerType elementsType = scope.GetType(ElementsTypeName);
     if (elementsType == null)
     {
         errors.Add(new Error(GetChild(1), "El tipo '{0}' no está definido en el ámbito actual", ElementsTypeName));
         HasError = true;
         RelatedType = new ArrayType(UndefinedType.UndefinedInstance, ElementsTypeName);
     }
     else
         RelatedType = new ArrayType(elementsType, ElementsTypeName);
 }
Example #16
0
        public override void CheckSemantic(Scope scope, List<Error> errors)
        {
            //es añadido al scope en el CheckSemantic del TypeDeclarationSecuence si no esta redefinido incorrectamente
            //RelatedType se inicializa en el CheckSemantic del TypeDeclarationSecuence: 'RelatedType = new Record()'
            if (TypeName.CompareTo("int") == 0 || TypeName.CompareTo("string") == 0)
                errors.Add(new Error(GetChild(0),"El tipo '{0}' está definido en la Biblioteca Estándar de Tiger y no puede ser redefinido", TypeName));

            foreach (RecordVariableDecNode field in Fields)
            {
                field.CheckSemantic(scope, errors);
                if (!((RecordType)RelatedType).AddMember(field.VariableName, field))
                    errors.Add(new Error(field.GetChild(0), "No es posible definir una campo con el nombre '{0}' debido a que existe otro campo con igual nombre dentro del mismo 'record'", field.VariableName));
            }
        }
Example #17
0
        public override void CheckSemantic(Scope scope, List<Error> errors)
        {
            //es añadido al scope en el CheckSemantic del TypeDeclarationSecuence si no esta redefinido incorrectamente
            if (TypeName.CompareTo("int") == 0 || TypeName.CompareTo("string") == 0)
                errors.Add(new Error(GetChild(0), "El tipo '{0}' está definido en la Biblioteca Estándar de Tiger y no puede ser redefinido", TypeName));

            RelatedType = scope.GetType(BaseTypeName);
            if (RelatedType == null)
            {
                errors.Add(new Error(GetChild(1), "El tipo '{0}' no está definido en el ámbito actual", BaseTypeName));
                HasError = true;
                RelatedType = UndefinedType.UndefinedInstance;
            }
        }
        public override void CheckSemantic(Scope scope, List<Error> errors)
        {
            TigerType type = scope.GetType(TypeName);
            if (type == null)
            {
                errors.Add(new Error(GetChild(0), "El tipo '{0}' no está definido en el ámbito atual", TypeName));
                HasError = true;
                ReturnType = UndefinedType.UndefinedInstance;
                return;
            }

            RecordType recordType = type as RecordType;
            if (recordType == null)
            {
                errors.Add(new Error(GetChild(0), "El tipo de una expresión de creación de 'record' debe ser de un tipo definido como 'record' y se encontró '{0}'", TypeName));
                HasError = true;
                ReturnType = UndefinedType.UndefinedInstance;
                return;
            }

            ReturnType = recordType;
            for (int i = 0; i < Fields.Count; i++)
            {
                FieldExpPair member = Fields[i];
                member.CheckSemantic(scope, errors);
                string realName;
                RecordVariableDecNode memberDec = recordType.GetField(i,out realName);
                if (realName == null)
                {
                    errors.Add(
                        new Error(member.GetChild(0),"El tipo definido como 'record' '{0}' no tiene definido un campo no. {1}", TypeName,(i + 1)));
                    HasError = true;
                }
                else if (realName.CompareTo(member.Name) != 0)
                {
                    errors.Add(
                        new Error(member.GetChild(0),"El campo no. {0} del tipo definido como 'record' '{1}' no se declaró con el nombre '{2}' sino con el nombre '{3}'",
                                  (i + 1), TypeName, member.Name, realName));
                    HasError = true;
                }
                else if (!member.Exp.ReturnType.MatchWith(memberDec.RelatedType))
                {
                    errors.Add(
                        new Error(member.Exp,
                            "En una expresión de creación de un 'record' el tipo de cada campo debe coincidir con el tipo de su expresión de inicialización y en el campo '{0}' se encontraron los tipos '{1}' y '{2}'", member.Name, memberDec.RelatedType, member.Exp.ReturnType));
                    HasError = true;
                }
            }
        }
Example #19
0
 public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     DeclarationNode varDeclaration = scope.GetFunVar(Name);
     if (varDeclaration == null || !(varDeclaration is VariableDecNode))
     {
         errors.Add(new Error(GetChild(0),"La variable '{0}' no está definida",Name));
         HasError = true;
         ReturnType = UndefinedType.UndefinedInstance;
     }
     else
     {
         ReturnType = varDeclaration.RelatedType;
         VarDeclaration = (VariableDecNode)varDeclaration;
     }
 }
 public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     LeftOperand.CheckSemantic(scope, errors);
     RightOperand.CheckSemantic(scope, errors);
     if (!LeftOperand.ReturnType.MatchWith(IntType.IntInstance))
     {
         errors.Add(new Error(LeftOperand, "El operando izquierdo del operador binario '{0}' debe ser de tipo 'int' y se encontró una expresión de tipo '{1}'", Text, LeftOperand.ReturnType));
         HasError = true;
     }
     if(!RightOperand.ReturnType.MatchWith(IntType.IntInstance))
     {
         errors.Add(new Error(RightOperand, "El operando derecho del operador binario '{0}' debe ser de tipo 'int' y se encontró una expresión de tipo '{1}'", Text, RightOperand.ReturnType));
         HasError = true;
     }
     ReturnType = IntType.IntInstance;
 }
Example #21
0
 public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     ConditionExp.CheckSemantic(scope, errors);
     if (!ConditionExp.ReturnType.MatchWith(IntType.IntInstance))
     {
         errors.Add(new Error(ConditionExp, "La condición de la expresión 'if-then' debe ser una expresión de tipo 'int' y se encontró una expresión de tipo '{0}'", ConditionExp.ReturnType));
         HasError = true;
     }
     ThenExp.CheckSemantic(scope, errors);
     if (!ThenExp.ReturnType.MatchWith(VoidType.VoidInstance))
     {
         errors.Add(new Error(ThenExp, "La expresión 'then' en una expresión 'if-then' no puede devolver ningún valor y se encontró una expresión de tipo '{0}'", ThenExp.ReturnType));
         HasError = true;
     }
     ReturnType = VoidType.VoidInstance;
 }
 public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     InitialExp.CheckSemantic(scope, errors);
     //se pone por defecto con error y de tipo indefinido para factorizar
     HasError = true;
     RelatedType = UndefinedType.UndefinedInstance;
     if (TypeName != null) //se conoce el tipo de la variable
     {
         TigerType formalType = scope.GetType(TypeName);
         if (formalType == null) //el tipo formal no esta definido
             errors.Add(new Error(GetChild(2),"El tipo '{0}' no ha sido definido en el ámbito actual", TypeName));
         else
             if (!InitialExp.ReturnType.MatchWith(formalType)) //el tipo real no coincide con el formal
             {
                 errors.Add(new Error(InitialExp, "En una declaración el tipo de variable debe coincidir con el tipo de la expresión de inicialización y se encontró el tipo '{0}' y una expresión de tipo '{1}'", formalType, InitialExp.ReturnType));
                 RelatedType = formalType; // En C# si se declara 'string a = 5' se asume que 'a' es de tipo 'string' aunque no machee
             }
             else //si entra aqui es que no hay error
             {
                 HasError = false;
                 RelatedType = formalType;
             }
     }
     else //se debe inferir el tipo de la variable
     {
         if (InitialExp.ReturnType == NillType.NillInstance)
             errors.Add(new Error(InitialExp,"No es posible inferir el tipo de la variable '{0}' debido a que la expresión de inicialización es de tipo 'nil'",VariableName));
         else if (InitialExp.ReturnType.MatchWith(VoidType.VoidInstance))
             errors.Add(new Error(InitialExp,"No es posible inferir el tipo de la variable debido a que la expresión de inicialización es de tipo 'void'"));
         else //si entra aqui es que no hay error
         {
             HasError = false;
             RelatedType = InitialExp.ReturnType;
         }
     }
     DeclarationNode varDeclaretions = scope.GetFunVar(VariableName, false);
     if (varDeclaretions != null)
     {
         if (varDeclaretions is VariableDecNode)
             errors.Add(new Error(GetChild(0),"No es posible definir una variable con el nombre '{0}' debido a que existe otra variable con igual nombre dentro del mismo 'let'",VariableName));
         else
             errors.Add(new Error(GetChild(0),"No es posible definir una variable con el nombre '{0}' debido a que existe una función con igual nombre dentro del mismo 'let'", VariableName));
         HasError = true;
     }
     else
         scope.AddFunVar(VariableName, this);
 }
Example #23
0
 public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     ConditionExp.CheckSemantic(scope, errors);
     if (!ConditionExp.ReturnType.MatchWith(IntType.IntInstance))
     {
         errors.Add(new Error(ConditionExp, "La condición de la expresión 'if-then-else' debe ser una expresión de tipo 'int' y se encontró una expresión de tipo '{0}'", ConditionExp.ReturnType));
         HasError = true;
     }
     ThenExp.CheckSemantic(scope, errors);
     ElseExp.CheckSemantic(scope, errors);
     if (!ThenExp.ReturnType.MatchWith(ElseExp.ReturnType))
     {
         errors.Add(new Error(this, "Las expresiones 'then' y 'else' de una expresión 'if-then-else' deben ser del mismo tipo y se encontraron expresiones con los tipos '{1}' y '{2}'", Text, ThenExp.ReturnType, ElseExp.ReturnType));
         HasError = true;
         ReturnType = UndefinedType.UndefinedInstance;
     }
     else
         ReturnType = ThenExp.ReturnType is UndefinedType ? ElseExp.ReturnType : ThenExp.ReturnType;
 }
Example #24
0
        public override void CheckSemantic(Scope scope, List<Error> errors)
        {
            //el tipo del valor de retorno se determino en el chequeo de semantica de la secuencia de declaraciones de funciones
            scope = new Scope(scope);

            for (int index = 0; index < Arguments.Count; index++)
            {
                FunctionVariableDecNode paramDecl = Arguments[index];
                paramDecl.Index = index;
                paramDecl.CheckSemantic(scope, errors);
            }

            BodyExp.CheckSemantic(scope, errors);

            if (!RelatedType.MatchWith(BodyExp.ReturnType))
            {
                errors.Add(new Error(GetChild(2),"El tipo de retorno del cuerpo de la función no coincide con el tipo definido"));
                HasError = true;
            }
        }
Example #25
0
        public override void CheckSemantic(Scope scope, List<Error> errors)
        {
            Array.CheckSemantic(scope, errors);
            if (Array.ReturnType is ArrayType)
                ReturnType = ((ArrayType)Array.ReturnType).ElementsType;
            else if(Array.ReturnType == UndefinedType.UndefinedInstance)
                ReturnType = UndefinedType.UndefinedInstance;
            else
            {
                errors.Add(new Error(Array, "El operador '[]' sólo se puede aplicar a expresiones de un tipo definido como 'array' y se encontró una expresión de tipo '{0}'", Array.ReturnType));
                HasError = true;
                ReturnType = UndefinedType.UndefinedInstance;
            }

            AccessExp.CheckSemantic(scope, errors);
            if (!AccessExp.ReturnType.MatchWith(IntType.IntInstance))
            {
                errors.Add(new Error(AccessExp,"La expresión de indización en una expresión de acceso a 'array' debe ser de tipo 'int' y se encontró una expresión de tipo '{0}'", AccessExp.ReturnType));
                HasError = true;
            }
        }
Example #26
0
        public override void CheckSemantic(Scope scope, List<Error> errors)
        {
            var forScope = new Scope(scope);

            InitExp.CheckSemantic(forScope, errors);
            UpperBoundExp.CheckSemantic(scope, errors);
            BodyExp.CheckSemantic(forScope, errors);

            if (!UpperBoundExp.ReturnType.MatchWith(IntType.IntInstance))
            {
                errors.Add(new Error(UpperBoundExp,"La expresión 'to' de una expresión de 'for' debe ser de tipo 'int' y se encontró una expresión de tipo '{0}'", UpperBoundExp.ReturnType));
                HasError = true;
            }

            if (!BodyExp.ReturnType.MatchWith(VoidType.VoidInstance))
            {
                errors.Add(new Error(BodyExp, "El cuerpo de una instrucción 'for' debe ser una expresión de tipo 'void' y se encontró una expresión de tipo de tipo '{0}'", BodyExp.ReturnType));
                HasError = true;
            }

            ReturnType = VoidType.VoidInstance;
        }
Example #27
0
 public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     ReturnType = VoidType.VoidInstance;
     ITree actual = this;
     while (true)
     {
         if (actual.Parent == null || actual.Parent is FunctionDecNode)
         {
             errors.Add(new Error(this,"Una expresión 'break' sólo puede ser utilizada en el cuerpo de una expresión iterativa 'for' o 'while'"));
             HasError = true;
             return;
         }
         if (actual.Parent is IterativeNode && actual == ((IterativeNode)actual.Parent).BodyExp)
         {
             IterativeNode = ((IterativeNode)actual.Parent);
             return;
         }
         if (actual.Parent is ListExpNode)
             ((ListExpNode)actual.Parent).ReturnType = VoidType.VoidInstance;
         actual = actual.Parent;
     }
 }
Example #28
0
 public abstract void CheckSemantic(Scope scope, List<Error> errors);
        public override void CheckSemantic(Scope scope, List<Error> errors)
        {
            #region declaracion de variables utilizadas
            HashSet<string> typesNames = new HashSet<string>();
            var graphNodes = new Dictionary<string, TypeDecNode>();
            List<RecordDecNode> firstsRecordDecs = new List<RecordDecNode>();
            List<TypeDecNode> redefinedDecs = new List<TypeDecNode>();
            Dictionary<string, List<string>> reverseGraph;
            Dictionary<string, List<string>> graph;
            #endregion

            #region detectar redefiniciones y almacenar para procesarlas, añadir records no repetidos al scope, detectar nodos del grafo
            foreach (TypeDecNode typeDec in Declarations)
                if (scope.GetType(typeDec.TypeName,false) != null || !typesNames.Add(typeDec.TypeName))//detectar redefiniciones y almacenar para procesarlos al final
                {
                    errors.Add(new Error(typeDec.GetChild(0),"No es posible definir un tipo con el nombre '{0}' debido a que existe otro tipo con igual nombre dentro de un mismo 'let'", typeDec.TypeName));
                    HasError = true;
                    if (typeDec is RecordDecNode)
                        typeDec.RelatedType = new RecordType(typeDec.TypeName);
                    redefinedDecs.Add(typeDec);
                }
                else if (typeDec is RecordDecNode)//poner el tipo y añadir al scope
                {
                    firstsRecordDecs.Add((RecordDecNode)typeDec);
                    typeDec.RelatedType = new RecordType(typeDec.TypeName);
                    scope.AddType(typeDec.TypeName, typeDec.RelatedType);
                }
                else //es alias o array
                    graphNodes.Add(typeDec.TypeName, typeDec); //añadir el nodo al grafo
            #endregion

            #region añadir las aristas al grafo y al reverso del grafo a partir de los nodos del grafo
            CreateGraph(graphNodes, out graph, out reverseGraph);
            #endregion

            #region detectar nodos que pertenecen a ciclos usando SCC y procesarlos
            List<List<string>> scc = SCC(graph, reverseGraph);

            foreach (var component in scc)
                //si la componente tiene mas de un nodo || tiene un nodo con una referencia a si mismo (los nodos tienen siempre 0 o 1 referenecia)
                if (component.Count > 1 || (graph[component[0]].Count == 1 && graph[component[0]][0].CompareTo(component[0]) == 0)) //todos los nodos de la componente son invalidos
                    foreach (string s in component)
                    {
                        TypeDecNode node = graphNodes[s];
                        graphNodes.Remove(s); //eliminar s del grafo para convertirlo en un DAG
                        //reportar error
                        errors.Add(new Error(node.GetChild(0),"El tipo '{0}' está definido en función de si mismo",s));
                        //procesar los nodos invalidos
                        if (node is AliasDecNode)//alias -> RelatedType = Undef
                            node.RelatedType = UndefinedType.UndefinedInstance;
                        if (node is ArrayDecNode)//array -> RelatedType = new Array(Undef)
                            node.RelatedType = new ArrayType(UndefinedType.UndefinedInstance, node.TypeName);
                        scope.AddType(s,node.RelatedType);
                    }

            #endregion

            #region hallar el subgrafo que es un DAG y hacer order topologico invertido
            CreateGraph(graphNodes, out graph, out reverseGraph, false); //el reverso no es necesario en este caso
            List<string> order = ReversedTopologicalSort(graph);
            #endregion

            #region chequear semantica de los nodos en el orden topologico invertido y añadirlos al scope
            foreach (string s in order)
            {
                var node = graphNodes[s];
                node.CheckSemantic(scope, errors);
                scope.AddType(s,node.RelatedType);
            }

            #endregion

            #region chequear semantica de los records
            foreach (var recordDec in firstsRecordDecs)
                recordDec.CheckSemantic(scope, errors); //ya se añadieron al scope
            #endregion

            #region chequear semantica de los repetidos
            foreach (var redefinedDec in redefinedDecs)
                redefinedDec.CheckSemantic(scope, errors); //no se añaden al scope pq estan repetidos
            #endregion
        }
        public override void CheckSemantic(Scope scope, List<Error> errors)
        {
            foreach (FunctionDecNode funcDec in Declarations)
            {
                #region determinar el tipo de retorno
                if (funcDec.ReturnTypeName == null) // es un procedure
                    funcDec.RelatedType = VoidType.VoidInstance;
                else // es una function
                {
                    TigerType funType = scope.GetType(funcDec.ReturnTypeName);
                    if (funType == null)
                    {
                        errors.Add(
                            new Error(funcDec.GetChild(0),
                                "El tipo '{0}' no está definido en el ámbito actual", funcDec.ReturnTypeName));
                        HasError = true;
                        funcDec.RelatedType = UndefinedType.UndefinedInstance;
                    }
                    else
                        funcDec.RelatedType = funType;
                }

                #endregion

                #region determinar el tipo de cada parametro
                foreach (FunctionVariableDecNode paramDecl in funcDec.Arguments)
                {
                    TigerType paramType = scope.GetType(paramDecl.TypeName);
                    if (paramType == null)
                    {
                        paramDecl.RelatedType = UndefinedType.UndefinedInstance;
                        HasError = true;
                        errors.Add(new Error(paramDecl.GetChild(0),"El tipo '{0}' no está definido en el ámbito actual", paramDecl.TypeName));
                    }
                    else
                        paramDecl.RelatedType = paramType;
                }
                #endregion

                #region añadir la funcion al scope si no esta repetida

                DeclarationNode funDeclarations = scope.GetFunVar(funcDec.Name, false);
                if (funDeclarations != null)
                {
                    if (funDeclarations is FunctionDecNode)
                        errors.Add(new Error(funcDec.GetChild(0),"No es posible definir una función con el nombre '{0}' debido a que existe otra función con igual nombre dentro de un mismo 'let'", funcDec.Name));
                    else
                        errors.Add(new Error(funcDec.GetChild(0), "No es posible definir una función con el nombre '{0}' debido a que existe una variable con igual nombre dentro de un mismo 'let'", funcDec.Name));
                    HasError = true;
                }
                else if (BuiltInFunctions.Functions.Contains(funcDec.Name))
                {
                    errors.Add(new Error(funcDec.GetChild(0),"La función '{0}' está definida en la Biblioteca Estándar de Tiger y no puede ser redefinida", funcDec.Name));
                    HasError = true;
                }
                else
                    scope.AddFunVar(funcDec.Name, funcDec);
                #endregion
            }
            foreach (FunctionDecNode funcDecl in Declarations)
                funcDecl.CheckSemantic(scope, errors);
        }