📄 semanticchecker.c
字号:
/**************************************************************************** * File name: semanticChecker.c * * Description: semantic checker for decafc * * Input: none * * Output: none * * Author: Luojian Chen * * Date: April 16, 1997 * ****************************************************************************/#include "semanticChecker.h"extern SymbolTablePtr typeSymbolTable;extern NodePtr rootNodePtr;extern NodePtr mainMethodDecNodePtr;extern ElementPtr Insert(SymbolTablePtr, String, int, ElementPtr);extern ElementPtr Lookup(SymbolTablePtr, String);extern void DisplaySymbolTable(SymbolTablePtr);extern void ReportError(ErrorIndex, String, int, int);ElementPtr intTypePtr = NULL;ElementPtr voidTypePtr = NULL;ElementPtr refTypePtr = NULL;ElementPtr unknownTypePtr = NULL;NodePtr mainClassDecNodePtr = NULL;void SemanticCheck(NodePtr);void CreateNewArrayType(NodePtr);NodePtr ClassNodeOfType(ElementPtr);Boolean IsArrayType(ElementPtr);static ElementPtr currentMethodReturnTypePtr = NULL;static NodePtr currentMethodDecNodePtr = NULL;static NodePtr lastNameNodePtr = NULL;static void CheckClassDec(NodePtr);static void CheckVarDecList(NodePtr, SymbolTablePtr, Boolean);static void CheckConstructorDec(NodePtr, NodePtr);static void CheckMethodDec(NodePtr, NodePtr);static void CheckVarDec(NodePtr, SymbolTablePtr, int, Boolean);static ElementPtr CheckReturnType(NodePtr);static void CheckParameterList(NodePtr, SymbolTablePtr);static void CheckBlock(NodePtr, NodePtr);static void CheckStatementList(NodePtr, NodePtr, SymbolTablePtr);static void CheckStatement(NodePtr, NodePtr, SymbolTablePtr);static void CheckAssignmentStatement(NodePtr, NodePtr, SymbolTablePtr);static ElementPtr CheckName(NodePtr, NodePtr, Boolean, SymbolTablePtr);static ElementPtr CheckExpression(NodePtr, NodePtr, SymbolTablePtr);static ElementPtr CheckIdentifier(NodePtr, NodePtr, Boolean, SymbolTablePtr);static ElementPtr CheckArrayAccess(NodePtr, NodePtr, Boolean, SymbolTablePtr);static ElementPtr CheckNewExpression(NodePtr, NodePtr, SymbolTablePtr);static ElementPtr CheckFunctionCall(NodePtr, NodePtr, SymbolTablePtr);static ElementPtr CheckMethodCall(NodePtr, NodePtr, Boolean, SymbolTablePtr, String *, NodePtr *);static ElementPtr CheckMethodName(NodePtr, NodePtr, String *, NodePtr *);static void CheckArgList(NodePtr, NodePtr, NodePtr, Boolean, SymbolTablePtr);static void CheckExpressionMeaning(NodePtr);static Boolean IsRelationExpression(NodePtr);static Boolean IsCheckedMethodDec(NodePtr);static Boolean IsPrimitiveType(ElementPtr);static Boolean IsEquivalentType(ElementPtr, ElementPtr);static Boolean DefinedBeforeUse(NodePtr, ElementPtr);static int DimensionOfType(ElementPtr);static ElementPtr TypeOfArrayAcess(ElementPtr, int);static ElementPtr GetNewArrayType(NodePtr);void SemanticCheck(NodePtr rootNodePtr){ int i; NodePtr classNodePtr = NULL; if (rootNodePtr == NULL) { return; } for (i = 0; i < rootNodePtr->children[0]->numberOfChildren; i ++) { classNodePtr = rootNodePtr->children[0]->children[i]; CheckClassDec(classNodePtr); #ifdef DEBUG printf("In SemanticCheck, symbol table for class %s:\n", classNodePtr->children[0]->info.lexeme); DisplaySymbolTable(classNodePtr->info.symbolTablePtr); #endif }}void CreateNewArrayType(NodePtr nodePtr){ NodePtr childNodePtr = NULL; String typeName = NULL; ElementPtr typePtr = NULL; childNodePtr = nodePtr->children[0]; if (childNodePtr->numberOfChildren == 0) { childNodePtr->typePtr = Lookup(typeSymbolTable, childNodePtr->info.lexeme); if (childNodePtr->typePtr == NULL) { ReportError(ERROR_UNDEFINED_TYPE, childNodePtr->info.lexeme, childNodePtr->lineNumber, childNodePtr->columnNumber); childNodePtr->typePtr = unknownTypePtr; nodePtr->typePtr = unknownTypePtr; } else { typePtr = childNodePtr->typePtr; if (IsPrimitiveType(typePtr) == FALSE) { if (DefinedBeforeUse(nodePtr, typePtr) == FALSE) { ReportError(ERRROR_TYPE_USED_BEFORE_DEFINITION, childNodePtr->info.lexeme, childNodePtr->lineNumber, childNodePtr->columnNumber); } } typeName = (String)malloc(strlen(childNodePtr->info.lexeme) + 2 + 1); strcpy(typeName, childNodePtr->info.lexeme); strcat(typeName, STRING_SQUARE_BRACKETS); nodePtr->info.lexeme = typeName; nodePtr->typePtr = Lookup(typeSymbolTable, typeName); if (nodePtr->typePtr == NULL) { nodePtr->typePtr = Insert(typeSymbolTable, typeName, 0, typePtr); } } } else { CreateNewArrayType(childNodePtr); typePtr = childNodePtr->typePtr; if (typePtr == unknownTypePtr) { nodePtr->typePtr = unknownTypePtr; } else { typeName = (String)malloc(strlen(typePtr->id) + 2 + 1); strcpy(typeName, typePtr->id); strcat(typeName, STRING_SQUARE_BRACKETS); nodePtr->info.lexeme = typeName; nodePtr->typePtr = Lookup(typeSymbolTable, typeName); if (nodePtr->typePtr == NULL) { nodePtr->typePtr = Insert(typeSymbolTable, typeName, 0, typePtr); } } }}NodePtr ClassNodeOfType(ElementPtr typePtr){ int i; NodePtr classDecListNodePtr = NULL; NodePtr classDecNodePtr = NULL; classDecListNodePtr = rootNodePtr->children[0]; for (i = 0; i < classDecListNodePtr->numberOfChildren; i ++) { classDecNodePtr = classDecListNodePtr->children[i]; if (classDecNodePtr->typePtr == typePtr) { return(classDecNodePtr); } } return(NULL);}Boolean IsArrayType(ElementPtr typePtr){ if (typePtr->typePtr != NULL) { return(TRUE); } else { return(FALSE); }}static void CheckClassDec(NodePtr classNodePtr){ int i; NodePtr classBodyNodePtr = NULL; NodePtr methodDecNodePtr = NULL; if (classNodePtr == NULL) { return; } classBodyNodePtr = classNodePtr->children[1]; CheckVarDecList(classBodyNodePtr->children[0], classNodePtr->info.symbolTablePtr, TRUE); CheckConstructorDec(classNodePtr, classBodyNodePtr->children[1]); if (classBodyNodePtr->children[2] != NULL) { for (i = 0; i < classBodyNodePtr->children[2]->numberOfChildren; i ++) { methodDecNodePtr = classBodyNodePtr->children[2]->children[i]; CheckMethodDec(classNodePtr, methodDecNodePtr); } }}static void CheckVarDecList(NodePtr varDecListNodePtr, SymbolTablePtr symbolTablePtr, Boolean isClassVar){ int i; NodePtr varDecNodePtr = NULL; if (varDecListNodePtr == NULL) { return; } for (i = 0; i < varDecListNodePtr->numberOfChildren; i ++) { varDecNodePtr = varDecListNodePtr->children[i]; if (varDecNodePtr == NULL) { continue; } CheckVarDec(varDecNodePtr, symbolTablePtr, i, isClassVar); }}static void CheckConstructorDec(NodePtr classNodePtr, NodePtr constructorNodePtr){ String className = NULL; if (constructorNodePtr == NULL) { return; } className = classNodePtr->children[0]->info.lexeme; currentMethodReturnTypePtr = classNodePtr->typePtr; if ((className == NULL) || (strcmp(className, constructorNodePtr->children[0]->info.lexeme) != 0)) { ReportError(ERROR_BAD_CONSTRUCTOR_NAME, constructorNodePtr->children[0]->info.lexeme, constructorNodePtr->children[0]->lineNumber, constructorNodePtr->children[0]->columnNumber); } CheckParameterList(constructorNodePtr->children[1], constructorNodePtr->info.symbolTablePtr); CheckBlock(classNodePtr, constructorNodePtr->children[2]);}static void CheckMethodDec(NodePtr classNodePtr, NodePtr methodDecNodePtr){ String className = NULL; if (methodDecNodePtr == NULL) { return; } if (methodDecNodePtr == mainMethodDecNodePtr) { mainClassDecNodePtr = classNodePtr; } className = classNodePtr->children[0]->info.lexeme; #ifdef DEBUG printf("In CheckMethodDec(), symbol table is:\n"); DisplaySymbolTable(methodDecNodePtr->info.symbolTablePtr); #endif if ((className != NULL) && (strcmp(className, methodDecNodePtr->children[1]->info.lexeme) == 0)) { ReportError(ERROR_BAD_METHOD_NAME, methodDecNodePtr->children[1]->info.lexeme, methodDecNodePtr->children[1]->lineNumber, methodDecNodePtr->children[1]->columnNumber); } if (IsCheckedMethodDec(methodDecNodePtr) == FALSE) { methodDecNodePtr->typePtr = CheckReturnType(methodDecNodePtr->children[0]); CheckParameterList(methodDecNodePtr->children[2], methodDecNodePtr->info.symbolTablePtr); } currentMethodReturnTypePtr = methodDecNodePtr->typePtr; CheckBlock(classNodePtr, methodDecNodePtr->children[3]);}static void CheckVarDec(NodePtr varDecNodePtr, SymbolTablePtr symbolTablePtr, int offset, Boolean isClassVar){ NodePtr typeNodePtr = NULL; NodePtr varNodePtr = NULL; ElementPtr elementPtr = NULL; if (varDecNodePtr == NULL) { return; } typeNodePtr = varDecNodePtr->children[0]; varNodePtr = varDecNodePtr->children[1]; if (typeNodePtr->numberOfChildren > 0) { CreateNewArrayType(typeNodePtr); varNodePtr->typePtr = typeNodePtr->typePtr; elementPtr = Lookup(symbolTablePtr, varNodePtr->info.lexeme); elementPtr->typePtr = varNodePtr->typePtr; } else { #ifdef DEBUG printf("In CheckVarDec(), Lookup type `%s'\n", typeNodePtr->info.lexeme); #endif typeNodePtr->typePtr = Lookup(typeSymbolTable, typeNodePtr->info.lexeme); if (typeNodePtr->typePtr == NULL) { ReportError(ERROR_UNDEFINED_TYPE, typeNodePtr->info.lexeme, typeNodePtr->lineNumber, typeNodePtr->columnNumber); varNodePtr->typePtr = unknownTypePtr; } else { varNodePtr->typePtr = typeNodePtr->typePtr; if (IsPrimitiveType(typeNodePtr->typePtr) == FALSE) { if (DefinedBeforeUse(typeNodePtr, typeNodePtr->typePtr) == FALSE) { ReportError(ERRROR_TYPE_USED_BEFORE_DEFINITION, typeNodePtr->info.lexeme, typeNodePtr->lineNumber, typeNodePtr->columnNumber); } } } elementPtr = Lookup(symbolTablePtr, varNodePtr->info.lexeme); elementPtr->typePtr = varNodePtr->typePtr; /* if (isClassVar == TRUE) { elementPtr->offset = offset + FIRST_CLASS_VAR_OFFSET; } else { elementPtr->offset = offset - 1 + FIRST_LOCAL_VAR_OFFSET; } */ }}static ElementPtr CheckReturnType(NodePtr typeNodePtr){ if (typeNodePtr == NULL) { return; } if (typeNodePtr->numberOfChildren > 0) { CreateNewArrayType(typeNodePtr); } else { #ifdef DEBUG printf("In CheckReturnType(), Lookup type `%s'\n", typeNodePtr->info.lexeme); #endif typeNodePtr->typePtr = Lookup(typeSymbolTable, typeNodePtr->info.lexeme); if (typeNodePtr->typePtr == NULL) { ReportError(ERROR_UNDEFINED_TYPE, typeNodePtr->info.lexeme, typeNodePtr->lineNumber, typeNodePtr->columnNumber); typeNodePtr->typePtr = unknownTypePtr; } else { if (IsPrimitiveType(typeNodePtr->typePtr) == FALSE) { if (DefinedBeforeUse(typeNodePtr, typeNodePtr->typePtr) == FALSE) { ReportError(ERRROR_TYPE_USED_BEFORE_DEFINITION, typeNodePtr->info.lexeme, typeNodePtr->lineNumber, typeNodePtr->columnNumber); } } } } return(typeNodePtr->typePtr);}static void CheckParameterList(NodePtr parameterListNodePtr, SymbolTablePtr symbolTablePtr){ int i; if (parameterListNodePtr == NULL) { return; } #ifdef DEBUG printf("In CheckParameterList(), symbol table is:\n"); DisplaySymbolTable(symbolTablePtr); #endif for (i = 0; i < parameterListNodePtr->numberOfChildren; i++) { if (parameterListNodePtr->children[i] == NULL) { continue; } CheckVarDec(parameterListNodePtr->children[i], symbolTablePtr, i, FALSE); }}static void CheckBlock(NodePtr classNodePtr, NodePtr blockNodePtr){ if (blockNodePtr == NULL) { return; } CheckVarDecList(blockNodePtr->children[0], blockNodePtr->info.symbolTablePtr, FALSE); CheckStatementList(classNodePtr, blockNodePtr->children[1], blockNodePtr->info.symbolTablePtr);}static void CheckStatementList(NodePtr classNodePtr, NodePtr stmtListNodePtr, SymbolTablePtr symbolTablePtr){ int i; NodePtr statementNodePtr = NULL; if (stmtListNodePtr == NULL) { return; } for (i = 0; i < stmtListNodePtr->numberOfChildren; i ++) { statementNodePtr = stmtListNodePtr->children[i]; CheckStatement(classNodePtr, statementNodePtr, symbolTablePtr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -