首先,作业要求概括如下:
根据前缀表达式文法,实现statements() 和expression() 两个函数。
并且要求使得语义分析在完成分析前缀表达式并输出中间代码的同时,也能够将前缀表达式翻译为中缀表达式, 且要求翻译后的中缀表达式中尽可能少用括号。
1 statements -> expression SEMI 2 | expression SEMI statements 3 4 expression -> PLUS expression expression 5 | MINUS expression expression 6 | TIMES expression expression 7 | DIVISION expression expression 8 | NUM_OR_ID
举例如下: 输入"+ a * b c;"时,应输出中缀式为" a + b * c", 而不是"a + (b * c)"或"(a) + (b * c)"等。
最后测试效果如下:
其中未实现河流命名算法故为阉割版。为方便读者阅读并理解后自行更改,这里只提供初版(low版),其代码如下(DDL后会更新):
1 //retinf.c 2 #include <stdio.h> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <stdbool.h> 6 7 #include "lex.h" 8 9 char err_id[] = "error"; 10 char * midexp; 11 extern char * yytext; 12 13 struct YYLVAL { 14 int last_op; /* last operation of expression 15 for elimination of redundant parentheses */ 16 17 char * val; /* 记录表达式中间临时变量 */ 18 char * expr; /* 记录表达式后缀式 */ 19 }; 20 21 typedef struct YYLVAL Yylval; 22 23 Yylval * expression(void); 24 25 char *newname(void); /* 在name.c中定义 */ 26 27 extern void freename(char *name); 28 29 void statements(void) { 30 Yylval *temp; 31 printf("Please input an infix expression and ending with \";\"\n"); 32 while (!match(EOI)) { 33 34 temp = expression(); 35 36 printf("The Expression Is %s\n", temp->expr); 37 freename(temp->val); 38 39 free(temp->expr); 40 free(temp); 41 if (match(SEMI)) { 42 printf("Please input an infix expression and ending with \";\"\n"); 43 advance(); 44 45 } 46 else { 47 fprintf(stderr, "%d: Inserting missing semicolon\n", yylineno); 48 } 49 } 50 } 51 52 Yylval * expression(void) { 53 Yylval *tempToReturn; 54 tempToReturn = (Yylval *)malloc(sizeof(Yylval)); 55 56 Yylval *temp0, *temp1; 57 while (match(PLUS) || match(MINUS) || match(TIMES) || match(DIVISION)) { 58 59 char op = yytext[0]; 60 advance(); 61 temp0 = expression(); 62 63 temp1 = expression(); 64 65 bool tempToReturnIsPro = op == '*' || op == '/'; 66 bool temp0IsLower = temp0->last_op == PLUS || temp0->last_op == MINUS; 67 bool temp1IsLower = temp1->last_op == PLUS || temp1->last_op == MINUS; 68 69 70 if (tempToReturnIsPro) { 71 if (temp0IsLower && temp1IsLower) { 72 tempToReturn->expr = (char*)malloc(strlen(temp0->expr) + strlen(temp1->expr) + 12); 73 sprintf(tempToReturn->expr, "( %s ) %c ( %s )", 74 temp0->expr, op, temp1->expr); 75 } 76 else if (temp0IsLower) { 77 tempToReturn->expr = (char*)malloc(strlen(temp0->expr) + strlen(temp1->expr) + 8); 78 sprintf(tempToReturn->expr, "( %s ) %c %s", 79 temp0->expr, op, temp1->expr); 80 } 81 else if (temp1IsLower) { 82 tempToReturn->expr = (char*)malloc(strlen(temp0->expr) + strlen(temp1->expr) + 8); 83 sprintf(tempToReturn->expr, "%s %c ( %s )", 84 temp0->expr, op, temp1->expr); 85 } 86 else { 87 tempToReturn->expr = (char*)malloc(strlen(temp0->expr) + strlen(temp1->expr) + 4); 88 sprintf(tempToReturn->expr, "%s %c %s", 89 temp0->expr, op, temp1->expr); 90 } 91 } 92 else {