/** * Checks assignment type1 statements for type errors. */ void checkAssignmentType1() { // Current receives current node at stmt. astTree stmtNode = currentASTNode->childNode->childNode; astTree idNode = stmtNode->childNode; char* idName = idNode->data.token_data; token type = checkTypeInSymbolTable(idName,idNode->data.lineNumber,idNode->data.charNumber); if(type == INVALID) return; astTree rhsNodes = stmtNode->sisterNode; switch(rhsNodes->ruleNum) { case 26: checkArithmeticExpression(idName,type,rhsNodes);break;// Arithmetic Expression case 27: checkSizeExpression(type,rhsNodes);break;// Size Expression case 28: break; // Function call } }
std::shared_ptr<inter::LogicalExpression> SemanticChecker::checkLogicalExpression(inter::ScopePrototype & scopePrototype, syntax::LogicalExpression & condition) { CHECK_FAIL(nullptr); std::shared_ptr<inter::LogicalExpression> obj = std::make_shared<inter::LogicalExpression>(); obj->operation = condition._operation; obj->negated = condition._isNegated; for (auto & operand : condition._operands) { if (operand->getType() == syntax::Node::Type::LogicalExpression) { obj->operands.push_back(checkLogicalExpression(scopePrototype, *(static_cast<syntax::LogicalExpression*>(operand.get())))); } else if (operand->getType() == syntax::Node::Type::Variable) { obj->operands.push_back(checkVariable(scopePrototype, *(static_cast<syntax::Variable*>(operand.get())))); } else if (operand->getType() == syntax::Node::Type::Call) { obj->operands.push_back(checkFunctionCall(scopePrototype, *(static_cast<syntax::Call*>(operand.get())))); } else if (operand->getType() == syntax::Node::Type::ArithmeticExpression) { obj->operands.push_back(checkArithmeticExpression(scopePrototype, *(static_cast<syntax::ArithmeticExpression*>(operand.get())))); } else { typedef syntax::Node::Type Type; Type nodeType = operand->getType(); if (nodeType == Type::Number) obj->operands.push_back(this->checkLiteral(scopePrototype, *(static_cast<syntax::Literal*>(operand.get())), "float")); else if (nodeType == Type::Bool) obj->operands.push_back(this->checkLiteral(scopePrototype, *(static_cast<syntax::Literal*>(operand.get())), "bool")); else { MessageHandler::error(std::string("Invalid logical expression operand!")); FAIL; return nullptr; } } } return obj; }
/** * Checks an arithmetic expression and reports type errors * if any. * @param idName * @param type * @param nodes */ void checkArithmeticExpression(char* idName, token type, astTree nodes) { int flag = 0; int lowPrecedenceOnly = 0; // For Strings and Matrix token acceptedType = type; astTree expression = nodes->childNode; int acceptedRows = 0; int acceptedCols = 0; int stringLength = 0; int assignMatrix = 0; // Whether to enter the size in MatrixTable or not. if(acceptedType == MATRIX) { // Find the size of the LHS matrix. astTree temp = expression->childNode->childNode->childNode->childNode; matrixSizes matrix = findMatrixInMatrixTable(idName,0,temp->data.lineNumber,temp->data.charNumber); if(matrix == NULL) { // The name wasn't found. assignMatrix = 1; } else { acceptedRows = matrix->rows; acceptedCols = matrix->columns; } } while(expression != NULL) { astTree termID = expression->childNode; while(termID != NULL) { astTree factor = termID->childNode; if(factor->ruleNum == 48) { // It is a variable. Check it's type. astTree typeNode = factor->childNode; if(typeNode->ruleNum == 65) { // // Check if it is a matrix element. if(typeNode->childNode->sisterNode->ruleNum == 77) { if(acceptedType == RNUM) { flag = 1; } else if(acceptedType != NUM) { typeError(4,typeNode->childNode->data.token_data,typeNode->childNode->data.lineNumber,typeNode->childNode->data.charNumber); } } else if(typeNode->childNode->sisterNode->ruleNum == 78) { token idNode = checkTypeInSymbolTable(typeNode->childNode->data.token_data,typeNode->childNode->data.lineNumber,typeNode->childNode->data.charNumber); if(idNode == INVALID) return; // If it is an error, ignore this statement and move on after reporting the error. if(acceptedType == RNUM) { if(idNode == NUM) { flag = 1; } else if(idNode != RNUM) { typeError(4,typeNode->childNode->data.token_data,typeNode->childNode->data.lineNumber,typeNode->childNode->data.charNumber); } } else if(acceptedType == NUM) { if(idNode != NUM) typeError(4,typeNode->childNode->data.token_data,typeNode->childNode->data.lineNumber,typeNode->childNode->data.charNumber); } else if(acceptedType == STR) { if(idNode != STR) { typeError(4,typeNode->childNode->data.token_data,typeNode->childNode->data.lineNumber,typeNode->childNode->data.charNumber); } else { int length= getSize(typeNode->childNode->data.token_data,typeNode->childNode->data.lineNumber,typeNode->childNode->data.charNumber,stList,0); if(length == 0) { // No string found error. return; } stringLength += length; lowPrecedenceOnly = 1; } } else if(acceptedType == MATRIX) { if(idNode != MATRIX) { typeError(4,typeNode->childNode->data.token_data,typeNode->childNode->data.lineNumber,typeNode->childNode->data.charNumber); } else { // Check if their sizes match. matrixSizes rhsMatrix = findMatrixInMatrixTable(typeNode->childNode->data.token_data,1,typeNode->childNode->data.lineNumber,typeNode->childNode->data.charNumber); if(rhsMatrix == NULL) { // Matrix hasn't been defined. return; } if((acceptedRows != 0 && acceptedCols != 0) && (rhsMatrix->rows != acceptedRows || rhsMatrix->columns != acceptedCols)) { // Sizes of matrix do not match. typeError(5,typeNode->childNode->data.token_data,typeNode->childNode->data.lineNumber,typeNode->childNode->data.charNumber); return; } else if(acceptedRows == 0 && acceptedCols == 0) { acceptedRows = rhsMatrix->rows; acceptedCols = rhsMatrix->columns; } lowPrecedenceOnly = 1; } } } } else if(typeNode->ruleNum == 66) { // It is a NUM type if(acceptedType == RNUM) flag = 1; else if(acceptedType != NUM) { typeError(4,typeNode->childNode->data.token_data,typeNode->childNode->data.lineNumber,typeNode->childNode->data.charNumber); } } else if(typeNode->ruleNum == 67) { if(acceptedType != RNUM) typeError(4,typeNode->childNode->data.token_data,typeNode->childNode->data.lineNumber,typeNode->childNode->data.charNumber); } else if(typeNode->ruleNum == 68) { if(acceptedType != STR) { typeError(4,typeNode->childNode->data.token_data,typeNode->childNode->data.lineNumber,typeNode->childNode->data.charNumber); } else { int length = strlen(typeNode->childNode->data.token_data); stringLength += length; lowPrecedenceOnly = 1; } } else if(typeNode->ruleNum == 69) { // Matrix assignment. } else { // Some weird error. fprintf(stderr, "You shouldn't have got here.\n"); exit(0); } } else { // rule no 53- factor -> (arithmeticExp) checkArithmeticExpression(idName,type,factor); } termID = termID->childNode->sisterNode; if(termID->ruleNum == 54) termID = NULL; else { if(termID->childNode->ruleNum == 58) flag = 0; termID = termID->childNode->sisterNode; } if(lowPrecedenceOnly == 1 || acceptedType == STR || acceptedType == MATRIX) { if(termID != NULL) typeError(6,termID->childNode->data.token_data,termID->childNode->childNode->data.lineNumber,termID->childNode->childNode->data.charNumber); } } expression = expression->childNode->sisterNode; if(expression->ruleNum == 51) { expression = NULL; } else { if(acceptedType == STR && expression->childNode->ruleNum == 56) typeError(7,expression->childNode->data.token_data,expression->childNode->childNode->data.lineNumber,expression->childNode->childNode->data.charNumber); expression = expression->childNode->sisterNode; } if(flag == 1) { astTree parentNode = expression->parentNode; while(parentNode->data.flag) parentNode = parentNode->childNode; typeError(8,parentNode->data.token_data,parentNode->data.lineNumber,parentNode->data.charNumber); return; } } if(assignMatrix) { fillDataInMatrixTable(idName,acceptedRows,acceptedCols); } if(acceptedType == STR && stringLength > 0) { fillDataInStringTable(idName,stringLength); } }