1.1其它函数设计
1.1.1 代码生成之前的初始化
函数接口
void beforeCodeGenerate()
返回值
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代码输出。