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