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) { //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) { //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); }
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; } } }
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); }
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); }