1.1其它函数设计

1.1.1 代码生成之前的初始化

  • 函数接口

    1. void beforeCodeGenerate()
  • 返回值

    1. void
  • 参数列表

  • 函数伪代码

    void beforeCodeGenerate() {
      初始化过程、函数到C程序头文件的映射;
      初始化头文件是否出现的映射;
    }
    

    1.1.2 判断数字是否相等(变参)

  • 函数接口

    bool isEqual(int num,...);
    
  • 返回值

     bool,当所有数字相等时返回true,否则返回false
    
  • 参数列表 | 参数 | 描述 | | —- | —- | | int num | 后续参数个数 | | … | 不定量整数参数 |

  • 函数伪代码
    bool isEqual(int num,...) {
      //变参列表,num表示参数个数
      va_list argp;
      int para;
      va_start(argp, num);
      int pre=va_arg(argp, int);
      for (int argno=1; argno<num; argno++) {
          para = va_arg(argp, int);
          if(para!=pre)
          return false;
          //存在不相等的数
      }
      va_end(argp);
      return true;
      //所有数相等
    }
    

1.1.3 将PASCAL-S的类型关键字转化为C的类型关键字

  • 函数接口

    string transformType(string pascalType);
    
  • 返回值

     string,转化后的C类型关键字
    
  • 参数列表 | 参数 | 描述 | | —- | —- | | string pascalType | 转化前的PASCAL-S的类型关键字 |

  • 函数伪代码
    string transformType(string pascalType) {  
      if (pascalType == "integer")  
          return "int";  
      if (pascalType == "real")  
          return "float";  
      if (pascalType == "boolean")  
          return "bool";  
      if (pascalType == "char")  
          return "char";  
      if (pascalType == "")  
          return "";  
      cout << "[transformType] pascalType error" << endl;  
      return "";  
    }
    

1.1.4 将PASCAL-S的运算符转化为C的运算符

  • 函数接口

    string transformOpertion(string operation, int mode=0);
    
  • 返回值

     string,mode==0时表示转化后的C运算符,mode!=0时表示原样返回,即认为PASCAL-S的运算符
    
  • 参数列表 | 参数 | 描述 | | —- | —- | | string operation | 转化前的PASCAL-S运算符 | | int mode | mode==0表示转化,mode!=0表示不转化,也就是原样返回 |

  • 伪代码
    string transformOpertion(string operation,int mode) {  
      if (mode != 0)  
          return operation;  
      if (operation == "not")  
          return "!";  
      if (operation == "=")  
          return "==";  
      if (operation == "<>")  
          return "!=";  
      if (operation == "or")  
          return "||";  
      if (operation == "div")  
          return "/";  
      if (operation == "mod")  
          return "%";  
      if (operation == "and")  
          return "&&";  
      return operation;  
    }
    

1.1.5 代码生成对外接口

  • 函数接口

    void codeGenerate(_Program *ASTRoot, string outName);
    
  • 返回值

  • 参数列表 | 参数 | 描述 | | —- | —- | | _Program *ASTRoot | 抽象语法树的根节点 | | string outName | 保存输出C代码的文件名 |

  • 伪代码

    void codeGenerate(_Program *ASTRoot, string outName) {  
      打开outName,并将其关联到输出文件流fout;  
      codeGenerateCurrentSymbolTable定位到主符号表;  
      调用beforeCodeGenerate做代码生成之前的初始化工作;  
      调用inputSubproDecList获取子程序声明列表;  
      调用inputConstList获取主程序常量定义列表;  
      调用inputVariantList获取主程序变量定义列表;  
      调用inputSubproDefList获取子程序定义列表;  
      调用inputSubMainFunction(ASTRoot)获取原PASCAL主程序对应C的程序头和语句体;  
    
      fout << "//Head files" << endl; //输出头文件区前缀注释  
      调用outputHeadFileList输出头文件;  
      fout << endl;  
    
      fout << "//Overall constant definiton" << endl; //输出全局常量区前缀注释  
      调用outputConstList输出全局常量定义;  
      fout << endl;  
    
      fout << "//Overall variable definition" << endl; //输出全局变量区前缀注释  
      调用outputVariantList输出全局变量定义;  
      fout << endl;  
    
      fout << "//Subprogram declaration" << endl; //输出子程序声明区前缀注释  
      调用outputSubproDecList输出子程序声明;  
      fout << endl;  
    
      fout << "//Main function" << endl; //输出主程序区前缀注释  
      调用outputMain输出主函数;  
      fout << endl;  
    
      fout << "//Subprogram definition" << endl; //输出子程序定义区前缀注释  
      调用outputSubproDefList输出子程序定义;  
    
      fout.close();  
    }
    

1.1.6 提供给语义分析的接口说明

以下三个接口提供给了语义分析的错误处理部分,以输出更加详细易读的报错信息:

extern void inputFunctionCall(_FunctionCall *functionCallNode, string &functionCall, int mode=0);//获取函数调用
extern int inputExpression(_Expression *expressionNode, string &expression, int mode=0, bool isReferedActualPara=false);//获取表达式
extern void inputVariantRef(_VariantReference *variantRefNode, string &variantRef, int mode=0, bool isReferedActualPara=false);//获取变量引用

其中都涉及到了mode参数,如果mode=0,表示是最终代码生成的情形,需要转化为C代码输出,如果mode!=0,表示是语义分析调用的情形,需要按照PASCAL-S的源代码输出。
语义分析程序在调用时,需要指定mode参数不为0。
在实现inputExpression时,PASCAL-S代码和C代码的主要区别在于运算符,所以又需要调用下列函数:

string transformOpertion(string operation, int mode=0);//将pascal的string transformOpertion(string operation, 转化为c的operation

同时也要考虑到自加括号的情形,所以在添加括号是,也要判断mode是否为0。
在实现inputVariantRef时,除了数组下标引用列表的形式需要判断mode外,也要注意无参调用的情形,PASCAL-S无参调用时只需要函数名,而C还需要在函数名后面添加一对括号。
最后要注意这三个函数的实现中,在相互调用时要加上mode参数,以保证完整地按照PASCAL-S代码输出,或者完整地按照C代码输出。