软件构造——语义分析
【实验目的】
通过上机实验,加深对语法制导翻译的理解,掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法。
【实验内容】
对给定的程序通过语义分析器能够判断语句串是否正确。正确则输出三地址指令形式的四元式代码,错误则抛出错误信息。
【设计思想】
(1)输入待分析的字符串。
语法如下:
a.关键字:begin,if,then,while,do,end.
b.运算符和界符::= + - * / < <= > >= <> = ; ( ) #
c.其他单词是标识符(ID)和整形常数(NUM):ID=letter(letter|digit)*,NUM=digitdigit*
d.空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM、运算符、界符和关键字,词法分析阶段通常被忽略。
(2)扫描字符串,采用递归向下进行分析。
主要函数如下:
a.scaner()//词法分析函数,char token[8]用来存放构成单词符号的字符串;
b.parser()//语法分析,在语法分析的基础上插入相应的语义动作:将输入串翻译成四元式序列。只对表达式、赋值语句进行翻译。
c.emit(char *result,char *arg1,char *op,char *ag2)//该函数功能是生成一个三地址语句返回四元式表中。
d.char *newtemp()//该函数返回一个新的临时变量名,临时变量名产生的顺序为T1,T2,…。
【实验要求】
四元式表的结构如下:
struct {char result[8];
char ag1[8];
char op[8];
char ag2[8];
}quad[20];
(3)输出为三地址指令形式的四元式序列。
例如:语句串begin a:=2+3*4;x:=(a+b)/c;end#,
输出的三地址指令如下:
t1=3*4
t2=2+t1
a=t2
t3=a+b
t4=t3/c
x=t4
代码:
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 #include<stdlib.h> 5 using namespace std; 6 struct { 7 char result[12]; 8 char ag1[12]; 9 char op[12]; 10 char ag2[12]; 11 }quad; 12 //变量的定义 13 char prog[80], token[12]; 14 char ch; int syn, p, m = 0, n, sum = 0, kk; //p 是缓冲区 prog 的指针, m 是 token 的指针 15 char *rwtab[6] = { "begin", "if", "then", "while", "do", "end" }; 16 void scaner(); 17 char *factor(void); 18 char *term(void); 19 char *expression(void); 20 int yucu(); 21 void emit(char *result, char *ag1, char *op, char *ag2); 22 char *newtemp(); 23 int statement(); 24 int k = 0; 25 void emit(char *result, char *ag1, char *op, char *ag2) { 26 strcpy(quad.result, result); 27 strcpy(quad.ag1, ag1); 28 strcpy(quad.op, op); 29 strcpy(quad.ag2, ag2); 30 //cout<<quad.result<<"="<<quad.ag1<<quad.op<<quad.ag2<<endl; 31 cout << "( " << quad.op << ", " << "entry(" << quad.ag1 << "), " << "entry(" << quad.ag2 << "), " << quad.result << ")\n" << endl; 32 //cout<<"entry("<<quad.ag1<<"entry("<<quad.op<<quad.ag2<<endl; 33 } 34 char *newtemp() { 35 char *p; 36 char m[12]; 37 p = (char *)malloc(12); 38 k++; 39 _itoa_s(k, m, 10); 40 strcpy(p + 1, m); 41 p[0] = 't'; 42 return (p); 43 } 44 //对字符的扫描 45 void scaner() { 46 for (n = 0; n<8; n++) 47 token[n] = NULL; 48 ch = prog[p++]; 49 while (ch == ' ') { 50 ch = prog[p]; 51 p++; 52 } 53 if ((ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z')) { 54 if ((ch >= 'a'&&ch <= 'c') || (ch >= 'A'&&ch <= 'C')){ 55 m = 0; 56 while ((ch >= '0'&&ch <= '9') || (ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z')) { 57 token[m++] = ch; 58 ch = prog[p++]; 59 } 60 token[m++] = '\0'; 61 p--; 62 syn = 10; 63 for (n = 0; n<6; n++) { 64 if (strcmp(token, rwtab[n]) == 0) { 65 syn = n + 1; 66 break; 67 } 68 } 69 } 70 else 71 cout << "Error!" << endl; 72 } 73 else if ((ch >= '0'&&ch <= '9')) { 74 { 75 sum = 0; 76 while ((ch >= '0'&&ch <= '9')) { 77 sum = sum * 10 + ch - '0'; 78 ch = prog[p++]; 79 } 80 } 81 p--; 82 syn = 11; 83 if (sum>32767) 84 syn = -1; 85 } 86 else switch (ch) 87 { 88 case'<': 89 m = 0; 90 token[m++] = ch; 91 ch = prog[p++]; 92 if (ch == '>') { 93 syn = 21; 94 token[m++] = ch; 95 } 96 else if (ch == '=') 97 { 98 syn = 22; 99 token[m++] = ch; 100 } 101 else { 102 syn = 23; 103 p--; 104 } 105 break; 106 case'>': 107 m = 0; 108 token[m++] = ch; 109 ch = prog[p++]; 110 if (ch == '=') { 111 syn = 24; 112 token[m++] = ch; 113 } 114 else { 115 syn = 20; 116 p--; 117 } 118 break; 119 case':': 120 m = 0; token[m++] = ch; 121 ch = prog[p++]; 122 if (ch == '=') { 123 syn = 18; 124 token[m++] = ch; 125 } 126 else { 127 syn = 17; 128 p--; 129 } 130 break; 131 case'*': 132 syn = 13; 133 token[0] = ch; 134 break; 135 case'/': 136 syn = 14; 137 token[0] = ch; 138 break; 139 case'+': 140 syn = 15; 141 token[0] = ch; 142 break; 143 case'-': 144 syn = 16; 145 token[0] = ch; 146 break; 147 case'=': 148 syn = 25; 149 token[0] = ch; 150 break; 151 case';': 152 syn = 26; 153 token[0] = ch; 154 break; 155 case'(': 156 syn = 27; 157 token[0] = ch; 158 break; 159 case')': 160 syn = 28; 161 token[0] = ch; 162 break; 163 case'#': 164 syn = 0; 165 token[0] = ch; 166 break; 167 default: 168 syn = -1; 169 break; 170 } 171 } 172 int lrparser() 173 { 174 //cout<<" 调用 lrparser"<<endl; 175 int schain = 0; 176 kk = 0; 177 if (syn == 1) { 178 scaner(); 179 schain = yucu(); 180 //cout<<"SYN= "<<syn<<endl; 181 if (syn == 6) { 182 scaner(); 183 if (syn == 0 && (kk == 0)) 184 cout << "success!" << endl; 185 } 186 /* else 187 { 188 if(kk!=1) 189 cout<<"缺 end!"<<endl; 190 kk=1; 191 } */ 192 } 193 else 194 { 195 cout << "Error!" << endl; 196 kk = 1; 197 } 198 return(schain); 199 } 200 int yucu() { // cout<<" 调用 yucu"<<endl; 201 int schain = 0; 202 schain = statement(); 203 while (syn == 26) { 204 scaner(); 205 schain = statement(); 206 } 207 return(schain); 208 } 209 int statement() 210 { 211 //cout<<" 调用 statement"<<endl; 212 char *eplace, *tt; 213 eplace = (char *)malloc(12); 214 tt = (char *)malloc(12); 215 int schain = 0; 216 switch (syn) { 217 case 10: 218 strcpy(tt, token); 219 scaner(); 220 // if(syn==18) { 221 scaner(); 222 strcpy(eplace, expression()); 223 emit(tt, eplace, "", ""); 224 schain = 0; 225 /* } 226 else { cout<<"缺少赋值符 !"<<endl; 227 kk=1; 228 } */ 229 return (schain); 230 break; 231 } 232 return (schain); 233 } 234 char *expression(void) { 235 char *tp, *ep2, *eplace, *tt; 236 tp = (char *)malloc(12); 237 ep2 = (char *)malloc(12); 238 eplace = (char *)malloc(12); 239 tt = (char *)malloc(12); 240 strcpy(eplace, term()); //调用 term 分析产生表达式计算的第一项 eplace 241 while ((syn == 15) || (syn == 16)) { 242 if (syn == 15) 243 strcpy(tt, "+"); 244 else 245 strcpy(tt, "-"); 246 scaner(); 247 strcpy(ep2, term()); //调用 term 分析产生表达式计算的第二项 ep2 248 strcpy(tp, newtemp()); // 调用 newtemp 产生临时变量 tp 存储计算结果 249 emit(tp, eplace, tt, ep2); //生成四元式送入四元式表 250 strcpy(eplace, tp); 251 } 252 return(eplace); 253 } 254 char *term(void) { 255 // cout<<" 调用 term"<<endl; 256 char *tp, *ep2, *eplace, *tt; 257 tp = (char *)malloc(12); 258 ep2 = (char *)malloc(12); 259 eplace = (char *)malloc(12); 260 tt = (char *)malloc(12); 261 strcpy(eplace, factor()); 262 while ((syn == 13) || (syn == 14)) { 263 if (syn == 13)strcpy(tt, "*"); 264 else strcpy(tt, "/"); 265 scaner(); strcpy(ep2, factor()); // 调用 factor 分析产生表达式计算的第二项 ep2 266 strcpy(tp, newtemp()); 267 //调用 newtemp产生临时变量 tp 存储计算结果 emit(tp,eplace,tt,ep2); //生成四元式送入四元式表 268 strcpy(eplace, tp); 269 } 270 return(eplace); 271 } 272 char *factor(void) { 273 char *fplace; 274 fplace = (char *)malloc(12); 275 strcpy(fplace, ""); 276 if (syn == 10) { 277 strcpy(fplace, token); 278 scaner(); 279 } 280 else if (syn == 11) { 281 itoa(sum, fplace, 10); 282 scaner(); 283 } 284 else if (syn == 27) { 285 scaner(); 286 fplace = expression(); //调用 expression分析返回表达式的值 287 if (syn == 28) 288 scaner(); 289 else { 290 cout << "缺)错误 !" << endl; 291 kk = 1; 292 } 293 } 294 else { 295 cout << "缺(错误 !" << endl; 296 kk = 1; 297 } 298 return(fplace); 299 } 300 int main(void) { 301 cout << "这是周博的语义分析器;" << endl; 302 for (int i = 0; i < 10; i++) 303 { 304 cout << "*************"; 305 } 306 cout << endl; 307 p = 0; 308 cout << "请输入一个字符串(以#结束):" << endl; 309 do { 310 cin.get(ch); 311 prog[p++] = ch; 312 } while (ch != '#'); 313 p = 0; 314 scaner(); 315 lrparser(); 316 for (int i = 0; i < 10; i++) 317 { 318 cout << "*************"; 319 } 320 return 0;
实验截图: