1.1函数返回值语句存在性检测(警告信息)
函数如果没有返回值语句,则其返回值将会是一个随机的值,许多编译器都将其作为一个警告检测,我们也简单的实现了一个函数返回值语句的存在性检测,如果检测到有函数没有或缺少返回值语句,则输出警告信息。
1.1.1 算法分析
按照文法定义,函数定义中的语句体一定是一个复合语句块_Compound。_Compound中的任何一条语句是返回值语句或“完全”地包含返回值语句,就可以认为该函数定义存在足够的返回值语句。_Compound的语句列表中的每一条语句,具体类型可能各不相同,不同的语句对于返回值语句的考虑也不太一样。
我们首先定义一个概念,“返回值完备”,下面是对其的递归定义:
- 如果一条语句是赋值形式的返回值语句或者exit过程调用形式的返回值语句,就认为该语句是“返回值完备”的
- 如果_Compound语句中,有任意一条语句是“返回值完备”的,那么该_Compound语句就是“返回值完备”的
- 如果_RepeatStatement、_WhileStatement、_ForStatement的循环体语句是“返回值完备”的,那么该语句就是“返回值完备”的
- 如果_IfStatement包含then语句和else语句,且这两条语句均是“返回值完备”的,那么该_IfStatement语句就是“返回值完备”的
- 如果函数定义的_Compound程序体是“返回值完备”的,那么该函数定义是“返回值完备”的
下面以表格的形式进行阐述:
语句种类 | 分析 |
---|---|
_Compound | 语句列表中,只要存在有任何一条语句是返回值语句或“完全”地包含返回值语句,就可以认为该_Comound语句是“返回值完备”的。 |
_RepeatStatement | 如果循环体语句是“返回值完备”的,就可以认为该_RepeatStatement语句是“返回值完备”的。 |
_WhileStatement | 如果循环体语句是“返回值完备”的,就可以认为该_RepeatStatement语句是“返回值完备”的。 |
_ForStatement | 如果循环体语句是“返回值完备”的,就可以认为该_RepeatStatement语句是“返回值完备”的。 |
_IfStatement | 如果_IfStatement不包含else部分,那么无论then语句是否是“返回值完备”,该_IfStatement语句都不是“返回值完备”的;如果_IfStatement包含else部分,那么当then语句和else语句都是“返回值完备”时,就可以认为该_IfStatement语句是“返回值完备”的,否则就认为该_IfStatement语句不是“返回值完备”的。 |
_AssignStatement | 如果是赋值语句形式的函数返回值语句,就认为该_AssignStatement语句是“返回值完备”的 |
_ProcedureCall | 如果是exit过程调用形式的函数返回值语句,就认为该_ProcedureCall语句是“返回值完备”的 |
1.1.2 数据结构
涉及的数据结构只有保存警告信息的列表,声明如下:
extern vector<string> semanticWarningInformation;
其定义在SemanticAnalyse.cpp中,因此这里需要用extern关键字声明。
1.1.3 警告信息格式设计
- 需要提供函数名functionId和函数名所在的行号functionLineNumber
格式为:[Return value statement missing!]
Incomplete return value statement of function “{functionId}”. 1.1.4 引用外部的函数接口
1.1.4.1 整型数字转化为字符串
函数接口
extern string itos(int num);//将整数转化为字符串
1.1.5 内部函数接口
1.1.5.1 检查当前语句是否是“返回值完备”的
函数接口
bool returnExistedCheckStatement(_Statement *statementNode);
参数列表 | 参数 | 描述 | | —- | —- | | _Statement *statementNode | 语句基类指针 |
返回值
bool,true表示当前语句是“返回值完备”的,false表示当前语句不是“返回值完备的”
伪代码
bool returnExistedCheckStatement(_Statement *statementNode) { if (statementNode == NULL) { cout << "[returnExistedCheckStatement] pointer of _Statement is null" << endl; return false; } if (是compound语句) { _Compound *compound = reinterpret_cast<_Compound*>(statementNode); 遍历语句列表 { 调用returnExistedCheckStatement检查当前语句的“返回值完备”性; if(当前语句是返回值完备的) return true; } return false; } else if (是repeat语句) { _RepeatStatement *repeatStatement = reinterpret_cast<_RepeatStatement*>(statementNode); 调用returnExistedCheckStatement检查循环体语句的“返回值完备”性; if(循环体语句是“返回值完备”的) return true; else return false; } else if (是while语句) { _WhileStatement *whileStatement = reinterpret_cast<_WhileStatement*>(statementNode); 调用returnExistedCheckStatement检查循环体语句的“返回值完备”性; if(循环体语句是“返回值完备”的) return true; else return false; } else if (是for语句) { _ForStatement *forStatement = reinterpret_cast<_ForStatement*>(statementNode); 调用returnExistedCheckStatement检查循环体语句的“返回值完备”性; if(循环体语句是“返回值完备”的) return true; else return false; } else if (是if语句) { _IfStatement *ifStatement = reinterpret_cast<_IfStatement*>(statementNode); if (ifStatement->then == NULL) { cout << "[returnExistedCheckStatement][IfStatement] the pointer of then statement is null"; return false; } if (if语句不包含else部分) return false; else{ 调用returnExistedCheckStatement检测then语句和else语句的“返回值完备”性; if(then语句和else语句都是“返回值完备”的) return true; else return false; } } else if (是赋值语句) { //判断是否是返回值语句 _AssignStatement *assignStatement = reinterpret_cast<_AssignStatement*>(statementNode); return assignStatement->isReturnStatement; //在之前的语义分析中,已经保存是否是返回值语句 //即fun:=expression的情况 } else if (是过程调用) { //判断是否是返回值语句 _ProcedureCall *procedureCall = reinterpret_cast<_ProcedureCall*>(statementNode); return procedureCall->isReturnStatement; //在之前的语义分析中,已经保存是否是返回值语句 //即exit()的情况 } else { cout << "[returnExistedCheckStatement] statement type error" << endl; return false; } }
1.1.5.2 检查函数定义的程序体语句列表是否是“返回值完备”的
函数接口
void returnExistedCheckMainCompound(_Compound *compoundNode, string functionId, intfunctionLineNumber);
参数列表 | 参数 | 描述 | | —- | —- | | _Compound *compoundNode | 程序体语句列表 | | string functionId | 函数名 | | int functionLineNumber | 函数名所在的行号 |
返回值
无
伪代码
void returnExistedCheckMainCompound(_Compound *compoundNode, string functionId, intfunctionLineNumber) { if (compoundNode == NULL) { cout << "[returnExistedCheckCompound] pointer of _Compound is null" << endl; return; } bool ok = false; //表示当前复合语句块的“返回值完备”性,true表示具有“返回值完备”性,false表示不具有“返回值完备”性 遍历复合语句块的语句列表 { 调用returnExistedCheckStatement检测当前语句的“返回值完备”性; if(当前语句是返回值完备的){ ok=true; break; } } if (复合语句块不是“返回值完备”的) { 按照函数缺少返回值语句的警告信息格式组织functionId、functionLineNumber,形成一条警告信息; 将警告信息添加到警告信息列表中; } }
1.1.5.3 检查函数定义是否是“返回值完备”的
函数接口
void returnExistedCheckFunctionDefinition(_FunctionDefinition* functionDefinitionNode);
参数列表 | 参数 | 描述 | | —- | —- | | _FunctionDefinition* functionDefinitionNode | 函数定义节点类指针 |
返回值
无
伪代码