1.1语义分析函数设计

1.1.1 常量语义分析

  • 函数接口

void SemanticAnalyseConst(_Constant* constant)

  • 返回值

void

  • 参数列表 | 参数 | 描述 | | —- | —- | | _Constant* constant | 指向该常量标识符的指针 |

  • 函数功能

对常量定义进行语义分析

  • 函数伪代码

    1. void SemanticAnalyseConst(_Constant* constant) {
    2. if(constant==NULL) {
    3. cout << "[SemanticAnalyseConst] pointer of _Constant is null" << endl;
    4. return;
    5. }
    6. constId.first去查符号表,检查是否重定义
    7. 调用checkIsTheSameAsKey函数,检查是否与主程序名、主程序参数名、库程序名同名;
    8. 若是,return;
    9. if (符号表记录不为空) {
    10. 调用addDuplicateDefinitionErrorInformation函数添加重定义错误信息;
    11. return;
    12. }
    13. if(该常量由另外的常量标识符定义) {
    14. 调用findSymbolRecord函数查询该常量标识符的记录;
    15. if(该常量标识符未定义) {
    16. 调用addUndefinedErrorInformation函数添加未定义错误信息;
    17. return;
    18. }
    19. if (该标识符不是常量) {
    20. 调用addPreFlagErrorInformation函数添加标识符种类错误信息;
    21. return;
    22. }
    23. 调用addConst函数将该标识符添加到符号表记录中;
    24. } else//该常量由常数值定义
    25. 调用addConst函数将该标识符添加到符号表记录中;
    26. }


    1.1.2 变量语义分析

  • 函数接口

void SemanticAnalyseVariant(_Variant* variant)

  • 返回值

void

  • 参数列表 | 参数 | 描述 | | —- | —- | | _Constant* constant | 指向该变量标识符的指针 |

  • 函数功能

对变量定义进行语义分析

  • 函数伪代码
    void SemanticAnalyseVariant(_Variant* variant) {
      if(variant==NULL) {
          cout << "[SemanticAnalyseVariant] pointer of _Variant is null" << endl;
          return;
      }
      用variantId.first去查符号表,检查是否重定义;
      调用checkIsTheSameAsKey函数,检查是否与主程序名、主程序参数名、库程序名同名;
      若是,return;
      if(符号表记录不为空) {
          调用addDuplicateDefinitionErrorInformation添加重定义错误信息;
          return;
      }
      if(如果当前变量不是数组)
      调用addVar将该变量添加进符号表; else {
          if(数组每一维上界均大于等于下界)
          调用addArray函数将该数组添加进符号表; else
          调用addArrayRangeUpSideDownErrorInformation添加数组越界错误信息;
      }
    }
    

1.1.3 语句语义分析

  • 函数接口

void SemanticAnalyseStatement(_Statement *statement)

  • 返回值

void

  • 参数列表 | 参数 | 描述 | | —- | —- | | _Statement *statement | 指向该语句标识符的指针 |

  • 函数功能

