实践说明
【题目要求】
基于已编写的C++语法分析器,分析当前目录下input.txt文件中的语义并生成中间代码。
input.txt中的待分析代码必须以begin开头、以end结尾,文件最后以#结束。
输出结果存放到当前目录下的output.txt文件中。
【可分析语法】
算术表达式
多条简单赋值语句
【操作步骤】
1、在input.txt文件中输入或更改待分析的C源程序段(段末请以#结尾)。
2、双击程序exe文件即可完成语义分析程序的运行。
3、在output.txt文件中查看语义分析结果。
输入举例(input.txt)
begin int a = 12; int b = 1 + 2 * 3 - (a - 4) / 8; a = b % 5; end#
输出举例(output.txt)
Your words(must start with 'begin', and end with 'end'): --------------------------------- begin int a = 12; int b = 1 + 2 * 3 - (a - 4) / 8; a = b % 5; end --------------------------------- The result of semantic analysis: (1) a = 12 (2) t1 = 2 * 3 (3) t2 = 1 + t1 (4) t3 = a - 4 (5) t4 = t3 / 8 (6) t5 = t2 - t4 (7) b = t5 (8) t6 = b % 5 (9) a = t6
编程平台
CodeBlocks 10.05
代码实现
基本思路
运用递归下降语法制导翻译法,修改语法分析器,在语法分析部分插入语义动作。
语义分析部分预定义
struct /*四元式表*/ { char result[8]; char ag1[8]; char op[8]; char ag2[8]; }quad[21]; void emit(char *result,char *ag1,char *op,char *ag2); /*声明四元式生成函数*/ char* newtemp(); /*临时变量生成函数*/ int quadIndex = 0; /*四元式下标*/ int k = 0; /*临时变量下标*/ int sum = 0; /*十进制数字*/
主函数定义
int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); inputBufferIndex = 0; // 初始化输入缓冲区下标 scanf("%[^#]s", inputBuffer); // 读入源程序字符串到缓冲区,以#结束,允许多行输入,#会读成'\0' printf("Your words(must start with 'begin', and end with 'end'):\n\n"); printf("---------------------------------\n"); printf("%s\n", inputBuffer); printf("---------------------------------\n\n"); printf("The result of semantic analysis:\n\n"); oneWord = scaner(); // 获得一个新单词 lrparser(); if(lexicalError == true && syntacticError == true) { printf("\nPlease correct the above lexical errors and syntactic errors for semantic analysis!\n"); } else { if(lexicalError == true) { printf("\nPlease correct the above lexical errors for semantic analysis!\n"); } else if(syntacticError == true) { printf("\nPlease correct the above syntactic errors for semantic analysis!\n"); } } return 0; }
语义分析部分函数
/*四元式生成函数*/ void emit(char *result,char *ag1,char *op,char *ag2) { strcpy(quad[quadIndex].result,result); // 无法识别'->',得用'.' strcpy(quad[quadIndex].ag1,ag1); strcpy(quad[quadIndex].op,op); strcpy(quad[quadIndex].ag2,ag2); ++quadIndex; } /*临时变量生成函数*/ char* newtemp() { char *p; char m[8]; p = (char*)malloc(8); itoa(++k,m,10); strcpy(p+1,m); p[0] = 't'; return p; }
语法分析主函数
int lrparser() { int schain = 0; while(isLineBreak()); // 判断是否存在换行 if(oneWord -> categoryCode != 1) // 'begin'的种别码 { cout << "missing 'begin' error in line " << rowNumber << "!" << endl; syntacticError = true; } else { oneWord = scaner(); // 获得一个新单词 } schain = statementString(); // 调用语句串分析函数 if(oneWord -> categoryCode != 12) { cout << "missing 'end' error in line " << rowNumber << "!" << endl; syntacticError = true; } else { oneWord = scaner(); // 获得一个新单词 while(isLineBreak()); // 判断是否存在换行 if(oneWord -> categoryCode == 1000 && syntacticError == false && lexicalError == false) // '\0'的种别码 { for(int i = 0; i < quadIndex; ++i) { cout << "(" << i + 1 << ") "; cout << quad[i].result << " = "; cout << quad[i].ag1 << " "; cout << quad[i].op << " "; cout << quad[i].ag2 << endl; } } else { if(oneWord -> categoryCode != 1000) { cout << "the syntax after the first 'end' is invalid in line " << rowNumber << "!" << endl; syntacticError = true; } while(true) { oneWord = scaner(); // 获得一个新单词 while(isLineBreak()); // 判断是否存在换行 isLexicalError(); // 调用检测词法错误函数 if(oneWord -> categoryCode == 1000) { break; } } } } return schain; }
语句串分析函数
int statementString() { int schain = 0; while(isLineBreak()); // 判断是否存在换行 schain = statement(); // 调用语句分析函数 while(oneWord -> categoryCode == 64) // ';'的种别码 { oneWord = scaner(); // 获得一个新单词 while(isLineBreak()); // 判断是否存在换行 isLexicalError(); // 调用检测词法错误函数 schain = statement(); // 调用语句分析函数 } return schain; }
语句分析函数
int statement() { char tt[8]; char eplace[8]; int schain = 0; switch (oneWord -> categoryCode) { case 1: { cout << "only the first 'begin' is valid in line " << rowNumber << "!" << endl; oneWord -> categoryCode = 64; syntacticError = true; break; } case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 13: { if(oneWord -> categoryCode >= 2 && oneWord -> categoryCode <= 11) { oneWord = scaner(); // 获得一个新单词 isLexicalError(); // 调用检测词法错误函数 if(oneWord -> categoryCode == 64 || oneWord -> categoryCode == 12 || oneWord -> categoryCode == 1000 || oneWord -> categoryCode == 20) // 说明出现char;或char end或char'\0'或char'\n'的情况 { if(oneWord -> categoryCode == 20) { cout << "statement error in line " << (rowNumber - 1) << "!" << endl; oneWord -> categoryCode = 64; } else { cout << "statement error in line " << rowNumber << "!" << endl; } syntacticError = true; } } strcpy(tt,wordBuffer); oneWord = scaner(); // 获得一个新单词 isLexicalError(); // 调用检测词法错误函数 if(oneWord -> categoryCode == 20) { cout << "missing ';' error in line " << (rowNumber - 1) << "!" << endl; oneWord -> categoryCode = 64; syntacticError = true; } else if(oneWord -> categoryCode == 12 || oneWord -> categoryCode == 1000) { cout << "missing ';' error in line " << rowNumber << "!" << endl; syntacticError = true; } else if(oneWord -> categoryCode >= 42 && oneWord -> categoryCode <= 52) // '='、'+='、'-='、'*='、'/='、'%='、'>>='、'<<='、'&='、'^='、'|='的种别码 { oneWord = scaner(); // 获得一个新单词 while(isLineBreak()); // 判断是否存在换行 isLexicalError(); // 调用检测词法错误函数 strcpy(eplace,expression()); // 调用(等号右边的)表达式分析函数 emit(tt,eplace,"",""); schain = 0; if(oneWord -> categoryCode != 64) // 表达式一定以分号为结束 { if(oneWord -> categoryCode == 20) // 说明是换行符 { cout << "missing ';' error in line " << (rowNumber - 1) << "!" << endl; oneWord -> categoryCode = 64; } else { cout << "missing ';' error in line " << rowNumber << "!" << endl; } syntacticError = true; } } else if(oneWord -> categoryCode != 64) { cout << "missing equal sign error in line " << rowNumber << "!" << endl; syntacticError = true; } return schain; break; } case 12: case 1000: { break; } default: { cout << "statement error in line " << rowNumber << "!" << endl; syntacticError = true; oneWord = scaner(); // 获得一个新单词 while(isLineBreak()); // 判断是否存在换行 isLexicalError(); // 调用检测词法错误函数 while(oneWord -> categoryCode != 64 && oneWord -> categoryCode != 12 && oneWord -> categoryCode != 1000) { oneWord = scaner(); // 获得一个新单词 while(isLineBreak()); // 判断是否存在换行 isLexicalError(); // 调用检测词法错误函数 } } } }
(等号右边的)表达式分析函数
char* expression() { char *tp; char *ep2; char *eplace; char *tt; tp = (char*)malloc(12); ep2 = (char*)malloc(12); eplace = (char*)malloc(12); tt = (char*)malloc(12); strcpy(eplace,term()); // 调用项分析函数生成表达式计算的第一项eplace while(oneWord -> categoryCode == 21 || oneWord -> categoryCode == 22) // '+'或'-'的种别码 { strcpy(tt,oneWord -> value); oneWord = scaner(); // 获得一个新单词 while(isLineBreak()); // 判断是否存在换行 isLexicalError(); // 调用检测词法错误函数 strcpy(ep2,term()); // 调用项分析函数生成表达式计算的第二项ep2 strcpy(tp,newtemp()); // 调用newtemp产生临时变量tp存储计算结果 emit(tp,eplace,tt,ep2); // 生成四元式送入四元式表 strcpy(eplace,tp); // 将计算结果作为下一次表达式计算的第一项eplace } return eplace; }
项分析函数
char* term() { char *tp; char *ep2; char *eplace; char *tt; tp = (char*)malloc(12); ep2 = (char*)malloc(12); eplace = (char*)malloc(12); tt = (char*)malloc(12); strcpy(eplace,factor()); // 调用因子分析函数生成表达式计算的第一项eplace while(oneWord -> categoryCode >= 23 && oneWord -> categoryCode <= 25) // '*'、'/'、'%'的种别码 { strcpy(tt,oneWord -> value); oneWord = scaner(); // 获得一个新单词 while(isLineBreak()); // 判断是否存在换行 isLexicalError(); // 调用检测词法错误函数 strcpy(ep2,factor()); // 调用因子分析函数生成表达式计算的第二项ep2 strcpy(tp,newtemp()); // 调用newtemp产生临时变量tp存储计算结果 emit(tp,eplace,tt,ep2); // 生成四元式送入四元式表 strcpy(eplace,tp); // 将计算结果作为下一次表达式计算的第一项eplace } return eplace; }
因子分析函数
char* factor() { char *fplace; fplace = (char*)malloc(12); strcpy(fplace," "); if(oneWord -> categoryCode == 13) // 单词的种别码 { strcpy(fplace,oneWord -> value); oneWord = scaner(); // 获得一个新单词 isLexicalError(); // 调用检测词法错误函数 } else if(oneWord -> categoryCode == 14) // 数字的种别码 { itoa(sum,fplace,10); oneWord = scaner(); // 获得一个新单词 isLexicalError(); // 调用检测词法错误函数 } else if(oneWord -> categoryCode == 56) // '('的种别码 { oneWord = scaner(); // 获得一个新单词 while(isLineBreak()); // 判断是否存在换行 isLexicalError(); // 调用检测词法错误函数 fplace = expression(); // 调用(等号右边的)表达式分析函数 if(oneWord -> categoryCode == 57) // ')'的种别码 { oneWord = scaner(); // 获得一个新单词 while(isLineBreak()); // 判断是否存在换行 isLexicalError(); // 调用检测词法错误函数 } else { cout << "missing ')' error in line " << rowNumber << "!" << endl; syntacticError = true; } } else { cout << "expression error in line " << rowNumber << "!" << endl; syntacticError = true; } return fplace; }
如果文章内容出错或者您有更好的解决方法,欢迎到评论区指正和讨论!