// 语法制导翻译器设计示范程序 ----- 算数表达式四元式翻译(递归子程序法) // 要求: // 1. 读懂并运行该程序 ( 输入文件 : in1.exe ; 输出文件 : out1.exe ) ; // 2. 对不同源表达式反复运行,考查错误处理和输出的四元式序列。 // 3. 把该程序拷贝一副本,在该副本上进行修改和调试; // 4. 实验报告内容:(1) 写出表达式的属性翻译文法,画出递归子程序框图; // (2) 输出结果文件原样照抄( 四元式序列和错误信息至少各一条!) // (3) 讨论对该程序运行、理解和修改调试情况。 // 注:输入文件中的源表达式(字母:表示变量,数字:表示常数。)
#include "stdafx.h" #include "string.h" #include "stdio.h"
char word; //当前单词(word) char IT[20]; int CT[20]; int num_IT=0,num_CT=0; // 两个表中各元素个数的初值 int i_temp=1; // 临时变量序号 int err=0,erp; //错误编码与错误位置号 struct TOKEN //单词的 TOKEN 结构 { char t; int i; } ; struct TOKEN w_token; //单词的TOKEN(w_token) struct TOKEN sem[10]; //语义栈(sem) int i_sem;
struct QT //四元式结构 { char w; struct TOKEN w_token1; struct TOKEN w_token2; struct TOKEN temp; } ;
char exp[50]; //源算术表达式区 int i=0; //源单词序号
struct QT qt[30]; //四元式区 int q=0; //四元式序号
int insID(char word); //查填标识符表函数 int insCS(int num) ; //查填常数表函数 int E(); int T(); int F();
void next(); //读下一个单词 void newt(); //申请一个临时变量函数 void quat(char); //生成四元式函数
int main() //主函数 { FILE *fp; fp=fopen("in1.txt","r"); while (!feof(fp)) { fgets(exp,100,fp); do { next(); // 读一个单词 E(); if ((err!=0)||(word=='#')) break; else { err=3; erp=i-2; break;} } while ((word!='#')||(err!=0)); } { //从此开始输出结果 FILE *fp1; fp1=fopen("out1.txt","w"); rewind(fp1); fprintf(fp1,"\n"); fprintf(fp1,"\n * 源表达式清单:"); fprintf(fp1," %s ",exp); fprintf(fp1,"\n\n"); fprintf(fp1," * 变量表:"); for (i=0;i<num_IT;i++) fprintf(fp1," %c ",IT[i]); fprintf(fp1,"\n\n"); fprintf(fp1," * 常数表:"); for (i=0;i<num_CT;i++) fprintf(fp1," %d ",CT[i]); fprintf(fp1,"\n\n"); fprintf(fp1,"\n * 四元式序列:\n"); for (i=0;i<q;i++) { fprintf(fp1," (%d) ",i+1); fprintf(fp1," ( %c",qt[i].w); fprintf(fp1," , %c.%d",qt[i].w_token1.t,qt[i].w_token1.i); fprintf(fp1," , %c.%d",qt[i].w_token2.t,qt[i].w_token2.i); fprintf(fp1," , %c.%d )\n",qt[i].temp.t,qt[i].temp.i); } fclose(fp1); fclose(fp); printf("\n\n"); printf("\n * 源表达式清单:"); printf(" %s \n",exp); printf("\n * 错误信息:"); if (err==1) { printf("\n\n 缺右括号(或 缺运算符) ! "); printf(" 位置号为:%d\n", erp); } else if (err==2) printf("\n\n 缺运算对象 ! 位置号为:%d\n ",erp); else if (err==3) printf("\n\n 缺结束符 # ! 位置号为:%d \n ",erp); printf("\n\n 请修改输入文件 in1.txt ! \n\n"); printf(" 输出结果在文件 out1.txt 中! \n\n"); return 0; } } int E() { char w1; //算符(+\-)暂存变量 T(); if (err!=0) return 0; while ( word=='+' || word=='-') { w1=word; //暂存运算符(+|-) next(); //next(w) T(); if (err!=0) return 0; quat(w1); } return 1; } int T() { char w2; //算符(*|/)暂存变量 F(); if (err!=0) return 0; while ( word=='*' || word=='/') { w2=word; //暂存运算符(*|/) next(); //读下一个单词 F(); if (err!=0) return 0; quat(w2); } return 1; } int F() { if ( word=='(') { next(); //next(w) E(); if (err!=0) return 0; else if ( word!=')') { err=1; erp=i-3;return 0;} } else if ((word>='a' && word<='z')||(word>='0' && word<='9')) { sem[++i_sem]=w_token; //push(SEM,w) } else if (err!=0) return 0; else { err=2; erp=i-3; return 0;} next(); //next(w) return 1; }
void next() { while (exp[i]==' ') i++; // 滤空格 if (exp[i]!='\0') { word=exp[i++]; // 读取一个有效单词 if (word>='a' && word<='z') { w_token.t='i'; w_token.i=insID(word) ; } //取变量的TOKEN if (word>='0' && word<='9') { w_token.t='c'; w_token.i=insCS(word-48) ; } // 取常的TOKEN } //else { err=2;erp=i+1;} }
void newt() { w_token.t='t'; w_token.i=i_temp++; }
void quat(char ww) { newt(); qt[q].w=ww; //QT[q]:=(ww,SEM[s-1],SEM[s],temp); qt[q].w_token1=sem[i_sem-1]; qt[q].w_token2=sem[i_sem]; qt[q].temp=w_token; i_sem--; //pop(SEM); i_sem--; //pop(SEM); sem[++i_sem]=w_token; //push(SEM,temp); q++; } int insID(char word) //查填标识符表函数 { int i; for (i=0;i<num_IT;i++) if (word==IT[i]) return i+1; IT[i]=word; num_IT++; return i+1; } int insCS(int num) //查填常数表函数 { int i; for (i=0;i<num_CT;i++) if (num==CT[i]) return i+1; CT[i]=num; num_CT++; return i+1; } 就是按照要求写一篇试验报告,希望有大人指点
----------------解决方案--------------------------------------------------------