对语句定义进行语义分析

  • 函数伪代码
    void SemanticAnalyseStatement(_Statement *statement) {
      if(statement==NULL) {
          cout << "[SemanticAnalyseStatement] pointer of _Statement is null" << endl;
          return;
      }
      if(语句类型是"compound") {
          调用reinterpret_cast函数将该语句转换为_CompoundStatement类型;
          遍历对复合语句块中的每一条语句,调用SemanticAnalyseStatement函数进行语义分析;
      } else if(语句类型是"repeat") {
          调用reinterpret_cast函数将该语句转换为_RepeatStatement类型;
          调用SemanticAnalyseExpression得到条件表达式的类型;
          if (条件表达式的类型 != "boolean") {
              //repeat语句类型检查,condition表达式类型检查 checked
              调用addExpressionTypeErrorInformation函数添加类型错误信息;
              该语句类型赋值为"error";
          } else
          该语句类型赋值为"void";
          调用SemanticAnalyseStatement函数对循环体语句进行语义分析;
      } else if(语句类型是"while") {
          调用reinterpret_cast函数将该语句转换为_WhileStatement类型;
          调用SemanticAnalyseExpression得到条件表达式的类型;
          string type = SemanticAnalyseExpression(whileStatement->condition);
          if (条件表达式的类型 != "boolean") {
              //repeat语句类型检查,condition表达式类型检查 checked
              调用addExpressionTypeErrorInformation函数添加类型错误信息;
              该语句类型赋值为"error";
          } else
          该语句类型赋值为"void";
          调用SemanticAnalyseStatement函数对循环体语句进行语义分析;
      } else if(语句类型是"for") {
          调用reinterpret_cast函数将该语句转换为_ForStatement类型;
          调用 findSymbolRecord函数,找到循环变量的记录;
          if(记录不为空) {
              调用addUndefinedErrorInformation函数添加重定义错误信息;
              return;
          }
          if(该记录类型不为传值参数、传引用参数、普通变量) {
          }
          调用addPreFlagErrorInformation添加标识符种类错误信息;
          return;
      }
      if (循环变量类型不为整型) {
          调用addUsageTypeErrorInformation函数添加标识符类型错误信息;
          return;
      }
      //for语句类型检查,start和end表达式类型检查
      forStatement语句类型赋值为"void";
      string type = SemanticAnalyseExpression(forStatement->start);
      调用SemanticAnalyseExpression函数获得forStatement语句的start值的类型;
      if (start值的类型不为 "integer") {
          调用addUsageTypeErrorInformation函数添加标识符类型错误信息;
          forStatement语句类型赋值为 "error";
      }
      调用SemanticAnalyseExpression函数获得forStatement语句的end值的类型;
      if (end值的类型不为 "integer") {
          调用addUsageTypeErrorInformation函数添加标识符类型错误信息;
          forStatement语句类型赋值为 "error";
      }
      调用SemanticAnalyseStatement函数对循环体语句进行语义分析
    } else if(语句类型是"if") {
      调用reinterpret_cast函数将该语句转换为_IfStatement类型;
      调用SemanticAnalyseExpression函数获得条件表达式的类型;
      if (条件表达式的类型不为 "boolean") {
          调用addUsageTypeErrorInformation函数添加标识符类型错误信息;
          ifStatement语句类型赋值为 "error";
          ;
      } else
      ifStatement语句类型赋值为"void";
      调用 SemanticAnalyseStatement对then语句进行语义分析;
      if(if语句对应的els不等于NULL)
      调用SemanticAnalyseStatement函数对 else语句进行语义分析;
    } else if(语句类型是"assign") {
      调用reinterpret_cast函数将该语句转换为_AssignStatement类型;
      assign语句类型赋值为"void";
      将assign语句的左值的locFlag赋值为-1;
      调用SemanticAnalyseVariantReference函数获得assign语句的左值的类型;
      if (assign语句的左值的类型为 "constant") {
          调用addGeneralErrorInformation函数添加通用错误信息;
          return;
      }
      调用SemanticAnalyseExpression函数获得assign语句的右值的类型
      if (assign语句的右值的类型为 "function return reference") {
          if (assign语句的右值的类型不等于函数返回值类型 && !(assign语句的右值的类型为"integer"且函数返回值类型为"real")) {
              调用addGeneralErrorInformation函数添加通用错误信息;
              assign语句类型赋值为"error";
          }
          assign语句是返回值语句;
          return;
      }
      //比较左值和右值类型,获得赋值语句的类型;类型不同时,只支持整型到实型的隐式转换
      if (左值类型不等于右值类型 && !(左值类型=="real" && 右值类型=="integer")) {
          调用addAssignTypeMismatchErrorInformation函数添加左值类型与右值类型不匹配的错误信息;
          assign语句赋值为 "error";
      } else
      assign语句类型赋值为"void";
    } else if(语句类型是"procedure") {
      //read的参数只能是变量或数组元素;
      调用reinterpret_cast函数将该语句转换为_ProcedureCall类型;
      通过procedureId,调用findSymbolRecord函数查主表,获得这条语句的记录;
      if (记录为空)
      通过procedureId,调用findSymbolRecord函数查当前符号表,获得这条语句的记录;
      将procedure语句类型赋值为 "void";
      if (记录为空) {
          调用addUndefinedErrorInformation函数添加重定义错误信息;;
          将procedure语句类型赋值为"error";
          return;
      }
      if (该记录类型不是 "procedure") {
          调用addPreFlagErrorInformation函数添加标识符种类错误信息;
          将procedure语句类型赋值为"error";
          return;
      }
      if (语句类型是 "exit") {
          if (当前程序是"procedure") {
              if (exit语句的实参个数 != 0) {
                  调用addGeneralErrorInformation函数添加通用错误信息;
                  exit语句类型赋值为"error";
              }
              return;
          }
          //如果是函数
          if (exit语句的实参个数 != 1) {
              if (exit语句的实参个数== 0)
              调用addGeneralErrorInformation函数添加通用错误信息; else
              调用addGeneralErrorInformation函数添加通用错误信息;
              return;
          }
          调用SemanticAnalyseExpression函数获得函数返回值的类型
          if (实参表达式的类型 !=函数返回值的类型 && !(实参表达式的类型为 "real" && 函数返回值的类型为"integer")) {
              调用addGeneralErrorInformation函数添加通用错误信息;
              将procedure语句类型赋值为"error";
          }
          procedure语句是返回值语句;
          return;
      }
      if (记录的id类型为 "read" || 记录的id类型为"write") {
          if (procedure语句的参数为0) {
              调用addGeneralErrorInformation函数添加通用错误信息;
              将procedure语句类型赋值为"error";
          }
      }
      if (记录的id类型为 "read") {
          遍历read函数中的每一个参数,调用SemanticAnalyseExpression得到read函数各个参数的参数类型;
          if (!(read函数的参数类型引用域type为 "var" && (read函数的参数类型为"var" || read函数的参数类型为 "array")))
          调用addactualParameterOfReadErrorInformation函数来添加read的实参错误信息;
          if (read函数的参数表达式类型 == "boolean")
          调用addReadBooleanErrorInformation函数来添加添加read读取boolean类型变量错误的信息;
          if (read函数的参数类型== "error")
          read语句的类型赋值为 "error";
      }
      return;
    }
    if (记录的amount值 == -1) {
      遍历对语句块中的每一条语句,调用SemanticAnalyseExpression函数得到read函数各个参数的参数类型 {
          if (read函数的参数类型 == "error")
          read语句类型赋值为"error";
      }
      return;
    }
    if (语句的参数个数!= 记录的语句参数个数) {
      调用addNumberErrorInformation函数添加参数个数不匹配错误新;
      read语句类型赋值为"error";
      return;
    }
    遍历对语句块中的每一条语句,调用SemanticAnalyseExpression函数得到read函数的各个参数的参数类型 {
      调用findXthFormalParaType函数,得到对应的每一个实参的参数类型;
      调用isXthFormalParaRefered函数来得到每一个实参的类型是否是传引用调用;
      if (实参类型是传引用调用 && !(语句变量调用变量值为"var" && (实参传引用调用表达式类型为 "var" || 实参传引用调用表达式类型为"array"))) {
          调用addGeneralErrorInformation函数添加通用错误信息;
          continue;
      }
      if (实参类型是传值调用) {
          if (实参类型与形参类型不一致 && !(实参类型为"integer" && 形参类型为"real")) {
              调用addExpressionTypeErrorInformation函数添加类型错误信息;
              procedureCall->statementType = "error";
          }
      } else {
          if (实参类型与形参类型不一致) {
              调用addExpressionTypeErrorInformation函数添加类型错误信息;
              procedureCall->statementType = "error";
          }
      }
    }
    } else {
      cout << "[SemanticAnalyseStatement] statement type error" << endl;
      return;
    }
    }
    

1.1.4 表达式语义分析

  • 函数接口

string SemanticAnalyseExpression(_Expression* expression)

  • 返回值

void

  • 参数列表 | 参数 | 描述 | | —- | —- | | _Expression* expression | 指向该表达式标识符的指针 |

  • 函数功能

对表达式定义进行语义分析

  • 函数伪代码
    string SemanticAnalyseExpression(_Expression* expression) {
      if(expression==NULL) {
          cout << "[SemanticAnalyseExpression] pointer of _Expression is null" << endl;
          return "";
      }
      if (表达式类型为 "var") {
          调用SemanticAnalyseVariantReference函数获得常量的类型;
          if (常量引用类型为"integer" && 该常量类型为 "constant") {
              调用findSymbolRecord函数来查符号表查出常量值
              if (记录不存在) {
                  cout << "[SemanticAnalyseExpression] pointer of record is null" << endl;
                  return "";
              }
              if (记录的类型!= "constant") {
                  cout << "[SemanticAnalyseExpression] the record should be a constant" << endl;
                  return "";
              }
              将记录的常数值赋值给该表达式的值;
              if (表达式的值为负值)
              将记录的值加上负号之后赋值给表达式的值;
              常量表达式的值存在;
          }
          return 表达式的类型;
      } else if (表达式类型为 "integer") {
          将表达式的整数值赋值给该表达式的值;
          整型表达式的值存在;
          return 表达式的具体类型为 "integer";
      } else if (表达式类型为 "real")
      return 表达式的类型为 "real"; else if (表达式类型为  "char")
      return表达式的类型为 "char"; else if (表达式类型为"function")
      return 调用SemanticAnalyseFunctionCall函数获得函数调用的返回值类型; else if (表达式类型为"compound") {
          if (表达式的操作类型为 "relop") {
              调用SemanticAnalyseExpression函数获得表达式左值的类型;
              调用SemanticAnalyseExpression函数获得表达式右值的类型;
              if ((表达式左值的类型不等于表达式右值的类型 && 表达式左值的类型不为 "error") || (表达式左值的类型为 "integer" && 表达式右值的类型为 "real") || (表达式左值的类型为"real" &&表达式右值的类型为"integer"))
              return  表达式的具体类型为 "boolean"; else {
                  if(表达式左值的类型不等于表达式右值的类型 &&表达式左值的类型不等于"error" &&表达式左值的类型不等于 "error")
                  调用addOperandExpressionsTypeMismatchErrorInformation函数来添加操作符两边类型不一致错误信息;
                  return 表达式的具体类型为 "error";
              }
          } else if (表达式的操作类型为 "not") {
              调用SemanticAnalyseExpression函数获得表达式的类型;
              if (表达式的类型为"boolean")
              return 表达式的具体类型 "boolean"; else {
                  if(表达式的类型不为 "error" && 表达式的类型不为"boolean")
                  调用addSingleOperandExpressionTypeMismatchErrorInformation函数添加某个操作数类型错误信息;
                  return 表达式的具体类型为 "error";
              }
          } else if (表达式的操作类型为 "minus") {
              调用SemanticAnalyseExpression函数获得表达式的类型;
              if(表达式的类型为"integer" && 表达式操作数的值存在) {
                  将表达式操作数的值取负之后,重新赋值为表达式的值;
                  表达式的值存在;
              }
              if (表达式的类型为"integer" || 表达式的类型为 "real")
              return 返回表达式的具体类型; else {
                  if(表达式的类型不为 "error" &&表达式的类型不为"integer" &&表达式的类型不为"real")
                  调用addSingleOperandExpressionTypeMismatchErrorInformation函数添加某个操作数类型错误信息;
                  return 表达式的具体类型为 "error";
              }
          } else if (表达式的操作类型为"bracket") {
              调用SemanticAnalyseExpression函数获得表达式的类型;
              if(表达式的类型为 "integer" && 表达式操作数的值存在) {
                  将表达式操作数的值赋值为表达式的值;
                  表达式的值存在;
              }
              return 表达式的类型;
          } else if (表达式的操作类型为 "+" ||表达式的操作类型为 "-" || 表达式的操作类型为 "*" || 表达式的操作类型为"/") {
              调用SemanticAnalyseExpression函数获得表达式第一个操作数的类型;
              调用SemanticAnalyseExpression函数获得表达式第二个操作数的类型;
              if (表达式的操作类型为"/" && 除数类型为"integer" &&除数的值存在&& 除数的值为 0)
              调用addDivideZeroErrorInformation函数添加除0错误信息;
              if(第一个操作数类型为"integer" &&第二个操作数的类型为 "integer" && 第一个操作数的值存在 && 第二个操作数的值存在) {
                  表达式的值存在;
                  if(表达式的操作类型为"+")
                  表达式的值等于第一个操作数的值+第二个操作数的值; else if(表达式的操作类型为"-")
                  表达式的值等于第一个操作数的值-第二个操作数的值; else if(表达式的操作类型为"*")
                  表达式的值等于第一个操作数的值*第二个操作数的值; else
                  表达式的值等于第一个操作数的值/第二个操作数的值;
              }
              if((第一个操作数类型为"integer" || 第一个操作数类型为"real") && (第二个操作数类型为"integer" || 第二个操作数类型为"real")) {
                  if(第一个操作数类型为"integer" && 第二个操作数类型为"integer")
                  return 表达式的类型为"integer";
                  return 表达式的类型为"real";
              }
              if(第一个操作数类型不为 "error" && 第一个操作数类型不为 "integer" && 第一个操作数类型不为"real")
              调用addSingleOperandExpressionTypeMismatchErrorInformation函数添加某个操作数类型错误信息;
              if(第二个操作数类型不为"error" && 第二个操作数类型不为 "integer" && 第二个操作数类型不为 "real")
              调用addSingleOperandExpressionTypeMismatchErrorInformation函数添加某个操作数类型错误信息;
              return 表达式的类型为"error";
          } else if (表达式的操作类型 "div" || 表达式的操作类型"mod") {
              调用SemanticAnalyseExpression函数获得表达式第一个操作数的类型;
              调用SemanticAnalyseExpression函数获得表达式第二个操作数的类型;
              if (第二个操作数的类型"integer" && 第二个操作数的值存在&& 第二个操作数的值为0)
              调用addDivideZeroErrorInformation函数添加除0错误信息;
              if (第一个操作数类型为"integer" && 第二个操作数类型为"integer") {
                  if((第一个操作数的值存在 && 第二个操作数的值存在) {
                      if(表达式的操作类型 "div")
                      表达式的值等于第一个操作数的值/第二个操作数的值; else
                      表达式的值等于第一个操作数的值%第二个操作数的值;
                      表达式的值存在;
                  }
                  return 表达式的类型为"integer";
              }
              if(第一个操作数类型不为"error" &&第一个操作数类型不为"integer")
              调用addSingleOperandExpressionTypeMismatchErrorInformation函数添加某个操作数类型错误信息;
              if(第二个操作数类型不为"error" && 第二个操作数类型不为"integer")
              调用addSingleOperandExpressionTypeMismatchErrorInformation函数添加某个操作数类型错误信息;
              return 表达式的类型为"error";
          } else if (表达式的操作类型为 "and" || 表达式的操作类型为"or") {
              调用SemanticAnalyseExpression函数获得表达式第一个操作数的类型;
              调用SemanticAnalyseExpression函数获得表达式第二个操作数的类型;
              if (第一个操作数类型为"boolean" && 第二个操作数类型为 "boolean")
              return expression->expressionType = "boolean";
              if (第一个操作数类型不为 "error" && 第一个操作数类型不为"boolean")
              调用addSingleOperandExpressionTypeMismatchErrorInformation函数添加某个操作数类型错误信息;
              if (第二个操作数类型不为 "error" && 第二个操作数类型不为"boolean")
              调用addSingleOperandExpressionTypeMismatchErrorInformation函数添加某个操作数类型错误信息;
              return 表达式的类型为 "error";
          } else {
              cout << "[_Expression::SemanticAnalyseExpression] ERROR: operation not found" << endl;
              return "error";
          }
      }
    }
    

1.1.5 程序语义分析

  • 函数接口

void SemanticAnalyseProgram(_Program *program)

  • 返回值

void

  • 参数列表 | 参数 | 描述 | | —- | —- | | _Statement *statement | 指向该程序标识符的指针 |

  • 函数功能

对程序定义进行语义分析

  • 函数伪代码
    void SemanticAnalyseProgram(_Program *program) {
      if (program == NULL) {
          cout << "[SemanticAnalyseProgram] pointer of _Program is null" << endl;
          return;
      }
      调用lib.insert函数将read、write、writeln、exit 4个库函数加入函数库;
      if (程序与库函数名同名)
          调用addGeneralErrorInformation添加通用错误信息;
      调用addProgramName函数将该程序的函数名存储到主符号表的第0个位置,将主程序的参数添加到主符号表中,flag定为"parameter of program;
      遍历主程序参数{
          if (该程序名是否和主程序名同名)
              调用addGeneralErrorInformation函数添加通用错误信息;
          else if (该程序名是否和主程序参数名同名)
              调用addGeneralErrorInformation函数添加通用错误信息;
          else
              调用addVoidPara函数将主程序参数加入到符号表中;
      }
      调用addProcedure函数添加read过程,该过程变参
      调用addProcedure函数添加write过程,该过程变参
      调用addProcedure函数添加writeln过程,该过程变参
      调用addProcedure函数添加exit过程;
      调用SemanticAnalyseSubprogram对分程序进行语义分析;
    }
    

1.1.6 分程序语义分析

  • 函数接口

void SemanticAnalyseSubprogram(_SubProgram* subprogram)

  • 返回值

void

  • 参数列表 | 参数 | 描述 | | —- | —- | | _SubProgram* subprogram | 指向该分程序标识符的指针 |

  • 函数功能

对分程序定义进行语义分析

  • 函数伪代码
    void SemanticAnalyseSubprogram(_SubProgram* subprogram) {
      if(subprogram==NULL) {
          cout << "[SemanticAnalyseSubprogram] pointer of _Subprogram is null" << endl;
          return;
      }
      遍历分程序的常量列表
      调用SemanticAnalyseConst函数对常量进行语义分析;
      遍历分程序的变量列表
      调用SemanticAnalyseVariant函数对变量进行语义分析;
      遍历分程序的子程序定义列表 {
          调用SemanticAnalyseSubprogramDefinition函数对子程序定义进行语义分析;
          进行符号表的重定位;
      }
      调用 SemanticAnalyseStatement函数对语句进行语义分析;
    }
    

1.1.7 子程序语义分析

  • 函数接口

void SemanticAnalyseSubprogramDefinition(_FunctionDefinition* functionDefinition)

  • 返回值

void

  • 参数列表 | 参数 | 描述 | | —- | —- | | _FunctionDefinition* functionDefinition | 指向该子程序标识符的指针 |

  • 函数功能

对子程序定义进行语义分析

  • 函数伪代码
    void SemanticAnalyseSubprogramDefinition(_FunctionDefinition* functionDefinition) {
      if(functionDefinition==NULL) {
          cout << "[SemanticAnalyseSubprogramDefinition] pointer of _FunctionDefinition is null" << endl;
          return;
      }
      调用findSymbolRecord函数查找该子程序定义的记录;
      if(记录不为空) {
          调用addDuplicateDefinitionErrorInformation函数添加未定义错误信息;
          return;
      }
      if (子程序无返回值)
      子程序的类型为 "procedure"; else
      子程序的类型为"function";
      调用 createSubSymbolTableAndInit()函数创建并定位到子符号表;
      调用addProgramName函数将子程序名等信息添加到子符号表中;
      if (如果该程序是过程)//如果是过程
      调用addProcedure函数将过程添加到主程序表中; else
      调用addFunction函数将函数添加到主程序表中;
      遍历子程序的形参列表 {
          调用SemanticAnalyseFormalParameter函数对形式参数列表进行语义分析,并将形式参数添加到子符号表中;
      }
      遍历子程序的常量列表 {
          调用SemanticAnalyseConst函数对常数列表进行语义分析,并将常数添加到子符号表中;
      }
      遍历子程序的变量列表 {
          调用SemanticAnalyseVariant函数对变量列表进行语义分析,并将变量添加到子符号表中;
      }
      调用SemanticAnalyseStatement函数对compound进行语义分析;
      调用returnExistedCheckFunctionDefinition函数对函数进行返回值语句的存在性检查;
    }
    

1.1.8 函数调用语义分析

  • 函数接口

string SemanticAnalyseFunctionCall(_FunctionCall *functionCall)

  • 返回值

void

  • 参数列表 | 参数 | 描述 | | —- | —- | | _FunctionCall *functionCall | 指向该函数调用标识符的指针 |

  • 函数功能

对函数调用定义进行语义分析

  • 函数伪代码
    string SemanticAnalyseFunctionCall(_FunctionCall *functionCall) {
      if(functionCall==NULL) {
          cout << "[SemanticAnalyseFunctionCall] pointer of _FunctionCall is null" << endl;
          return "";
      }
      调用findSymbolRecord函数在主符号表查找该函数调用定义的记录
      if (记录为空)
      调用findSymbolRecord函数在当前符号表查找该函数调用定义的记录
      if (记录为空) {
          调用addaddUndefinedErrorInformation函数添加未定义错误信息;
          return 函数调用类型为 "error";
      }
      if (记录类型不是"function") {
          调用addPreFlagErrorInformation函数添加标识符种类错误信息;
          return 函数调用类型为 "error";
      }
      if (函数的参数量为-1) {
          遍历函数的参数列表
          调用SemanticAnalyseExpression函数对每一个参数进行表达式的语义分析;
          return 记录的类型;
      }
      if (参数个数不一致) {
          调用addNumberErrorInformation函数添加参数个数不一致错误信息;
          return 记录的类型;
      }
      //检查各位置的实参和形参类型是否一致 形参在符号表中的定位
      遍历函数的参数列表 {
          string actualType = SemanticAnalyseExpression(functionCall->actualParaList[i]);
          string formalType = record->findXthFormalParaType(i + 1);
          调用SemanticAnalyseExpression函数得到每一个实参的类型;
          调用findXthFormalParaType函数得到每一个形参的类型;
          调用isXthFormalParaRefered函数检查第X维形式参数是否是引用调用;
          if (是引用调用 && !(实参类型引用为 "var" && (实参类型为 "var" || 实参类型为"array"))) {
              调用addGeneralErrorInformation函数添加通用错误信息;
              continue;
          }
          if (是传值参数) {
              if (实参类型与形参不一致&& !(实参类型为 "integer" && 形参类型为 "real"))
              调用addExpressionTypeErrorInformation函数添加表达式类型错误信息;
          } else {
              if (实参类型与形参不一致)
              调用addExpressionTypeErrorInformation函数添加表达式类型错误信息;
          }
      }
      return 函数调用类型;
    }
    

1.1.9 形式参数语义分析

  • 函数接口

void SemanticAnalyseFormalParameter(_FormalParameter *formalParameter)

  • 返回值

void

  • 参数列表 | 参数 | 描述 | | —- | —- | | _FunctionCall *functionCall | 指向该形式参数标识符的指针 |

  • 函数功能

对形式参数定义进行语义分析

  • 函数伪代码
    void SemanticAnalyseFormalParameter(_FormalParameter* formalParameter) {
      if(formalParameter==NULL) {
          cout << "[SemanticAnalyseFormalParameter] pointer of _FormalParameter is null" << endl;
          return;
      }
      if (调用checkIsTheSameAsKey函数检查是否与库程序名、主程序名、主程序参数同名)
      return;
      调用findSymbolRecord函数在当前符号表中寻找该标识符记录;
      if(记录不为空)
      调用addDuplicateDefinitionErrorInformation函数添加重定义错误信息;
      if(形参类型传值参数)
      调用addPara函数添加传值参数标识符到符号表中; else
      调用addVarPara函数添加传引用参数标识符到符号表中;
    }
    

1.1.10 变量引用语义分析

  • 函数接口

string SemanticAnalyseVariantReference(_VariantReference* variantReference)

  • 返回值

void

  • 参数列表 | 参数 | 描述 | | —- | —- | | _VariantReference* variantReference | 指向该变量引用标识符的指针 |

  • 函数功能

对变量引用定义进行语义分析

  • 函数伪代码
    string SemanticAnalyseVariantReference(_VariantReference* variantReference) {
      if(variantReference==NULL) {
          cout << "[SemanticAnalyseVariantReference] pointer of _VariantReference is null" << endl;
          return "";
      }
      调用findSymbolRecord函数在当前符号表查找该变量引用定义的记录
      if (记录为空) {
          调用addaddUndefinedErrorInformation函数添加未定义错误信息;
          return 该变量引用类型为 "error";
      }
      if (该变量引用不是数组) {
          if (记录类型引用为"(sub)program name") {
              if (记录类型为 "procedure") {
                  调用addGeneralErrorInformation函数添加通用错误信息;
                  return 该变量引用类型为"error";
              }
              if (变量引用为左值) {
                  变量引用的种类为 "function return reference";
                  return 变量引用的类型;
              }
              //如果是右值
              if (变量引用为右值且形参个数不为0) {
                  调用addNumberErrorInformation函数添加参数个数不一致错误信息;
                  return 变量引用的类型;
              }
              变量引用的种类为"function call";
              return 变量引用的类型;
          }
          if (记录类型为 "function") {
              变量引用类型为 "function";
              if (变量引用为左值) {
                  return 变量引用的类型为 "error";
                  调用addGeneralErrorInformation函数添加通用错误信息;
              }
              if (如果形参个数不为0) {
                  addNumberErrorInformation(variantReference->variantId.first, variantReference->variantId.second, 0, record->amount, "function");
                  调用addNumberErrorInformation函数添加参数个数不一致错误信息;
                  return 变量引用的类型;
              }
              return 变量引用的类型;
          }
          if (!(记录类型为"value parameter" || 记录类型为 "var parameter" || 记录类型为 "normal variant" || 记录类型为 "constant")) {
              调用addGeneralErrorInformation函数添加通用错误信息;
              return 变量引用的类型"error";
          }
          变量引用的种类为 "var";
          if (记录的类型为 "constant")
          变量引用的类型赋值为"constant";
          return 变量引用的类型;
      } else if (变量引用的类型为数组) {
          if (记录不是 "array") {
              调用addPreFlagErrorInformation函数添加标识符种类错误信息;
              return 变量引用的类型为"error";
          }
          变量引用的种类赋值为 "array";
          if (变量引用的下标维数和符号表所存记录不一致) {
              调用addNumberErrorInformation函数添加参数个数不一致错误信息;
              变量引用的类型赋值为 "error";
              return 变量引用的类型;
          }
          将符号表记录类型赋值给变量引用类型;
          遍历变量引用的的表达式列表 {
              调用SemanticAnalyseExpression函数得到每一个表达式的类型;
              if (表达式下标类型不为"integer") {
                  variantReference->variantType = "error";
                  调用addExpressionTypeErrorInformation函数添加表达式类型错误信息;
                  变量引用的类型赋值为 "error";
              }
              if(变量引用的值存在) {
                  if(调用checkArrayXthIndexRange函数检查每一维是否越界) {
                      调用addArrayRangeOutOfBoundErrorInformation函数添加数组下标越界错误信息;
                      变量引用的类型赋值为 "error";
                  }
              }
          }
          return 记录的类型;
      } else {
          cout << "[SemanticAnalyseVariantReference] flag of variantReference is not 0 or 1" << endl;
          return 变量引用的类型为 "error";
      }
    }