Verificaciones Semánticas
Verificaciones Semánticas
findType()
Determina el tipo de una expresión:
infoType findType(Node* root) {
if (!root) return NON_TYPE;
switch (root->t_Node) {
case N_TERM: // Literal o variable, retornar el tipo del símbolo
return root->sym->type;
case N_PLUS: // Operadores aritméticos, lógicos e invocaciones a métodos
...
case N_AND: // Retornar el tipo del símbolo o buscar en hijos
if (root->sym) return root->sym->type;
if (root->left) {
infoType type = findType(root->left);
if (type != NON_TYPE) return type;
}
if (root->right) {
infoType type = findType(root->right);
if (type != NON_TYPE) return type;
}
return NON_TYPE; // Si no se encontró un tipo, retorna el valor por defecto (funciona como null)
default:
fprintf(stderr, "Error funcion 'findType()': Nodo del AST no soportado.\n");
exit(EXIT_FAILURE);
}
}
checkParameters()
Valida llamadas a métodos:
int checkParameters(Node* methodCall, Level* symbolTable) {
Symbol* method = getSymbol(symbolTable, methodCall->sym->name);
Symbol* param = method->nextParam;
Symbol* exprList = inOrderExpressionList(methodCall->left, NULL);
// Comparar tipos y cantidad
while (param && currentExpr) {
if (param->type != currentExpr->type) return 0;
param = param->nextParam;
currentExpr = currentExpr->nextParam;
}
// Si quedaron parametros sin argumentos o argumentos sin parametros, no coinciden
if (param || currentExpr) {
freeSymbolList(exprList); // Liberar toda la lista de expresiones
return 0;
}
freeSymbolList(exprList); // Liberar toda la lista de expresiones
return 1; // Los parametros coinciden
}
fullCheck()
Función principal que valida todo el AST:
void fullCheck(Node* root, Stack* stack) {
if (!root || !stack) return;
switch (root->t_Node) {
case N_PROG:
case N_STATEMENT:
// 1. Procesar hijo/s
case N_VAR_DECL:
if (root->sym) {
// 1. Verificar que el tipo de la variable y el de la expresion a asignar sean iguales
// 2. Insertar variable con un nuevo símbolo en la tabla de símbolos
// 3. Liberar memoria del símbolo anterior del ast despues de insertarlo en la tabla de símbolos
// 4. Vincular el símbolo del nodo con el de la tabla de símbolos
} else {
// 1. Si no hay simbolo, es un nodo intermedio que contiene otras declaraciones
// 2. Procesar hijo/s
}
case N_METHOD_DECL:
if (root->sym) {
// 1. Insertar método en la tabla de símbolos
// 2. Copiar los parametros del símbolo del AST al símbolo de la tabla
// 3. Comprobar que el método 'main' no tenga errores
// Error semantico: El método 'main' no debe tener parametros, no puede ser externo.
// debe tener tipo de retorno 'void', solo puede haber un método 'main'.
// 4. Si el método no es externo, analizar su cuerpo
// Los parámetros ya están en newSym, ahora verificarlos
// Analizar las declaraciones del cuerpo del metodo
// 5. Liberar memoria del símbolo anterior del ast déspues de insertarlo en la tabla de símbolos
// 6. Vincular el símbolo del nodo con el de la tabla de símbolos
} else {
// 1. Si no hay simbolo, es un nodo intermedio que contiene otros métodos
// 2. Procesar hijo/s
}
case N_BLOCK:
// 1. Se abre un nuevo nivel de la tabla de símbolos
// 2. Procesar hijo/s
// 3. Se cierra el nuevo nivel de la tabla de símbolos luego de analizar su cuerpo
case N_ASSIGN:
// 1. Procesar los hijos para vincular los símbolos
// 2. Verificar errores
// Error semantico: Variable 'nombre' no declarada. Asignacion con tipos incompatibles.
// Error semantico: El símbolo 'nombre' no es una variable o parametro y no se le puede asignar un valor.
// 3. Liberar memoria del símbolo anterior del ast. Vincular el símbolo del nodo con el de la tabla de símbolos
case N_METHOD_CALL:
// 1. Procesar los argumentos para vincular los símbolos
// 2. Verificar errores
// Error semantico: Metodo 'nombre' no declarado. El símbolo 'nombre' no es un método y no se le puede invocar.
// Error semantico: Llamada a método inexistente 'nombre' o con parametros incorrectos.
// 3. Liberar memoria del símbolo anterior del ast. Vincular el símbolo del nodo con el de la tabla de símbolos
case N_EXPR:
// 1. Es una expresion terminal (constante o variable)
// 2. Variable, buscar en la tabla de símbolos
// Error semantico: Variable 'nombre' no declarada.
// Error semantico: El símbolo 'nombre' no es una variable o parametro y no se puede usar como expresion.
// Liberar memoria del símbolo anterior del ast. Vincular el símbolo del nodo con el de la tabla de símbolos
// 3. Error semantico: El símbolo 'nombre' no es una constante, variable o parametro valido para una expresion.
// 4. Procesar hijo/s
case N_PLUS: case N_MINUS: case N_MULT: case N_DIV: case N_MOD:
case N_LESS: case N_GREAT: case N_EQUAL: case N_AND: case N_OR: case N_NOT: case N_NEG:
// 1. Verificar errores
// Error semantico: Operacion 'nombre operacion' incompleta.
// Error semantico: Variable 'nombre' no declarada.
// Error semantico: Operacion 'nombre operacion' con tipos no enteros o booleanos.
// 2. Establecer el tipo de resultado como entero o booleano
case N_IF:
case N_WHILE:
// 1. Procesar la condición para vincular los símbolos
// 2. Verificar errores
// Error semantico: La expresion condicional 'nombre operacion' no es booleana.
// 3. Procesar hijo/s
case N_THEN:
case N_ELSE:
// Procesar hijo
case N_RETURN:
// 1. Procesar la expresión de retorno si existe
// 2. Verificar errores
// Error de retorno: Tipos incompatibles en el retorno del método y la expresion de retorno.
// Error de retorno: El método debe retornar un valor.
case N_TERM:
// 1. Si no es una constante, buscar en la tabla de símbolos
// 2. Verificar errores
// Error semantico: Variable 'nombre' no declarada.
default:
// Error semantico: Nodo desconocido en el AST
}
}